github.com/ylsgit/go-ethereum@v1.6.5/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 "fmt" 21 "math/big" 22 23 "github.com/ethereum/go-ethereum/common" 24 "github.com/ethereum/go-ethereum/common/math" 25 "github.com/ethereum/go-ethereum/core/types" 26 "github.com/ethereum/go-ethereum/crypto" 27 "github.com/ethereum/go-ethereum/params" 28 ) 29 30 var ( 31 bigZero = new(big.Int) 32 ) 33 34 func opAdd(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 35 x, y := stack.pop(), stack.pop() 36 stack.push(math.U256(x.Add(x, y))) 37 38 evm.interpreter.intPool.put(y) 39 40 return nil, nil 41 } 42 43 func opSub(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 44 x, y := stack.pop(), stack.pop() 45 stack.push(math.U256(x.Sub(x, y))) 46 47 evm.interpreter.intPool.put(y) 48 49 return nil, nil 50 } 51 52 func opMul(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 53 x, y := stack.pop(), stack.pop() 54 stack.push(math.U256(x.Mul(x, y))) 55 56 evm.interpreter.intPool.put(y) 57 58 return nil, nil 59 } 60 61 func opDiv(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 62 x, y := stack.pop(), stack.pop() 63 if y.Sign() != 0 { 64 stack.push(math.U256(x.Div(x, y))) 65 } else { 66 stack.push(new(big.Int)) 67 } 68 69 evm.interpreter.intPool.put(y) 70 71 return nil, nil 72 } 73 74 func opSdiv(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 75 x, y := math.S256(stack.pop()), math.S256(stack.pop()) 76 if y.Sign() == 0 { 77 stack.push(new(big.Int)) 78 return nil, nil 79 } else { 80 n := new(big.Int) 81 if evm.interpreter.intPool.get().Mul(x, y).Sign() < 0 { 82 n.SetInt64(-1) 83 } else { 84 n.SetInt64(1) 85 } 86 87 res := x.Div(x.Abs(x), y.Abs(y)) 88 res.Mul(res, n) 89 90 stack.push(math.U256(res)) 91 } 92 evm.interpreter.intPool.put(y) 93 return nil, nil 94 } 95 96 func opMod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 97 x, y := stack.pop(), stack.pop() 98 if y.Sign() == 0 { 99 stack.push(new(big.Int)) 100 } else { 101 stack.push(math.U256(x.Mod(x, y))) 102 } 103 evm.interpreter.intPool.put(y) 104 return nil, nil 105 } 106 107 func opSmod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 108 x, y := math.S256(stack.pop()), math.S256(stack.pop()) 109 110 if y.Sign() == 0 { 111 stack.push(new(big.Int)) 112 } else { 113 n := new(big.Int) 114 if x.Sign() < 0 { 115 n.SetInt64(-1) 116 } else { 117 n.SetInt64(1) 118 } 119 120 res := x.Mod(x.Abs(x), y.Abs(y)) 121 res.Mul(res, n) 122 123 stack.push(math.U256(res)) 124 } 125 evm.interpreter.intPool.put(y) 126 return nil, nil 127 } 128 129 func opExp(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 130 base, exponent := stack.pop(), stack.pop() 131 stack.push(math.Exp(base, exponent)) 132 133 evm.interpreter.intPool.put(base, exponent) 134 135 return nil, nil 136 } 137 138 func opSignExtend(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 139 back := stack.pop() 140 if back.Cmp(big.NewInt(31)) < 0 { 141 bit := uint(back.Uint64()*8 + 7) 142 num := stack.pop() 143 mask := back.Lsh(common.Big1, bit) 144 mask.Sub(mask, common.Big1) 145 if num.Bit(int(bit)) > 0 { 146 num.Or(num, mask.Not(mask)) 147 } else { 148 num.And(num, mask) 149 } 150 151 stack.push(math.U256(num)) 152 } 153 154 evm.interpreter.intPool.put(back) 155 return nil, nil 156 } 157 158 func opNot(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 159 x := stack.pop() 160 stack.push(math.U256(x.Not(x))) 161 return nil, nil 162 } 163 164 func opLt(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 165 x, y := stack.pop(), stack.pop() 166 if x.Cmp(y) < 0 { 167 stack.push(evm.interpreter.intPool.get().SetUint64(1)) 168 } else { 169 stack.push(new(big.Int)) 170 } 171 172 evm.interpreter.intPool.put(x, y) 173 return nil, nil 174 } 175 176 func opGt(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 177 x, y := stack.pop(), stack.pop() 178 if x.Cmp(y) > 0 { 179 stack.push(evm.interpreter.intPool.get().SetUint64(1)) 180 } else { 181 stack.push(new(big.Int)) 182 } 183 184 evm.interpreter.intPool.put(x, y) 185 return nil, nil 186 } 187 188 func opSlt(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 189 x, y := math.S256(stack.pop()), math.S256(stack.pop()) 190 if x.Cmp(math.S256(y)) < 0 { 191 stack.push(evm.interpreter.intPool.get().SetUint64(1)) 192 } else { 193 stack.push(new(big.Int)) 194 } 195 196 evm.interpreter.intPool.put(x, y) 197 return nil, nil 198 } 199 200 func opSgt(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 201 x, y := math.S256(stack.pop()), math.S256(stack.pop()) 202 if x.Cmp(y) > 0 { 203 stack.push(evm.interpreter.intPool.get().SetUint64(1)) 204 } else { 205 stack.push(new(big.Int)) 206 } 207 208 evm.interpreter.intPool.put(x, y) 209 return nil, nil 210 } 211 212 func opEq(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 213 x, y := stack.pop(), stack.pop() 214 if x.Cmp(y) == 0 { 215 stack.push(evm.interpreter.intPool.get().SetUint64(1)) 216 } else { 217 stack.push(new(big.Int)) 218 } 219 220 evm.interpreter.intPool.put(x, y) 221 return nil, nil 222 } 223 224 func opIszero(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 225 x := stack.pop() 226 if x.Sign() > 0 { 227 stack.push(new(big.Int)) 228 } else { 229 stack.push(evm.interpreter.intPool.get().SetUint64(1)) 230 } 231 232 evm.interpreter.intPool.put(x) 233 return nil, nil 234 } 235 236 func opAnd(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 237 x, y := stack.pop(), stack.pop() 238 stack.push(x.And(x, y)) 239 240 evm.interpreter.intPool.put(y) 241 return nil, nil 242 } 243 func opOr(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 244 x, y := stack.pop(), stack.pop() 245 stack.push(x.Or(x, y)) 246 247 evm.interpreter.intPool.put(y) 248 return nil, nil 249 } 250 func opXor(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 251 x, y := stack.pop(), stack.pop() 252 stack.push(x.Xor(x, y)) 253 254 evm.interpreter.intPool.put(y) 255 return nil, nil 256 } 257 258 func opByte(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 259 th, val := stack.pop(), stack.pop() 260 if th.Cmp(big.NewInt(32)) < 0 { 261 byte := evm.interpreter.intPool.get().SetInt64(int64(math.PaddedBigBytes(val, 32)[th.Int64()])) 262 stack.push(byte) 263 } else { 264 stack.push(new(big.Int)) 265 } 266 267 evm.interpreter.intPool.put(th, val) 268 return nil, nil 269 } 270 func opAddmod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 271 x, y, z := stack.pop(), stack.pop(), stack.pop() 272 if z.Cmp(bigZero) > 0 { 273 add := x.Add(x, y) 274 add.Mod(add, z) 275 stack.push(math.U256(add)) 276 } else { 277 stack.push(new(big.Int)) 278 } 279 280 evm.interpreter.intPool.put(y, z) 281 return nil, nil 282 } 283 func opMulmod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 284 x, y, z := stack.pop(), stack.pop(), stack.pop() 285 if z.Cmp(bigZero) > 0 { 286 mul := x.Mul(x, y) 287 mul.Mod(mul, z) 288 stack.push(math.U256(mul)) 289 } else { 290 stack.push(new(big.Int)) 291 } 292 293 evm.interpreter.intPool.put(y, z) 294 return nil, nil 295 } 296 297 func opSha3(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 298 offset, size := stack.pop(), stack.pop() 299 data := memory.Get(offset.Int64(), size.Int64()) 300 hash := crypto.Keccak256(data) 301 302 if evm.vmConfig.EnablePreimageRecording { 303 evm.StateDB.AddPreimage(common.BytesToHash(hash), data) 304 } 305 306 stack.push(new(big.Int).SetBytes(hash)) 307 308 evm.interpreter.intPool.put(offset, size) 309 return nil, nil 310 } 311 312 func opAddress(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 313 stack.push(contract.Address().Big()) 314 return nil, nil 315 } 316 317 func opBalance(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 318 addr := common.BigToAddress(stack.pop()) 319 balance := evm.StateDB.GetBalance(addr) 320 321 stack.push(new(big.Int).Set(balance)) 322 return nil, nil 323 } 324 325 func opOrigin(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 326 stack.push(evm.Origin.Big()) 327 return nil, nil 328 } 329 330 func opCaller(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 331 stack.push(contract.Caller().Big()) 332 return nil, nil 333 } 334 335 func opCallValue(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 336 stack.push(evm.interpreter.intPool.get().Set(contract.value)) 337 return nil, nil 338 } 339 340 func opCalldataLoad(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 341 stack.push(new(big.Int).SetBytes(getData(contract.Input, stack.pop(), common.Big32))) 342 return nil, nil 343 } 344 345 func opCalldataSize(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 346 stack.push(evm.interpreter.intPool.get().SetInt64(int64(len(contract.Input)))) 347 return nil, nil 348 } 349 350 func opCalldataCopy(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 351 var ( 352 mOff = stack.pop() 353 cOff = stack.pop() 354 l = stack.pop() 355 ) 356 memory.Set(mOff.Uint64(), l.Uint64(), getData(contract.Input, cOff, l)) 357 358 evm.interpreter.intPool.put(mOff, cOff, l) 359 return nil, nil 360 } 361 362 func opExtCodeSize(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 363 a := stack.pop() 364 365 addr := common.BigToAddress(a) 366 a.SetInt64(int64(evm.StateDB.GetCodeSize(addr))) 367 stack.push(a) 368 369 return nil, nil 370 } 371 372 func opCodeSize(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 373 l := evm.interpreter.intPool.get().SetInt64(int64(len(contract.Code))) 374 stack.push(l) 375 return nil, nil 376 } 377 378 func opCodeCopy(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 379 var ( 380 mOff = stack.pop() 381 cOff = stack.pop() 382 l = stack.pop() 383 ) 384 codeCopy := getData(contract.Code, cOff, l) 385 386 memory.Set(mOff.Uint64(), l.Uint64(), codeCopy) 387 388 evm.interpreter.intPool.put(mOff, cOff, l) 389 return nil, nil 390 } 391 392 func opExtCodeCopy(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 393 var ( 394 addr = common.BigToAddress(stack.pop()) 395 mOff = stack.pop() 396 cOff = stack.pop() 397 l = stack.pop() 398 ) 399 codeCopy := getData(evm.StateDB.GetCode(addr), cOff, l) 400 401 memory.Set(mOff.Uint64(), l.Uint64(), codeCopy) 402 403 evm.interpreter.intPool.put(mOff, cOff, l) 404 405 return nil, nil 406 } 407 408 func opGasprice(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 409 stack.push(evm.interpreter.intPool.get().Set(evm.GasPrice)) 410 return nil, nil 411 } 412 413 func opBlockhash(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 414 num := stack.pop() 415 416 n := evm.interpreter.intPool.get().Sub(evm.BlockNumber, common.Big257) 417 if num.Cmp(n) > 0 && num.Cmp(evm.BlockNumber) < 0 { 418 stack.push(evm.GetHash(num.Uint64()).Big()) 419 } else { 420 stack.push(new(big.Int)) 421 } 422 423 evm.interpreter.intPool.put(num, n) 424 return nil, nil 425 } 426 427 func opCoinbase(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 428 stack.push(evm.Coinbase.Big()) 429 return nil, nil 430 } 431 432 func opTimestamp(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 433 stack.push(math.U256(new(big.Int).Set(evm.Time))) 434 return nil, nil 435 } 436 437 func opNumber(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 438 stack.push(math.U256(new(big.Int).Set(evm.BlockNumber))) 439 return nil, nil 440 } 441 442 func opDifficulty(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 443 stack.push(math.U256(new(big.Int).Set(evm.Difficulty))) 444 return nil, nil 445 } 446 447 func opGasLimit(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 448 stack.push(math.U256(new(big.Int).Set(evm.GasLimit))) 449 return nil, nil 450 } 451 452 func opPop(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 453 evm.interpreter.intPool.put(stack.pop()) 454 return nil, nil 455 } 456 457 func opMload(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 458 offset := stack.pop() 459 val := new(big.Int).SetBytes(memory.Get(offset.Int64(), 32)) 460 stack.push(val) 461 462 evm.interpreter.intPool.put(offset) 463 return nil, nil 464 } 465 466 func opMstore(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 467 // pop value of the stack 468 mStart, val := stack.pop(), stack.pop() 469 memory.Set(mStart.Uint64(), 32, math.PaddedBigBytes(val, 32)) 470 471 evm.interpreter.intPool.put(mStart, val) 472 return nil, nil 473 } 474 475 func opMstore8(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 476 off, val := stack.pop().Int64(), stack.pop().Int64() 477 memory.store[off] = byte(val & 0xff) 478 479 return nil, nil 480 } 481 482 func opSload(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 483 loc := common.BigToHash(stack.pop()) 484 val := evm.StateDB.GetState(contract.Address(), loc).Big() 485 stack.push(val) 486 return nil, nil 487 } 488 489 func opSstore(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 490 loc := common.BigToHash(stack.pop()) 491 val := stack.pop() 492 evm.StateDB.SetState(contract.Address(), loc, common.BigToHash(val)) 493 494 evm.interpreter.intPool.put(val) 495 return nil, nil 496 } 497 498 func opJump(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 499 pos := stack.pop() 500 if !contract.jumpdests.has(contract.CodeHash, contract.Code, pos) { 501 nop := contract.GetOp(pos.Uint64()) 502 return nil, fmt.Errorf("invalid jump destination (%v) %v", nop, pos) 503 } 504 *pc = pos.Uint64() 505 506 evm.interpreter.intPool.put(pos) 507 return nil, nil 508 } 509 func opJumpi(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 510 pos, cond := stack.pop(), stack.pop() 511 if cond.Sign() != 0 { 512 if !contract.jumpdests.has(contract.CodeHash, contract.Code, pos) { 513 nop := contract.GetOp(pos.Uint64()) 514 return nil, fmt.Errorf("invalid jump destination (%v) %v", nop, pos) 515 } 516 *pc = pos.Uint64() 517 } else { 518 *pc++ 519 } 520 521 evm.interpreter.intPool.put(pos, cond) 522 return nil, nil 523 } 524 func opJumpdest(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 525 return nil, nil 526 } 527 528 func opPc(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 529 stack.push(evm.interpreter.intPool.get().SetUint64(*pc)) 530 return nil, nil 531 } 532 533 func opMsize(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 534 stack.push(evm.interpreter.intPool.get().SetInt64(int64(memory.Len()))) 535 return nil, nil 536 } 537 538 func opGas(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 539 stack.push(evm.interpreter.intPool.get().SetUint64(contract.Gas)) 540 return nil, nil 541 } 542 543 func opCreate(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 544 var ( 545 value = stack.pop() 546 offset, size = stack.pop(), stack.pop() 547 input = memory.Get(offset.Int64(), size.Int64()) 548 gas = contract.Gas 549 ) 550 if evm.ChainConfig().IsEIP150(evm.BlockNumber) { 551 gas -= gas / 64 552 } 553 554 contract.UseGas(gas) 555 _, addr, returnGas, suberr := evm.Create(contract, input, gas, value) 556 // Push item on the stack based on the returned error. If the ruleset is 557 // homestead we must check for CodeStoreOutOfGasError (homestead only 558 // rule) and treat as an error, if the ruleset is frontier we must 559 // ignore this error and pretend the operation was successful. 560 if evm.ChainConfig().IsHomestead(evm.BlockNumber) && suberr == ErrCodeStoreOutOfGas { 561 stack.push(new(big.Int)) 562 } else if suberr != nil && suberr != ErrCodeStoreOutOfGas { 563 stack.push(new(big.Int)) 564 } else { 565 stack.push(addr.Big()) 566 } 567 contract.Gas += returnGas 568 569 evm.interpreter.intPool.put(value, offset, size) 570 571 return nil, nil 572 } 573 574 func opCall(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 575 gas := stack.pop().Uint64() 576 // pop gas and value of the stack. 577 addr, value := stack.pop(), stack.pop() 578 value = math.U256(value) 579 // pop input size and offset 580 inOffset, inSize := stack.pop(), stack.pop() 581 // pop return size and offset 582 retOffset, retSize := stack.pop(), stack.pop() 583 584 address := common.BigToAddress(addr) 585 586 // Get the arguments from the memory 587 args := memory.Get(inOffset.Int64(), inSize.Int64()) 588 589 if value.Sign() != 0 { 590 gas += params.CallStipend 591 } 592 593 ret, returnGas, err := evm.Call(contract, address, args, gas, value) 594 if err != nil { 595 stack.push(new(big.Int)) 596 } else { 597 stack.push(big.NewInt(1)) 598 599 memory.Set(retOffset.Uint64(), retSize.Uint64(), ret) 600 } 601 contract.Gas += returnGas 602 603 evm.interpreter.intPool.put(addr, value, inOffset, inSize, retOffset, retSize) 604 return ret, nil 605 } 606 607 func opCallCode(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 608 gas := stack.pop().Uint64() 609 // pop gas and value of the stack. 610 addr, value := stack.pop(), stack.pop() 611 value = math.U256(value) 612 // pop input size and offset 613 inOffset, inSize := stack.pop(), stack.pop() 614 // pop return size and offset 615 retOffset, retSize := stack.pop(), stack.pop() 616 617 address := common.BigToAddress(addr) 618 619 // Get the arguments from the memory 620 args := memory.Get(inOffset.Int64(), inSize.Int64()) 621 622 if value.Sign() != 0 { 623 gas += params.CallStipend 624 } 625 626 ret, returnGas, err := evm.CallCode(contract, address, args, gas, value) 627 if err != nil { 628 stack.push(new(big.Int)) 629 630 } else { 631 stack.push(big.NewInt(1)) 632 633 memory.Set(retOffset.Uint64(), retSize.Uint64(), ret) 634 } 635 contract.Gas += returnGas 636 637 evm.interpreter.intPool.put(addr, value, inOffset, inSize, retOffset, retSize) 638 return ret, nil 639 } 640 641 func opDelegateCall(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 642 gas, to, inOffset, inSize, outOffset, outSize := stack.pop().Uint64(), stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop() 643 644 toAddr := common.BigToAddress(to) 645 args := memory.Get(inOffset.Int64(), inSize.Int64()) 646 647 ret, returnGas, err := evm.DelegateCall(contract, toAddr, args, gas) 648 if err != nil { 649 stack.push(new(big.Int)) 650 } else { 651 stack.push(big.NewInt(1)) 652 memory.Set(outOffset.Uint64(), outSize.Uint64(), ret) 653 } 654 contract.Gas += returnGas 655 656 evm.interpreter.intPool.put(to, inOffset, inSize, outOffset, outSize) 657 return ret, nil 658 } 659 660 func opReturn(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 661 offset, size := stack.pop(), stack.pop() 662 ret := memory.GetPtr(offset.Int64(), size.Int64()) 663 664 evm.interpreter.intPool.put(offset, size) 665 666 return ret, nil 667 } 668 669 func opStop(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 670 return nil, nil 671 } 672 673 func opSuicide(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 674 balance := evm.StateDB.GetBalance(contract.Address()) 675 evm.StateDB.AddBalance(common.BigToAddress(stack.pop()), balance) 676 677 evm.StateDB.Suicide(contract.Address()) 678 679 return nil, nil 680 } 681 682 // following functions are used by the instruction jump table 683 684 // make log instruction function 685 func makeLog(size int) executionFunc { 686 return func(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 687 topics := make([]common.Hash, size) 688 mStart, mSize := stack.pop(), stack.pop() 689 for i := 0; i < size; i++ { 690 topics[i] = common.BigToHash(stack.pop()) 691 } 692 693 d := memory.Get(mStart.Int64(), mSize.Int64()) 694 evm.StateDB.AddLog(&types.Log{ 695 Address: contract.Address(), 696 Topics: topics, 697 Data: d, 698 // This is a non-consensus field, but assigned here because 699 // core/state doesn't know the current block number. 700 BlockNumber: evm.BlockNumber.Uint64(), 701 }) 702 703 evm.interpreter.intPool.put(mStart, mSize) 704 return nil, nil 705 } 706 } 707 708 // make push instruction function 709 func makePush(size uint64, pushByteSize int) executionFunc { 710 return func(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 711 codeLen := len(contract.Code) 712 713 startMin := codeLen 714 if int(*pc+1) < startMin { 715 startMin = int(*pc + 1) 716 } 717 718 endMin := codeLen 719 if startMin+pushByteSize < endMin { 720 endMin = startMin + pushByteSize 721 } 722 723 integer := evm.interpreter.intPool.get() 724 stack.push(integer.SetBytes(common.RightPadBytes(contract.Code[startMin:endMin], pushByteSize))) 725 726 *pc += size 727 return nil, nil 728 } 729 } 730 731 // make push instruction function 732 func makeDup(size int64) executionFunc { 733 return func(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 734 stack.dup(evm.interpreter.intPool, int(size)) 735 return nil, nil 736 } 737 } 738 739 // make swap instruction function 740 func makeSwap(size int64) executionFunc { 741 // switch n + 1 otherwise n would be swapped with n 742 size += 1 743 return func(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 744 stack.swap(int(size)) 745 return nil, nil 746 } 747 }