github.com/MikyChow/arbitrum-go-ethereum@v0.0.0-20230306102812-078da49636de/core/vm/instructions.go (about) 1 // Copyright 2015 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package vm 18 19 import ( 20 "math/big" 21 "sync/atomic" 22 23 "github.com/MikyChow/arbitrum-go-ethereum/common" 24 "github.com/MikyChow/arbitrum-go-ethereum/core/types" 25 "github.com/MikyChow/arbitrum-go-ethereum/params" 26 "github.com/holiman/uint256" 27 "golang.org/x/crypto/sha3" 28 ) 29 30 func opAdd(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 31 x, y := scope.Stack.pop(), scope.Stack.peek() 32 y.Add(&x, y) 33 return nil, nil 34 } 35 36 func opSub(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 37 x, y := scope.Stack.pop(), scope.Stack.peek() 38 y.Sub(&x, y) 39 return nil, nil 40 } 41 42 func opMul(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 43 x, y := scope.Stack.pop(), scope.Stack.peek() 44 y.Mul(&x, y) 45 return nil, nil 46 } 47 48 func opDiv(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 49 x, y := scope.Stack.pop(), scope.Stack.peek() 50 y.Div(&x, y) 51 return nil, nil 52 } 53 54 func opSdiv(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 55 x, y := scope.Stack.pop(), scope.Stack.peek() 56 y.SDiv(&x, y) 57 return nil, nil 58 } 59 60 func opMod(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 61 x, y := scope.Stack.pop(), scope.Stack.peek() 62 y.Mod(&x, y) 63 return nil, nil 64 } 65 66 func opSmod(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 67 x, y := scope.Stack.pop(), scope.Stack.peek() 68 y.SMod(&x, y) 69 return nil, nil 70 } 71 72 func opExp(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 73 base, exponent := scope.Stack.pop(), scope.Stack.peek() 74 exponent.Exp(&base, exponent) 75 return nil, nil 76 } 77 78 func opSignExtend(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 79 back, num := scope.Stack.pop(), scope.Stack.peek() 80 num.ExtendSign(num, &back) 81 return nil, nil 82 } 83 84 func opNot(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 85 x := scope.Stack.peek() 86 x.Not(x) 87 return nil, nil 88 } 89 90 func opLt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 91 x, y := scope.Stack.pop(), scope.Stack.peek() 92 if x.Lt(y) { 93 y.SetOne() 94 } else { 95 y.Clear() 96 } 97 return nil, nil 98 } 99 100 func opGt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 101 x, y := scope.Stack.pop(), scope.Stack.peek() 102 if x.Gt(y) { 103 y.SetOne() 104 } else { 105 y.Clear() 106 } 107 return nil, nil 108 } 109 110 func opSlt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 111 x, y := scope.Stack.pop(), scope.Stack.peek() 112 if x.Slt(y) { 113 y.SetOne() 114 } else { 115 y.Clear() 116 } 117 return nil, nil 118 } 119 120 func opSgt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 121 x, y := scope.Stack.pop(), scope.Stack.peek() 122 if x.Sgt(y) { 123 y.SetOne() 124 } else { 125 y.Clear() 126 } 127 return nil, nil 128 } 129 130 func opEq(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 131 x, y := scope.Stack.pop(), scope.Stack.peek() 132 if x.Eq(y) { 133 y.SetOne() 134 } else { 135 y.Clear() 136 } 137 return nil, nil 138 } 139 140 func opIszero(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 141 x := scope.Stack.peek() 142 if x.IsZero() { 143 x.SetOne() 144 } else { 145 x.Clear() 146 } 147 return nil, nil 148 } 149 150 func opAnd(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 151 x, y := scope.Stack.pop(), scope.Stack.peek() 152 y.And(&x, y) 153 return nil, nil 154 } 155 156 func opOr(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 157 x, y := scope.Stack.pop(), scope.Stack.peek() 158 y.Or(&x, y) 159 return nil, nil 160 } 161 162 func opXor(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 163 x, y := scope.Stack.pop(), scope.Stack.peek() 164 y.Xor(&x, y) 165 return nil, nil 166 } 167 168 func opByte(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 169 th, val := scope.Stack.pop(), scope.Stack.peek() 170 val.Byte(&th) 171 return nil, nil 172 } 173 174 func opAddmod(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 175 x, y, z := scope.Stack.pop(), scope.Stack.pop(), scope.Stack.peek() 176 if z.IsZero() { 177 z.Clear() 178 } else { 179 z.AddMod(&x, &y, z) 180 } 181 return nil, nil 182 } 183 184 func opMulmod(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 185 x, y, z := scope.Stack.pop(), scope.Stack.pop(), scope.Stack.peek() 186 z.MulMod(&x, &y, z) 187 return nil, nil 188 } 189 190 // opSHL implements Shift Left 191 // The SHL instruction (shift left) pops 2 values from the stack, first arg1 and then arg2, 192 // and pushes on the stack arg2 shifted to the left by arg1 number of bits. 193 func opSHL(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 194 // Note, second operand is left in the stack; accumulate result into it, and no need to push it afterwards 195 shift, value := scope.Stack.pop(), scope.Stack.peek() 196 if shift.LtUint64(256) { 197 value.Lsh(value, uint(shift.Uint64())) 198 } else { 199 value.Clear() 200 } 201 return nil, nil 202 } 203 204 // opSHR implements Logical Shift Right 205 // The SHR instruction (logical shift right) pops 2 values from the stack, first arg1 and then arg2, 206 // and pushes on the stack arg2 shifted to the right by arg1 number of bits with zero fill. 207 func opSHR(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 208 // Note, second operand is left in the stack; accumulate result into it, and no need to push it afterwards 209 shift, value := scope.Stack.pop(), scope.Stack.peek() 210 if shift.LtUint64(256) { 211 value.Rsh(value, uint(shift.Uint64())) 212 } else { 213 value.Clear() 214 } 215 return nil, nil 216 } 217 218 // opSAR implements Arithmetic Shift Right 219 // The SAR instruction (arithmetic shift right) pops 2 values from the stack, first arg1 and then arg2, 220 // and pushes on the stack arg2 shifted to the right by arg1 number of bits with sign extension. 221 func opSAR(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 222 shift, value := scope.Stack.pop(), scope.Stack.peek() 223 if shift.GtUint64(256) { 224 if value.Sign() >= 0 { 225 value.Clear() 226 } else { 227 // Max negative shift: all bits set 228 value.SetAllOne() 229 } 230 return nil, nil 231 } 232 n := uint(shift.Uint64()) 233 value.SRsh(value, n) 234 return nil, nil 235 } 236 237 func opKeccak256(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 238 offset, size := scope.Stack.pop(), scope.Stack.peek() 239 data := scope.Memory.GetPtr(int64(offset.Uint64()), int64(size.Uint64())) 240 241 if interpreter.hasher == nil { 242 interpreter.hasher = sha3.NewLegacyKeccak256().(keccakState) 243 } else { 244 interpreter.hasher.Reset() 245 } 246 interpreter.hasher.Write(data) 247 interpreter.hasher.Read(interpreter.hasherBuf[:]) 248 249 evm := interpreter.evm 250 if evm.Config.EnablePreimageRecording { 251 evm.StateDB.AddPreimage(interpreter.hasherBuf, data) 252 } 253 254 size.SetBytes(interpreter.hasherBuf[:]) 255 return nil, nil 256 } 257 func opAddress(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 258 scope.Stack.push(new(uint256.Int).SetBytes(scope.Contract.Address().Bytes())) 259 return nil, nil 260 } 261 262 func opBalance(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 263 slot := scope.Stack.peek() 264 address := common.Address(slot.Bytes20()) 265 slot.SetFromBig(interpreter.evm.StateDB.GetBalance(address)) 266 return nil, nil 267 } 268 269 func opOrigin(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 270 scope.Stack.push(new(uint256.Int).SetBytes(interpreter.evm.Origin.Bytes())) 271 return nil, nil 272 } 273 func opCaller(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 274 scope.Stack.push(new(uint256.Int).SetBytes(scope.Contract.Caller().Bytes())) 275 return nil, nil 276 } 277 278 func opCallValue(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 279 v, _ := uint256.FromBig(scope.Contract.value) 280 scope.Stack.push(v) 281 return nil, nil 282 } 283 284 func opCallDataLoad(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 285 x := scope.Stack.peek() 286 if offset, overflow := x.Uint64WithOverflow(); !overflow { 287 data := getData(scope.Contract.Input, offset, 32) 288 x.SetBytes(data) 289 } else { 290 x.Clear() 291 } 292 return nil, nil 293 } 294 295 func opCallDataSize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 296 scope.Stack.push(new(uint256.Int).SetUint64(uint64(len(scope.Contract.Input)))) 297 return nil, nil 298 } 299 300 func opCallDataCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 301 var ( 302 memOffset = scope.Stack.pop() 303 dataOffset = scope.Stack.pop() 304 length = scope.Stack.pop() 305 ) 306 dataOffset64, overflow := dataOffset.Uint64WithOverflow() 307 if overflow { 308 dataOffset64 = 0xffffffffffffffff 309 } 310 // These values are checked for overflow during gas cost calculation 311 memOffset64 := memOffset.Uint64() 312 length64 := length.Uint64() 313 scope.Memory.Set(memOffset64, length64, getData(scope.Contract.Input, dataOffset64, length64)) 314 315 return nil, nil 316 } 317 318 func opReturnDataSize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 319 scope.Stack.push(new(uint256.Int).SetUint64(uint64(len(interpreter.returnData)))) 320 return nil, nil 321 } 322 323 func opReturnDataCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 324 var ( 325 memOffset = scope.Stack.pop() 326 dataOffset = scope.Stack.pop() 327 length = scope.Stack.pop() 328 ) 329 330 offset64, overflow := dataOffset.Uint64WithOverflow() 331 if overflow { 332 return nil, ErrReturnDataOutOfBounds 333 } 334 // we can reuse dataOffset now (aliasing it for clarity) 335 var end = dataOffset 336 end.Add(&dataOffset, &length) 337 end64, overflow := end.Uint64WithOverflow() 338 if overflow || uint64(len(interpreter.returnData)) < end64 { 339 return nil, ErrReturnDataOutOfBounds 340 } 341 scope.Memory.Set(memOffset.Uint64(), length.Uint64(), interpreter.returnData[offset64:end64]) 342 return nil, nil 343 } 344 345 func opExtCodeSize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 346 slot := scope.Stack.peek() 347 slot.SetUint64(uint64(interpreter.evm.StateDB.GetCodeSize(slot.Bytes20()))) 348 return nil, nil 349 } 350 351 func opCodeSize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 352 l := new(uint256.Int) 353 l.SetUint64(uint64(len(scope.Contract.Code))) 354 scope.Stack.push(l) 355 return nil, nil 356 } 357 358 func opCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 359 var ( 360 memOffset = scope.Stack.pop() 361 codeOffset = scope.Stack.pop() 362 length = scope.Stack.pop() 363 ) 364 uint64CodeOffset, overflow := codeOffset.Uint64WithOverflow() 365 if overflow { 366 uint64CodeOffset = 0xffffffffffffffff 367 } 368 codeCopy := getData(scope.Contract.Code, uint64CodeOffset, length.Uint64()) 369 scope.Memory.Set(memOffset.Uint64(), length.Uint64(), codeCopy) 370 371 return nil, nil 372 } 373 374 func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 375 var ( 376 stack = scope.Stack 377 a = stack.pop() 378 memOffset = stack.pop() 379 codeOffset = stack.pop() 380 length = stack.pop() 381 ) 382 uint64CodeOffset, overflow := codeOffset.Uint64WithOverflow() 383 if overflow { 384 uint64CodeOffset = 0xffffffffffffffff 385 } 386 addr := common.Address(a.Bytes20()) 387 codeCopy := getData(interpreter.evm.StateDB.GetCode(addr), uint64CodeOffset, length.Uint64()) 388 scope.Memory.Set(memOffset.Uint64(), length.Uint64(), codeCopy) 389 390 return nil, nil 391 } 392 393 // opExtCodeHash returns the code hash of a specified account. 394 // There are several cases when the function is called, while we can relay everything 395 // to `state.GetCodeHash` function to ensure the correctness. 396 // 397 // (1) Caller tries to get the code hash of a normal contract account, state 398 // 399 // should return the relative code hash and set it as the result. 400 // 401 // (2) Caller tries to get the code hash of a non-existent account, state should 402 // 403 // return common.Hash{} and zero will be set as the result. 404 // 405 // (3) Caller tries to get the code hash for an account without contract code, 406 // 407 // state should return emptyCodeHash(0xc5d246...) as the result. 408 // 409 // (4) Caller tries to get the code hash of a precompiled account, the result 410 // 411 // should be zero or emptyCodeHash. 412 // 413 // It is worth noting that in order to avoid unnecessary create and clean, 414 // all precompile accounts on mainnet have been transferred 1 wei, so the return 415 // here should be emptyCodeHash. 416 // If the precompile account is not transferred any amount on a private or 417 // customized chain, the return value will be zero. 418 // 419 // (5) Caller tries to get the code hash for an account which is marked as suicided 420 // 421 // in the current transaction, the code hash of this account should be returned. 422 // 423 // (6) Caller tries to get the code hash for an account which is marked as deleted, 424 // 425 // this account should be regarded as a non-existent account and zero should be returned. 426 func opExtCodeHash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 427 slot := scope.Stack.peek() 428 address := common.Address(slot.Bytes20()) 429 if interpreter.evm.StateDB.Empty(address) { 430 slot.Clear() 431 } else { 432 slot.SetBytes(interpreter.evm.StateDB.GetCodeHash(address).Bytes()) 433 } 434 return nil, nil 435 } 436 437 func opGasprice(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 438 439 // Arbitrum: provide an opportunity to remove the tip from the gas price 440 gasPrice := interpreter.evm.ProcessingHook.GasPriceOp(interpreter.evm) 441 442 v, _ := uint256.FromBig(gasPrice) 443 scope.Stack.push(v) 444 return nil, nil 445 } 446 447 func opBlockhash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 448 num := scope.Stack.peek() 449 num64, overflow := num.Uint64WithOverflow() 450 if overflow { 451 num.Clear() 452 return nil, nil 453 } 454 upper, err := interpreter.evm.ProcessingHook.L1BlockNumber(interpreter.evm.Context) 455 if err != nil { 456 return nil, err 457 } 458 var lower uint64 459 if upper < 257 { 460 lower = 0 461 } else { 462 lower = upper - 256 463 } 464 if num64 >= lower && num64 < upper { 465 h, err := interpreter.evm.ProcessingHook.L1BlockHash(interpreter.evm.Context, num64) 466 if err != nil { 467 return nil, err 468 } 469 num.SetBytes(h.Bytes()) 470 } else { 471 num.Clear() 472 } 473 return nil, nil 474 } 475 476 func opCoinbase(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 477 scope.Stack.push(new(uint256.Int).SetBytes(interpreter.evm.Context.Coinbase.Bytes())) 478 return nil, nil 479 } 480 481 func opTimestamp(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 482 v, _ := uint256.FromBig(interpreter.evm.Context.Time) 483 scope.Stack.push(v) 484 return nil, nil 485 } 486 487 func opNumber(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 488 bnum, err := interpreter.evm.ProcessingHook.L1BlockNumber(interpreter.evm.Context) 489 if err != nil { 490 return nil, err 491 } 492 v, _ := uint256.FromBig(new(big.Int).SetUint64(bnum)) 493 scope.Stack.push(v) 494 return nil, nil 495 } 496 497 func opDifficulty(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 498 v, _ := uint256.FromBig(interpreter.evm.Context.Difficulty) 499 scope.Stack.push(v) 500 return nil, nil 501 } 502 503 func opRandom(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 504 v := new(uint256.Int).SetBytes(interpreter.evm.Context.Random.Bytes()) 505 scope.Stack.push(v) 506 return nil, nil 507 } 508 509 func opGasLimit(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 510 scope.Stack.push(new(uint256.Int).SetUint64(interpreter.evm.Context.GasLimit)) 511 return nil, nil 512 } 513 514 func opPop(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 515 scope.Stack.pop() 516 return nil, nil 517 } 518 519 func opMload(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 520 v := scope.Stack.peek() 521 offset := int64(v.Uint64()) 522 v.SetBytes(scope.Memory.GetPtr(offset, 32)) 523 return nil, nil 524 } 525 526 func opMstore(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 527 // pop value of the stack 528 mStart, val := scope.Stack.pop(), scope.Stack.pop() 529 scope.Memory.Set32(mStart.Uint64(), &val) 530 return nil, nil 531 } 532 533 func opMstore8(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 534 off, val := scope.Stack.pop(), scope.Stack.pop() 535 scope.Memory.store[off.Uint64()] = byte(val.Uint64()) 536 return nil, nil 537 } 538 539 func opSload(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 540 loc := scope.Stack.peek() 541 hash := common.Hash(loc.Bytes32()) 542 val := interpreter.evm.StateDB.GetState(scope.Contract.Address(), hash) 543 loc.SetBytes(val.Bytes()) 544 return nil, nil 545 } 546 547 func opSstore(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 548 if interpreter.readOnly { 549 return nil, ErrWriteProtection 550 } 551 loc := scope.Stack.pop() 552 val := scope.Stack.pop() 553 interpreter.evm.StateDB.SetState(scope.Contract.Address(), 554 loc.Bytes32(), val.Bytes32()) 555 return nil, nil 556 } 557 558 func opJump(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 559 if atomic.LoadInt32(&interpreter.evm.abort) != 0 { 560 return nil, errStopToken 561 } 562 pos := scope.Stack.pop() 563 if !scope.Contract.validJumpdest(&pos) { 564 return nil, ErrInvalidJump 565 } 566 *pc = pos.Uint64() - 1 // pc will be increased by the interpreter loop 567 return nil, nil 568 } 569 570 func opJumpi(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 571 if atomic.LoadInt32(&interpreter.evm.abort) != 0 { 572 return nil, errStopToken 573 } 574 pos, cond := scope.Stack.pop(), scope.Stack.pop() 575 if !cond.IsZero() { 576 if !scope.Contract.validJumpdest(&pos) { 577 return nil, ErrInvalidJump 578 } 579 *pc = pos.Uint64() - 1 // pc will be increased by the interpreter loop 580 } 581 return nil, nil 582 } 583 584 func opJumpdest(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 585 return nil, nil 586 } 587 588 func opPc(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 589 scope.Stack.push(new(uint256.Int).SetUint64(*pc)) 590 return nil, nil 591 } 592 593 func opMsize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 594 scope.Stack.push(new(uint256.Int).SetUint64(uint64(scope.Memory.Len()))) 595 return nil, nil 596 } 597 598 func opGas(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 599 scope.Stack.push(new(uint256.Int).SetUint64(scope.Contract.Gas)) 600 return nil, nil 601 } 602 603 func opCreate(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 604 if interpreter.readOnly { 605 return nil, ErrWriteProtection 606 } 607 var ( 608 value = scope.Stack.pop() 609 offset, size = scope.Stack.pop(), scope.Stack.pop() 610 input = scope.Memory.GetCopy(int64(offset.Uint64()), int64(size.Uint64())) 611 gas = scope.Contract.Gas 612 ) 613 if interpreter.evm.chainRules.IsEIP150 { 614 gas -= gas / 64 615 } 616 // reuse size int for stackvalue 617 stackvalue := size 618 619 scope.Contract.UseGas(gas) 620 //TODO: use uint256.Int instead of converting with toBig() 621 var bigVal = big0 622 if !value.IsZero() { 623 bigVal = value.ToBig() 624 } 625 626 res, addr, returnGas, suberr := interpreter.evm.Create(scope.Contract, input, gas, bigVal) 627 // Push item on the stack based on the returned error. If the ruleset is 628 // homestead we must check for CodeStoreOutOfGasError (homestead only 629 // rule) and treat as an error, if the ruleset is frontier we must 630 // ignore this error and pretend the operation was successful. 631 if interpreter.evm.chainRules.IsHomestead && suberr == ErrCodeStoreOutOfGas { 632 stackvalue.Clear() 633 } else if suberr != nil && suberr != ErrCodeStoreOutOfGas { 634 stackvalue.Clear() 635 } else { 636 stackvalue.SetBytes(addr.Bytes()) 637 } 638 scope.Stack.push(&stackvalue) 639 scope.Contract.Gas += returnGas 640 641 if suberr == ErrExecutionReverted { 642 interpreter.returnData = res // set REVERT data to return data buffer 643 return res, nil 644 } 645 interpreter.returnData = nil // clear dirty return data buffer 646 return nil, nil 647 } 648 649 func opCreate2(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 650 if interpreter.readOnly { 651 return nil, ErrWriteProtection 652 } 653 var ( 654 endowment = scope.Stack.pop() 655 offset, size = scope.Stack.pop(), scope.Stack.pop() 656 salt = scope.Stack.pop() 657 input = scope.Memory.GetCopy(int64(offset.Uint64()), int64(size.Uint64())) 658 gas = scope.Contract.Gas 659 ) 660 661 // Apply EIP150 662 gas -= gas / 64 663 scope.Contract.UseGas(gas) 664 // reuse size int for stackvalue 665 stackvalue := size 666 //TODO: use uint256.Int instead of converting with toBig() 667 bigEndowment := big0 668 if !endowment.IsZero() { 669 bigEndowment = endowment.ToBig() 670 } 671 res, addr, returnGas, suberr := interpreter.evm.Create2(scope.Contract, input, gas, 672 bigEndowment, &salt) 673 // Push item on the stack based on the returned error. 674 if suberr != nil { 675 stackvalue.Clear() 676 } else { 677 stackvalue.SetBytes(addr.Bytes()) 678 } 679 scope.Stack.push(&stackvalue) 680 scope.Contract.Gas += returnGas 681 682 if suberr == ErrExecutionReverted { 683 interpreter.returnData = res // set REVERT data to return data buffer 684 return res, nil 685 } 686 interpreter.returnData = nil // clear dirty return data buffer 687 return nil, nil 688 } 689 690 func opCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 691 stack := scope.Stack 692 // Pop gas. The actual gas in interpreter.evm.callGasTemp. 693 // We can use this as a temporary value 694 temp := stack.pop() 695 gas := interpreter.evm.callGasTemp 696 // Pop other call parameters. 697 addr, value, inOffset, inSize, retOffset, retSize := stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop() 698 toAddr := common.Address(addr.Bytes20()) 699 // Get the arguments from the memory. 700 args := scope.Memory.GetPtr(int64(inOffset.Uint64()), int64(inSize.Uint64())) 701 702 if interpreter.readOnly && !value.IsZero() { 703 return nil, ErrWriteProtection 704 } 705 var bigVal = big0 706 //TODO: use uint256.Int instead of converting with toBig() 707 // By using big0 here, we save an alloc for the most common case (non-ether-transferring contract calls), 708 // but it would make more sense to extend the usage of uint256.Int 709 if !value.IsZero() { 710 gas += params.CallStipend 711 bigVal = value.ToBig() 712 } 713 714 ret, returnGas, err := interpreter.evm.Call(scope.Contract, toAddr, args, gas, bigVal) 715 716 if err != nil { 717 temp.Clear() 718 } else { 719 temp.SetOne() 720 } 721 stack.push(&temp) 722 if err == nil || err == ErrExecutionReverted { 723 ret = common.CopyBytes(ret) 724 scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret) 725 } 726 scope.Contract.Gas += returnGas 727 728 interpreter.returnData = ret 729 return ret, nil 730 } 731 732 func opCallCode(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 733 // Pop gas. The actual gas is in interpreter.evm.callGasTemp. 734 stack := scope.Stack 735 // We use it as a temporary value 736 temp := stack.pop() 737 gas := interpreter.evm.callGasTemp 738 // Pop other call parameters. 739 addr, value, inOffset, inSize, retOffset, retSize := stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop() 740 toAddr := common.Address(addr.Bytes20()) 741 // Get arguments from the memory. 742 args := scope.Memory.GetPtr(int64(inOffset.Uint64()), int64(inSize.Uint64())) 743 744 //TODO: use uint256.Int instead of converting with toBig() 745 var bigVal = big0 746 if !value.IsZero() { 747 gas += params.CallStipend 748 bigVal = value.ToBig() 749 } 750 751 ret, returnGas, err := interpreter.evm.CallCode(scope.Contract, toAddr, args, gas, bigVal) 752 if err != nil { 753 temp.Clear() 754 } else { 755 temp.SetOne() 756 } 757 stack.push(&temp) 758 if err == nil || err == ErrExecutionReverted { 759 ret = common.CopyBytes(ret) 760 scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret) 761 } 762 scope.Contract.Gas += returnGas 763 764 interpreter.returnData = ret 765 return ret, nil 766 } 767 768 func opDelegateCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 769 stack := scope.Stack 770 // Pop gas. The actual gas is in interpreter.evm.callGasTemp. 771 // We use it as a temporary value 772 temp := stack.pop() 773 gas := interpreter.evm.callGasTemp 774 // Pop other call parameters. 775 addr, inOffset, inSize, retOffset, retSize := stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop() 776 toAddr := common.Address(addr.Bytes20()) 777 // Get arguments from the memory. 778 args := scope.Memory.GetPtr(int64(inOffset.Uint64()), int64(inSize.Uint64())) 779 780 ret, returnGas, err := interpreter.evm.DelegateCall(scope.Contract, toAddr, args, gas) 781 if err != nil { 782 temp.Clear() 783 } else { 784 temp.SetOne() 785 } 786 stack.push(&temp) 787 if err == nil || err == ErrExecutionReverted { 788 ret = common.CopyBytes(ret) 789 scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret) 790 } 791 scope.Contract.Gas += returnGas 792 793 interpreter.returnData = ret 794 return ret, nil 795 } 796 797 func opStaticCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 798 // Pop gas. The actual gas is in interpreter.evm.callGasTemp. 799 stack := scope.Stack 800 // We use it as a temporary value 801 temp := stack.pop() 802 gas := interpreter.evm.callGasTemp 803 // Pop other call parameters. 804 addr, inOffset, inSize, retOffset, retSize := stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop() 805 toAddr := common.Address(addr.Bytes20()) 806 // Get arguments from the memory. 807 args := scope.Memory.GetPtr(int64(inOffset.Uint64()), int64(inSize.Uint64())) 808 809 ret, returnGas, err := interpreter.evm.StaticCall(scope.Contract, toAddr, args, gas) 810 if err != nil { 811 temp.Clear() 812 } else { 813 temp.SetOne() 814 } 815 stack.push(&temp) 816 if err == nil || err == ErrExecutionReverted { 817 ret = common.CopyBytes(ret) 818 scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret) 819 } 820 scope.Contract.Gas += returnGas 821 822 interpreter.returnData = ret 823 return ret, nil 824 } 825 826 func opReturn(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 827 offset, size := scope.Stack.pop(), scope.Stack.pop() 828 ret := scope.Memory.GetPtr(int64(offset.Uint64()), int64(size.Uint64())) 829 830 return ret, errStopToken 831 } 832 833 func opRevert(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 834 offset, size := scope.Stack.pop(), scope.Stack.pop() 835 ret := scope.Memory.GetPtr(int64(offset.Uint64()), int64(size.Uint64())) 836 837 interpreter.returnData = ret 838 return ret, ErrExecutionReverted 839 } 840 841 func opUndefined(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 842 return nil, &ErrInvalidOpCode{opcode: OpCode(scope.Contract.Code[*pc])} 843 } 844 845 func opStop(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 846 return nil, errStopToken 847 } 848 849 func opSelfdestruct(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 850 if interpreter.readOnly { 851 return nil, ErrWriteProtection 852 } 853 beneficiary := scope.Stack.pop() 854 balance := interpreter.evm.StateDB.GetBalance(scope.Contract.Address()) 855 interpreter.evm.StateDB.AddBalance(beneficiary.Bytes20(), balance) 856 interpreter.evm.StateDB.Suicide(scope.Contract.Address()) 857 if beneficiary.Bytes20() == scope.Contract.Address() { 858 // Arbitrum: calling selfdestruct(this) burns the balance 859 interpreter.evm.StateDB.ExpectBalanceBurn(balance) 860 } 861 if interpreter.cfg.Debug { 862 interpreter.cfg.Tracer.CaptureEnter(SELFDESTRUCT, scope.Contract.Address(), beneficiary.Bytes20(), []byte{}, 0, balance) 863 interpreter.cfg.Tracer.CaptureExit([]byte{}, 0, nil) 864 } 865 return nil, errStopToken 866 } 867 868 // following functions are used by the instruction jump table 869 870 // make log instruction function 871 func makeLog(size int) executionFunc { 872 return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 873 if interpreter.readOnly { 874 return nil, ErrWriteProtection 875 } 876 topics := make([]common.Hash, size) 877 stack := scope.Stack 878 mStart, mSize := stack.pop(), stack.pop() 879 for i := 0; i < size; i++ { 880 addr := stack.pop() 881 topics[i] = addr.Bytes32() 882 } 883 884 d := scope.Memory.GetCopy(int64(mStart.Uint64()), int64(mSize.Uint64())) 885 interpreter.evm.StateDB.AddLog(&types.Log{ 886 Address: scope.Contract.Address(), 887 Topics: topics, 888 Data: d, 889 // This is a non-consensus field, but assigned here because 890 // core/state doesn't know the current block number. 891 BlockNumber: interpreter.evm.Context.BlockNumber.Uint64(), 892 }) 893 894 return nil, nil 895 } 896 } 897 898 // opPush1 is a specialized version of pushN 899 func opPush1(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 900 var ( 901 codeLen = uint64(len(scope.Contract.Code)) 902 integer = new(uint256.Int) 903 ) 904 *pc += 1 905 if *pc < codeLen { 906 scope.Stack.push(integer.SetUint64(uint64(scope.Contract.Code[*pc]))) 907 } else { 908 scope.Stack.push(integer.Clear()) 909 } 910 return nil, nil 911 } 912 913 // make push instruction function 914 func makePush(size uint64, pushByteSize int) executionFunc { 915 return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 916 codeLen := len(scope.Contract.Code) 917 918 startMin := codeLen 919 if int(*pc+1) < startMin { 920 startMin = int(*pc + 1) 921 } 922 923 endMin := codeLen 924 if startMin+pushByteSize < endMin { 925 endMin = startMin + pushByteSize 926 } 927 928 integer := new(uint256.Int) 929 scope.Stack.push(integer.SetBytes(common.RightPadBytes( 930 scope.Contract.Code[startMin:endMin], pushByteSize))) 931 932 *pc += size 933 return nil, nil 934 } 935 } 936 937 // make dup instruction function 938 func makeDup(size int64) executionFunc { 939 return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 940 scope.Stack.dup(int(size)) 941 return nil, nil 942 } 943 } 944 945 // make swap instruction function 946 func makeSwap(size int64) executionFunc { 947 // switch n + 1 otherwise n would be swapped with n 948 size++ 949 return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { 950 scope.Stack.swap(int(size)) 951 return nil, nil 952 } 953 }