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