123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870 |
- // Copyright 2015 The go-ethereum Authors
- // This file is part of the go-ethereum library.
- //
- // The go-ethereum library is free software: you can redistribute it and/or modify
- // it under the terms of the GNU Lesser General Public License as published by
- // the Free Software Foundation, either version 3 of the License, or
- // (at your option) any later version.
- //
- // The go-ethereum library is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU Lesser General Public License for more details.
- //
- // You should have received a copy of the GNU Lesser General Public License
- // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
- package vm
- import (
- "errors"
- "fmt"
- "math/big"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/common/math"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/params"
- )
- var (
- bigZero = new(big.Int)
- tt255 = math.BigPow(2, 255)
- errWriteProtection = errors.New("evm: write protection")
- errReturnDataOutOfBounds = errors.New("evm: return data out of bounds")
- errExecutionReverted = errors.New("evm: execution reverted")
- errMaxCodeSizeExceeded = errors.New("evm: max code size exceeded")
- )
- func opAdd(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := stack.pop(), stack.peek()
- math.U256(y.Add(x, y))
- evm.interpreter.intPool.put(x)
- return nil, nil
- }
- func opSub(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := stack.pop(), stack.peek()
- math.U256(y.Sub(x, y))
- evm.interpreter.intPool.put(x)
- return nil, nil
- }
- func opMul(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := stack.pop(), stack.pop()
- stack.push(math.U256(x.Mul(x, y)))
- evm.interpreter.intPool.put(y)
- return nil, nil
- }
- func opDiv(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := stack.pop(), stack.peek()
- if y.Sign() != 0 {
- math.U256(y.Div(x, y))
- } else {
- y.SetUint64(0)
- }
- evm.interpreter.intPool.put(x)
- return nil, nil
- }
- func opSdiv(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := math.S256(stack.pop()), math.S256(stack.pop())
- res := evm.interpreter.intPool.getZero()
- if y.Sign() == 0 || x.Sign() == 0 {
- stack.push(res)
- } else {
- if x.Sign() != y.Sign() {
- res.Div(x.Abs(x), y.Abs(y))
- res.Neg(res)
- } else {
- res.Div(x.Abs(x), y.Abs(y))
- }
- stack.push(math.U256(res))
- }
- evm.interpreter.intPool.put(x, y)
- return nil, nil
- }
- func opMod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := stack.pop(), stack.pop()
- if y.Sign() == 0 {
- stack.push(x.SetUint64(0))
- } else {
- stack.push(math.U256(x.Mod(x, y)))
- }
- evm.interpreter.intPool.put(y)
- return nil, nil
- }
- func opSmod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := math.S256(stack.pop()), math.S256(stack.pop())
- res := evm.interpreter.intPool.getZero()
- if y.Sign() == 0 {
- stack.push(res)
- } else {
- if x.Sign() < 0 {
- res.Mod(x.Abs(x), y.Abs(y))
- res.Neg(res)
- } else {
- res.Mod(x.Abs(x), y.Abs(y))
- }
- stack.push(math.U256(res))
- }
- evm.interpreter.intPool.put(x, y)
- return nil, nil
- }
- func opExp(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- base, exponent := stack.pop(), stack.pop()
- stack.push(math.Exp(base, exponent))
- evm.interpreter.intPool.put(base, exponent)
- return nil, nil
- }
- func opSignExtend(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- back := stack.pop()
- if back.Cmp(big.NewInt(31)) < 0 {
- bit := uint(back.Uint64()*8 + 7)
- num := stack.pop()
- mask := back.Lsh(common.Big1, bit)
- mask.Sub(mask, common.Big1)
- if num.Bit(int(bit)) > 0 {
- num.Or(num, mask.Not(mask))
- } else {
- num.And(num, mask)
- }
- stack.push(math.U256(num))
- }
- evm.interpreter.intPool.put(back)
- return nil, nil
- }
- func opNot(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x := stack.peek()
- math.U256(x.Not(x))
- return nil, nil
- }
- func opLt(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := stack.pop(), stack.peek()
- if x.Cmp(y) < 0 {
- y.SetUint64(1)
- } else {
- y.SetUint64(0)
- }
- evm.interpreter.intPool.put(x)
- return nil, nil
- }
- func opGt(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := stack.pop(), stack.peek()
- if x.Cmp(y) > 0 {
- y.SetUint64(1)
- } else {
- y.SetUint64(0)
- }
- evm.interpreter.intPool.put(x)
- return nil, nil
- }
- func opSlt(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := stack.pop(), stack.peek()
- xSign := x.Cmp(tt255)
- ySign := y.Cmp(tt255)
- switch {
- case xSign >= 0 && ySign < 0:
- y.SetUint64(1)
- case xSign < 0 && ySign >= 0:
- y.SetUint64(0)
- default:
- if x.Cmp(y) < 0 {
- y.SetUint64(1)
- } else {
- y.SetUint64(0)
- }
- }
- evm.interpreter.intPool.put(x)
- return nil, nil
- }
- func opSgt(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := stack.pop(), stack.peek()
- xSign := x.Cmp(tt255)
- ySign := y.Cmp(tt255)
- switch {
- case xSign >= 0 && ySign < 0:
- y.SetUint64(0)
- case xSign < 0 && ySign >= 0:
- y.SetUint64(1)
- default:
- if x.Cmp(y) > 0 {
- y.SetUint64(1)
- } else {
- y.SetUint64(0)
- }
- }
- evm.interpreter.intPool.put(x)
- return nil, nil
- }
- func opEq(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := stack.pop(), stack.peek()
- if x.Cmp(y) == 0 {
- y.SetUint64(1)
- } else {
- y.SetUint64(0)
- }
- evm.interpreter.intPool.put(x)
- return nil, nil
- }
- func opIszero(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x := stack.peek()
- if x.Sign() > 0 {
- x.SetUint64(0)
- } else {
- x.SetUint64(1)
- }
- return nil, nil
- }
- func opAnd(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := stack.pop(), stack.pop()
- stack.push(x.And(x, y))
- evm.interpreter.intPool.put(y)
- return nil, nil
- }
- func opOr(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := stack.pop(), stack.peek()
- y.Or(x, y)
- evm.interpreter.intPool.put(x)
- return nil, nil
- }
- func opXor(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := stack.pop(), stack.peek()
- y.Xor(x, y)
- evm.interpreter.intPool.put(x)
- return nil, nil
- }
- func opByte(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- th, val := stack.pop(), stack.peek()
- if th.Cmp(common.Big32) < 0 {
- b := math.Byte(val, 32, int(th.Int64()))
- val.SetUint64(uint64(b))
- } else {
- val.SetUint64(0)
- }
- evm.interpreter.intPool.put(th)
- return nil, nil
- }
- func opAddmod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y, z := stack.pop(), stack.pop(), stack.pop()
- if z.Cmp(bigZero) > 0 {
- x.Add(x, y)
- x.Mod(x, z)
- stack.push(math.U256(x))
- } else {
- stack.push(x.SetUint64(0))
- }
- evm.interpreter.intPool.put(y, z)
- return nil, nil
- }
- func opMulmod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y, z := stack.pop(), stack.pop(), stack.pop()
- if z.Cmp(bigZero) > 0 {
- x.Mul(x, y)
- x.Mod(x, z)
- stack.push(math.U256(x))
- } else {
- stack.push(x.SetUint64(0))
- }
- evm.interpreter.intPool.put(y, z)
- return nil, nil
- }
- // opSHL implements Shift Left
- // The SHL instruction (shift left) pops 2 values from the stack, first arg1 and then arg2,
- // and pushes on the stack arg2 shifted to the left by arg1 number of bits.
- func opSHL(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- // Note, second operand is left in the stack; accumulate result into it, and no need to push it afterwards
- shift, value := math.U256(stack.pop()), math.U256(stack.peek())
- defer evm.interpreter.intPool.put(shift) // First operand back into the pool
- if shift.Cmp(common.Big256) >= 0 {
- value.SetUint64(0)
- return nil, nil
- }
- n := uint(shift.Uint64())
- math.U256(value.Lsh(value, n))
- return nil, nil
- }
- // opSHR implements Logical Shift Right
- // The SHR instruction (logical shift right) pops 2 values from the stack, first arg1 and then arg2,
- // and pushes on the stack arg2 shifted to the right by arg1 number of bits with zero fill.
- func opSHR(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- // Note, second operand is left in the stack; accumulate result into it, and no need to push it afterwards
- shift, value := math.U256(stack.pop()), math.U256(stack.peek())
- defer evm.interpreter.intPool.put(shift) // First operand back into the pool
- if shift.Cmp(common.Big256) >= 0 {
- value.SetUint64(0)
- return nil, nil
- }
- n := uint(shift.Uint64())
- math.U256(value.Rsh(value, n))
- return nil, nil
- }
- // opSAR implements Arithmetic Shift Right
- // The SAR instruction (arithmetic shift right) pops 2 values from the stack, first arg1 and then arg2,
- // and pushes on the stack arg2 shifted to the right by arg1 number of bits with sign extension.
- func opSAR(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- // Note, S256 returns (potentially) a new bigint, so we're popping, not peeking this one
- shift, value := math.U256(stack.pop()), math.S256(stack.pop())
- defer evm.interpreter.intPool.put(shift) // First operand back into the pool
- if shift.Cmp(common.Big256) >= 0 {
- if value.Sign() > 0 {
- value.SetUint64(0)
- } else {
- value.SetInt64(-1)
- }
- stack.push(math.U256(value))
- return nil, nil
- }
- n := uint(shift.Uint64())
- value.Rsh(value, n)
- stack.push(math.U256(value))
- return nil, nil
- }
- func opSha3(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- offset, size := stack.pop(), stack.pop()
- data := memory.Get(offset.Int64(), size.Int64())
- hash := crypto.Keccak256(data)
- if evm.vmConfig.EnablePreimageRecording {
- evm.StateDB.AddPreimage(common.BytesToHash(hash), data)
- }
- stack.push(evm.interpreter.intPool.get().SetBytes(hash))
- evm.interpreter.intPool.put(offset, size)
- return nil, nil
- }
- func opAddress(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(contract.Address().Big())
- return nil, nil
- }
- func opBalance(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- slot := stack.peek()
- slot.Set(evm.StateDB.GetBalance(common.BigToAddress(slot)))
- return nil, nil
- }
- func opOrigin(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(evm.Origin.Big())
- return nil, nil
- }
- func opCaller(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(contract.Caller().Big())
- return nil, nil
- }
- func opCallValue(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(evm.interpreter.intPool.get().Set(contract.value))
- return nil, nil
- }
- func opCallDataLoad(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(evm.interpreter.intPool.get().SetBytes(getDataBig(contract.Input, stack.pop(), big32)))
- return nil, nil
- }
- func opCallDataSize(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(evm.interpreter.intPool.get().SetInt64(int64(len(contract.Input))))
- return nil, nil
- }
- func opCallDataCopy(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- var (
- memOffset = stack.pop()
- dataOffset = stack.pop()
- length = stack.pop()
- )
- memory.Set(memOffset.Uint64(), length.Uint64(), getDataBig(contract.Input, dataOffset, length))
- evm.interpreter.intPool.put(memOffset, dataOffset, length)
- return nil, nil
- }
- func opReturnDataSize(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(evm.interpreter.intPool.get().SetUint64(uint64(len(evm.interpreter.returnData))))
- return nil, nil
- }
- func opReturnDataCopy(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- var (
- memOffset = stack.pop()
- dataOffset = stack.pop()
- length = stack.pop()
- end = evm.interpreter.intPool.get().Add(dataOffset, length)
- )
- defer evm.interpreter.intPool.put(memOffset, dataOffset, length, end)
- if end.BitLen() > 64 || uint64(len(evm.interpreter.returnData)) < end.Uint64() {
- return nil, errReturnDataOutOfBounds
- }
- memory.Set(memOffset.Uint64(), length.Uint64(), evm.interpreter.returnData[dataOffset.Uint64():end.Uint64()])
- return nil, nil
- }
- func opExtCodeSize(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- slot := stack.peek()
- slot.SetUint64(uint64(evm.StateDB.GetCodeSize(common.BigToAddress(slot))))
- return nil, nil
- }
- func opCodeSize(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- l := evm.interpreter.intPool.get().SetInt64(int64(len(contract.Code)))
- stack.push(l)
- return nil, nil
- }
- func opCodeCopy(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- var (
- memOffset = stack.pop()
- codeOffset = stack.pop()
- length = stack.pop()
- )
- codeCopy := getDataBig(contract.Code, codeOffset, length)
- memory.Set(memOffset.Uint64(), length.Uint64(), codeCopy)
- evm.interpreter.intPool.put(memOffset, codeOffset, length)
- return nil, nil
- }
- func opExtCodeCopy(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- var (
- addr = common.BigToAddress(stack.pop())
- memOffset = stack.pop()
- codeOffset = stack.pop()
- length = stack.pop()
- )
- codeCopy := getDataBig(evm.StateDB.GetCode(addr), codeOffset, length)
- memory.Set(memOffset.Uint64(), length.Uint64(), codeCopy)
- evm.interpreter.intPool.put(memOffset, codeOffset, length)
- return nil, nil
- }
- func opGasprice(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(evm.interpreter.intPool.get().Set(evm.GasPrice))
- return nil, nil
- }
- func opBlockhash(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- num := stack.pop()
- n := evm.interpreter.intPool.get().Sub(evm.BlockNumber, common.Big257)
- if num.Cmp(n) > 0 && num.Cmp(evm.BlockNumber) < 0 {
- stack.push(evm.GetHash(num.Uint64()).Big())
- } else {
- stack.push(evm.interpreter.intPool.getZero())
- }
- evm.interpreter.intPool.put(num, n)
- return nil, nil
- }
- func opCoinbase(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(evm.Coinbase.Big())
- return nil, nil
- }
- func opTimestamp(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(math.U256(evm.interpreter.intPool.get().Set(evm.Time)))
- return nil, nil
- }
- func opNumber(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(math.U256(evm.interpreter.intPool.get().Set(evm.BlockNumber)))
- return nil, nil
- }
- func opDifficulty(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(math.U256(evm.interpreter.intPool.get().Set(evm.Difficulty)))
- return nil, nil
- }
- func opGasLimit(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(math.U256(evm.interpreter.intPool.get().SetUint64(evm.GasLimit)))
- return nil, nil
- }
- func opPop(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- evm.interpreter.intPool.put(stack.pop())
- return nil, nil
- }
- func opMload(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- offset := stack.pop()
- val := evm.interpreter.intPool.get().SetBytes(memory.Get(offset.Int64(), 32))
- stack.push(val)
- evm.interpreter.intPool.put(offset)
- return nil, nil
- }
- func opMstore(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- // pop value of the stack
- mStart, val := stack.pop(), stack.pop()
- memory.Set(mStart.Uint64(), 32, math.PaddedBigBytes(val, 32))
- evm.interpreter.intPool.put(mStart, val)
- return nil, nil
- }
- func opMstore8(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- off, val := stack.pop().Int64(), stack.pop().Int64()
- memory.store[off] = byte(val & 0xff)
- return nil, nil
- }
- func opSload(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- loc := common.BigToHash(stack.pop())
- val := evm.StateDB.GetState(contract.Address(), loc).Big()
- stack.push(val)
- return nil, nil
- }
- func opSstore(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- loc := common.BigToHash(stack.pop())
- val := stack.pop()
- evm.StateDB.SetState(contract.Address(), loc, common.BigToHash(val))
- evm.interpreter.intPool.put(val)
- return nil, nil
- }
- func opJump(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- pos := stack.pop()
- if !contract.jumpdests.has(contract.CodeHash, contract.Code, pos) {
- nop := contract.GetOp(pos.Uint64())
- return nil, fmt.Errorf("invalid jump destination (%v) %v", nop, pos)
- }
- *pc = pos.Uint64()
- evm.interpreter.intPool.put(pos)
- return nil, nil
- }
- func opJumpi(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- pos, cond := stack.pop(), stack.pop()
- if cond.Sign() != 0 {
- if !contract.jumpdests.has(contract.CodeHash, contract.Code, pos) {
- nop := contract.GetOp(pos.Uint64())
- return nil, fmt.Errorf("invalid jump destination (%v) %v", nop, pos)
- }
- *pc = pos.Uint64()
- } else {
- *pc++
- }
- evm.interpreter.intPool.put(pos, cond)
- return nil, nil
- }
- func opJumpdest(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- return nil, nil
- }
- func opPc(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(evm.interpreter.intPool.get().SetUint64(*pc))
- return nil, nil
- }
- func opMsize(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(evm.interpreter.intPool.get().SetInt64(int64(memory.Len())))
- return nil, nil
- }
- func opGas(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(evm.interpreter.intPool.get().SetUint64(contract.Gas))
- return nil, nil
- }
- func opCreate(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- var (
- value = stack.pop()
- offset, size = stack.pop(), stack.pop()
- input = memory.Get(offset.Int64(), size.Int64())
- gas = contract.Gas
- )
- if evm.ChainConfig().IsEIP150(evm.BlockNumber) {
- gas -= gas / 64
- }
- contract.UseGas(gas)
- res, addr, returnGas, suberr := evm.Create(contract, input, gas, value)
- // Push item on the stack based on the returned error. If the ruleset is
- // homestead we must check for CodeStoreOutOfGasError (homestead only
- // rule) and treat as an error, if the ruleset is frontier we must
- // ignore this error and pretend the operation was successful.
- if evm.ChainConfig().IsHomestead(evm.BlockNumber) && suberr == ErrCodeStoreOutOfGas {
- stack.push(evm.interpreter.intPool.getZero())
- } else if suberr != nil && suberr != ErrCodeStoreOutOfGas {
- stack.push(evm.interpreter.intPool.getZero())
- } else {
- stack.push(addr.Big())
- }
- contract.Gas += returnGas
- evm.interpreter.intPool.put(value, offset, size)
- if suberr == errExecutionReverted {
- return res, nil
- }
- return nil, nil
- }
- func opCall(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- // Pop gas. The actual gas in in evm.callGasTemp.
- evm.interpreter.intPool.put(stack.pop())
- gas := evm.callGasTemp
- // Pop other call parameters.
- addr, value, inOffset, inSize, retOffset, retSize := stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop()
- toAddr := common.BigToAddress(addr)
- value = math.U256(value)
- // Get the arguments from the memory.
- args := memory.Get(inOffset.Int64(), inSize.Int64())
- if value.Sign() != 0 {
- gas += params.CallStipend
- }
- ret, returnGas, err := evm.Call(contract, toAddr, args, gas, value)
- if err != nil {
- stack.push(evm.interpreter.intPool.getZero())
- } else {
- stack.push(evm.interpreter.intPool.get().SetUint64(1))
- }
- if err == nil || err == errExecutionReverted {
- memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
- }
- contract.Gas += returnGas
- evm.interpreter.intPool.put(addr, value, inOffset, inSize, retOffset, retSize)
- return ret, nil
- }
- func opCallCode(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- // Pop gas. The actual gas is in evm.callGasTemp.
- evm.interpreter.intPool.put(stack.pop())
- gas := evm.callGasTemp
- // Pop other call parameters.
- addr, value, inOffset, inSize, retOffset, retSize := stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop()
- toAddr := common.BigToAddress(addr)
- value = math.U256(value)
- // Get arguments from the memory.
- args := memory.Get(inOffset.Int64(), inSize.Int64())
- if value.Sign() != 0 {
- gas += params.CallStipend
- }
- ret, returnGas, err := evm.CallCode(contract, toAddr, args, gas, value)
- if err != nil {
- stack.push(evm.interpreter.intPool.getZero())
- } else {
- stack.push(evm.interpreter.intPool.get().SetUint64(1))
- }
- if err == nil || err == errExecutionReverted {
- memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
- }
- contract.Gas += returnGas
- evm.interpreter.intPool.put(addr, value, inOffset, inSize, retOffset, retSize)
- return ret, nil
- }
- func opDelegateCall(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- // Pop gas. The actual gas is in evm.callGasTemp.
- evm.interpreter.intPool.put(stack.pop())
- gas := evm.callGasTemp
- // Pop other call parameters.
- addr, inOffset, inSize, retOffset, retSize := stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop()
- toAddr := common.BigToAddress(addr)
- // Get arguments from the memory.
- args := memory.Get(inOffset.Int64(), inSize.Int64())
- ret, returnGas, err := evm.DelegateCall(contract, toAddr, args, gas)
- if err != nil {
- stack.push(evm.interpreter.intPool.getZero())
- } else {
- stack.push(evm.interpreter.intPool.get().SetUint64(1))
- }
- if err == nil || err == errExecutionReverted {
- memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
- }
- contract.Gas += returnGas
- evm.interpreter.intPool.put(addr, inOffset, inSize, retOffset, retSize)
- return ret, nil
- }
- func opStaticCall(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- // Pop gas. The actual gas is in evm.callGasTemp.
- evm.interpreter.intPool.put(stack.pop())
- gas := evm.callGasTemp
- // Pop other call parameters.
- addr, inOffset, inSize, retOffset, retSize := stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop()
- toAddr := common.BigToAddress(addr)
- // Get arguments from the memory.
- args := memory.Get(inOffset.Int64(), inSize.Int64())
- ret, returnGas, err := evm.StaticCall(contract, toAddr, args, gas)
- if err != nil {
- stack.push(evm.interpreter.intPool.getZero())
- } else {
- stack.push(evm.interpreter.intPool.get().SetUint64(1))
- }
- if err == nil || err == errExecutionReverted {
- memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
- }
- contract.Gas += returnGas
- evm.interpreter.intPool.put(addr, inOffset, inSize, retOffset, retSize)
- return ret, nil
- }
- func opReturn(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- offset, size := stack.pop(), stack.pop()
- ret := memory.GetPtr(offset.Int64(), size.Int64())
- evm.interpreter.intPool.put(offset, size)
- return ret, nil
- }
- func opRevert(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- offset, size := stack.pop(), stack.pop()
- ret := memory.GetPtr(offset.Int64(), size.Int64())
- evm.interpreter.intPool.put(offset, size)
- return ret, nil
- }
- func opStop(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- return nil, nil
- }
- func opSuicide(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- balance := evm.StateDB.GetBalance(contract.Address())
- evm.StateDB.AddBalance(common.BigToAddress(stack.pop()), balance)
- evm.StateDB.Suicide(contract.Address())
- return nil, nil
- }
- // following functions are used by the instruction jump table
- // make log instruction function
- func makeLog(size int) executionFunc {
- return func(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- topics := make([]common.Hash, size)
- mStart, mSize := stack.pop(), stack.pop()
- for i := 0; i < size; i++ {
- topics[i] = common.BigToHash(stack.pop())
- }
- d := memory.Get(mStart.Int64(), mSize.Int64())
- evm.StateDB.AddLog(&types.Log{
- Address: contract.Address(),
- Topics: topics,
- Data: d,
- // This is a non-consensus field, but assigned here because
- // core/state doesn't know the current block number.
- BlockNumber: evm.BlockNumber.Uint64(),
- })
- evm.interpreter.intPool.put(mStart, mSize)
- return nil, nil
- }
- }
- // make push instruction function
- func makePush(size uint64, pushByteSize int) executionFunc {
- return func(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- codeLen := len(contract.Code)
- startMin := codeLen
- if int(*pc+1) < startMin {
- startMin = int(*pc + 1)
- }
- endMin := codeLen
- if startMin+pushByteSize < endMin {
- endMin = startMin + pushByteSize
- }
- integer := evm.interpreter.intPool.get()
- stack.push(integer.SetBytes(common.RightPadBytes(contract.Code[startMin:endMin], pushByteSize)))
- *pc += size
- return nil, nil
- }
- }
- // make dup instruction function
- func makeDup(size int64) executionFunc {
- return func(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.dup(evm.interpreter.intPool, int(size))
- return nil, nil
- }
- }
- // make swap instruction function
- func makeSwap(size int64) executionFunc {
- // switch n + 1 otherwise n would be swapped with n
- size += 1
- return func(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.swap(int(size))
- return nil, nil
- }
- }
|