all: seperate consensus error and evm internal error (#20830)
* all: seperate consensus error and evm internal error There are actually two types of error will be returned when a tranaction/message call is executed: (a) consensus error (b) evm internal error. The former should be converted to a consensus issue, e.g. The sender doesn't enough asset to purchase the gas it specifies. The latter is allowed since evm itself is a blackbox and internal error is allowed to happen. This PR emphasizes the difference by introducing a executionResult structure. The evm error is embedded inside. So if any error returned, it indicates consensus issue happens. And also this PR improve the `EstimateGas` API to return the concrete revert reason if the transaction always fails * all: polish * accounts/abi/bind/backends: add tests * accounts/abi/bind/backends, internal: cleanup error message * all: address comments * core: fix lint * accounts, core, eth, internal: address comments * accounts, internal: resolve revert reason if possible * accounts, internal: address comments
This commit is contained in:
@@ -16,15 +16,51 @@
|
||||
|
||||
package vm
|
||||
|
||||
import "errors"
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// List execution errors
|
||||
// List evm execution errors
|
||||
var (
|
||||
ErrOutOfGas = errors.New("out of gas")
|
||||
ErrCodeStoreOutOfGas = errors.New("contract creation code storage out of gas")
|
||||
ErrDepth = errors.New("max call depth exceeded")
|
||||
ErrTraceLimitReached = errors.New("the number of logs reached the specified limit")
|
||||
ErrInsufficientBalance = errors.New("insufficient balance for transfer")
|
||||
ErrContractAddressCollision = errors.New("contract address collision")
|
||||
ErrNoCompatibleInterpreter = errors.New("no compatible interpreter")
|
||||
ErrExecutionReverted = errors.New("execution reverted")
|
||||
ErrMaxCodeSizeExceeded = errors.New("max code size exceeded")
|
||||
ErrInvalidJump = errors.New("invalid jump destination")
|
||||
ErrWriteProtection = errors.New("write protection")
|
||||
ErrReturnDataOutOfBounds = errors.New("return data out of bounds")
|
||||
ErrGasUintOverflow = errors.New("gas uint64 overflow")
|
||||
)
|
||||
|
||||
// ErrStackUnderflow wraps an evm error when the items on the stack less
|
||||
// than the minimal requirement.
|
||||
type ErrStackUnderflow struct {
|
||||
stackLen int
|
||||
required int
|
||||
}
|
||||
|
||||
func (e *ErrStackUnderflow) Error() string {
|
||||
return fmt.Sprintf("stack underflow (%d <=> %d)", e.stackLen, e.required)
|
||||
}
|
||||
|
||||
// ErrStackOverflow wraps an evm error when the items on the stack exceeds
|
||||
// the maximum allowance.
|
||||
type ErrStackOverflow struct {
|
||||
stackLen int
|
||||
limit int
|
||||
}
|
||||
|
||||
func (e *ErrStackOverflow) Error() string {
|
||||
return fmt.Sprintf("stack limit reached %d (%d)", e.stackLen, e.limit)
|
||||
}
|
||||
|
||||
// ErrInvalidOpCode wraps an evm error when an invalid opcode is encountered.
|
||||
type ErrInvalidOpCode struct {
|
||||
opcode OpCode
|
||||
}
|
||||
|
||||
func (e *ErrInvalidOpCode) Error() string { return fmt.Sprintf("invalid opcode: %s", e.opcode) }
|
||||
|
@@ -17,6 +17,7 @@
|
||||
package vm
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math/big"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
@@ -67,7 +68,7 @@ func run(evm *EVM, contract *Contract, input []byte, readOnly bool) ([]byte, err
|
||||
return interpreter.Run(contract, input, readOnly)
|
||||
}
|
||||
}
|
||||
return nil, ErrNoCompatibleInterpreter
|
||||
return nil, errors.New("no compatible interpreter")
|
||||
}
|
||||
|
||||
// Context provides the EVM with auxiliary information. Once provided
|
||||
@@ -190,7 +191,6 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
|
||||
if evm.vmConfig.NoRecursion && evm.depth > 0 {
|
||||
return nil, gas, nil
|
||||
}
|
||||
|
||||
// Fail if we're trying to execute above the call depth limit
|
||||
if evm.depth > int(params.CallCreateDepth) {
|
||||
return nil, gas, ErrDepth
|
||||
@@ -199,7 +199,6 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
|
||||
if !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) {
|
||||
return nil, gas, ErrInsufficientBalance
|
||||
}
|
||||
|
||||
var (
|
||||
to = AccountRef(addr)
|
||||
snapshot = evm.StateDB.Snapshot()
|
||||
@@ -246,7 +245,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
|
||||
// when we're in homestead this also counts for code storage gas errors.
|
||||
if err != nil {
|
||||
evm.StateDB.RevertToSnapshot(snapshot)
|
||||
if err != errExecutionReverted {
|
||||
if err != ErrExecutionReverted {
|
||||
contract.UseGas(contract.Gas)
|
||||
}
|
||||
}
|
||||
@@ -264,16 +263,17 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte,
|
||||
if evm.vmConfig.NoRecursion && evm.depth > 0 {
|
||||
return nil, gas, nil
|
||||
}
|
||||
|
||||
// Fail if we're trying to execute above the call depth limit
|
||||
if evm.depth > int(params.CallCreateDepth) {
|
||||
return nil, gas, ErrDepth
|
||||
}
|
||||
// Fail if we're trying to transfer more than the available balance
|
||||
if !evm.CanTransfer(evm.StateDB, caller.Address(), value) {
|
||||
// Note although it's noop to transfer X ether to caller itself. But
|
||||
// if caller doesn't have enough balance, it would be an error to allow
|
||||
// over-charging itself. So the check here is necessary.
|
||||
if !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) {
|
||||
return nil, gas, ErrInsufficientBalance
|
||||
}
|
||||
|
||||
var (
|
||||
snapshot = evm.StateDB.Snapshot()
|
||||
to = AccountRef(caller.Address())
|
||||
@@ -286,7 +286,7 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte,
|
||||
ret, err = run(evm, contract, input, false)
|
||||
if err != nil {
|
||||
evm.StateDB.RevertToSnapshot(snapshot)
|
||||
if err != errExecutionReverted {
|
||||
if err != ErrExecutionReverted {
|
||||
contract.UseGas(contract.Gas)
|
||||
}
|
||||
}
|
||||
@@ -306,12 +306,10 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
|
||||
if evm.depth > int(params.CallCreateDepth) {
|
||||
return nil, gas, ErrDepth
|
||||
}
|
||||
|
||||
var (
|
||||
snapshot = evm.StateDB.Snapshot()
|
||||
to = AccountRef(caller.Address())
|
||||
)
|
||||
|
||||
// Initialise a new contract and make initialise the delegate values
|
||||
contract := NewContract(caller, to, nil, gas).AsDelegate()
|
||||
contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
|
||||
@@ -319,7 +317,7 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
|
||||
ret, err = run(evm, contract, input, false)
|
||||
if err != nil {
|
||||
evm.StateDB.RevertToSnapshot(snapshot)
|
||||
if err != errExecutionReverted {
|
||||
if err != ErrExecutionReverted {
|
||||
contract.UseGas(contract.Gas)
|
||||
}
|
||||
}
|
||||
@@ -338,7 +336,6 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte
|
||||
if evm.depth > int(params.CallCreateDepth) {
|
||||
return nil, gas, ErrDepth
|
||||
}
|
||||
|
||||
var (
|
||||
to = AccountRef(addr)
|
||||
snapshot = evm.StateDB.Snapshot()
|
||||
@@ -360,7 +357,7 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte
|
||||
ret, err = run(evm, contract, input, true)
|
||||
if err != nil {
|
||||
evm.StateDB.RevertToSnapshot(snapshot)
|
||||
if err != errExecutionReverted {
|
||||
if err != ErrExecutionReverted {
|
||||
contract.UseGas(contract.Gas)
|
||||
}
|
||||
}
|
||||
@@ -441,13 +438,13 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
|
||||
// when we're in homestead this also counts for code storage gas errors.
|
||||
if maxCodeSizeExceeded || (err != nil && (evm.chainRules.IsHomestead || err != ErrCodeStoreOutOfGas)) {
|
||||
evm.StateDB.RevertToSnapshot(snapshot)
|
||||
if err != errExecutionReverted {
|
||||
if err != ErrExecutionReverted {
|
||||
contract.UseGas(contract.Gas)
|
||||
}
|
||||
}
|
||||
// Assign err if contract code size exceeds the max while the err is still empty.
|
||||
if maxCodeSizeExceeded && err == nil {
|
||||
err = errMaxCodeSizeExceeded
|
||||
err = ErrMaxCodeSizeExceeded
|
||||
}
|
||||
if evm.vmConfig.Debug && evm.depth == 0 {
|
||||
evm.vmConfig.Tracer.CaptureEnd(ret, gas-contract.Gas, time.Since(start), err)
|
||||
|
@@ -46,7 +46,7 @@ func callGas(isEip150 bool, availableGas, base uint64, callCost *big.Int) (uint6
|
||||
}
|
||||
}
|
||||
if !callCost.IsUint64() {
|
||||
return 0, errGasUintOverflow
|
||||
return 0, ErrGasUintOverflow
|
||||
}
|
||||
|
||||
return callCost.Uint64(), nil
|
||||
|
@@ -36,7 +36,7 @@ func memoryGasCost(mem *Memory, newMemSize uint64) (uint64, error) {
|
||||
// overflow. The constant 0x1FFFFFFFE0 is the highest number that can be used
|
||||
// without overflowing the gas calculation.
|
||||
if newMemSize > 0x1FFFFFFFE0 {
|
||||
return 0, errGasUintOverflow
|
||||
return 0, ErrGasUintOverflow
|
||||
}
|
||||
newMemSizeWords := toWordSize(newMemSize)
|
||||
newMemSize = newMemSizeWords * 32
|
||||
@@ -72,15 +72,15 @@ func memoryCopierGas(stackpos int) gasFunc {
|
||||
// And gas for copying data, charged per word at param.CopyGas
|
||||
words, overflow := bigUint64(stack.Back(stackpos))
|
||||
if overflow {
|
||||
return 0, errGasUintOverflow
|
||||
return 0, ErrGasUintOverflow
|
||||
}
|
||||
|
||||
if words, overflow = math.SafeMul(toWordSize(words), params.CopyGas); overflow {
|
||||
return 0, errGasUintOverflow
|
||||
return 0, ErrGasUintOverflow
|
||||
}
|
||||
|
||||
if gas, overflow = math.SafeAdd(gas, words); overflow {
|
||||
return 0, errGasUintOverflow
|
||||
return 0, ErrGasUintOverflow
|
||||
}
|
||||
return gas, nil
|
||||
}
|
||||
@@ -221,7 +221,7 @@ func makeGasLog(n uint64) gasFunc {
|
||||
return func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||
requestedSize, overflow := bigUint64(stack.Back(1))
|
||||
if overflow {
|
||||
return 0, errGasUintOverflow
|
||||
return 0, ErrGasUintOverflow
|
||||
}
|
||||
|
||||
gas, err := memoryGasCost(mem, memorySize)
|
||||
@@ -230,18 +230,18 @@ func makeGasLog(n uint64) gasFunc {
|
||||
}
|
||||
|
||||
if gas, overflow = math.SafeAdd(gas, params.LogGas); overflow {
|
||||
return 0, errGasUintOverflow
|
||||
return 0, ErrGasUintOverflow
|
||||
}
|
||||
if gas, overflow = math.SafeAdd(gas, n*params.LogTopicGas); overflow {
|
||||
return 0, errGasUintOverflow
|
||||
return 0, ErrGasUintOverflow
|
||||
}
|
||||
|
||||
var memorySizeGas uint64
|
||||
if memorySizeGas, overflow = math.SafeMul(requestedSize, params.LogDataGas); overflow {
|
||||
return 0, errGasUintOverflow
|
||||
return 0, ErrGasUintOverflow
|
||||
}
|
||||
if gas, overflow = math.SafeAdd(gas, memorySizeGas); overflow {
|
||||
return 0, errGasUintOverflow
|
||||
return 0, ErrGasUintOverflow
|
||||
}
|
||||
return gas, nil
|
||||
}
|
||||
@@ -254,13 +254,13 @@ func gasSha3(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize
|
||||
}
|
||||
wordGas, overflow := bigUint64(stack.Back(1))
|
||||
if overflow {
|
||||
return 0, errGasUintOverflow
|
||||
return 0, ErrGasUintOverflow
|
||||
}
|
||||
if wordGas, overflow = math.SafeMul(toWordSize(wordGas), params.Sha3WordGas); overflow {
|
||||
return 0, errGasUintOverflow
|
||||
return 0, ErrGasUintOverflow
|
||||
}
|
||||
if gas, overflow = math.SafeAdd(gas, wordGas); overflow {
|
||||
return 0, errGasUintOverflow
|
||||
return 0, ErrGasUintOverflow
|
||||
}
|
||||
return gas, nil
|
||||
}
|
||||
@@ -288,13 +288,13 @@ func gasCreate2(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memoryS
|
||||
}
|
||||
wordGas, overflow := bigUint64(stack.Back(2))
|
||||
if overflow {
|
||||
return 0, errGasUintOverflow
|
||||
return 0, ErrGasUintOverflow
|
||||
}
|
||||
if wordGas, overflow = math.SafeMul(toWordSize(wordGas), params.Sha3WordGas); overflow {
|
||||
return 0, errGasUintOverflow
|
||||
return 0, ErrGasUintOverflow
|
||||
}
|
||||
if gas, overflow = math.SafeAdd(gas, wordGas); overflow {
|
||||
return 0, errGasUintOverflow
|
||||
return 0, ErrGasUintOverflow
|
||||
}
|
||||
return gas, nil
|
||||
}
|
||||
@@ -307,7 +307,7 @@ func gasExpFrontier(evm *EVM, contract *Contract, stack *Stack, mem *Memory, mem
|
||||
overflow bool
|
||||
)
|
||||
if gas, overflow = math.SafeAdd(gas, params.ExpGas); overflow {
|
||||
return 0, errGasUintOverflow
|
||||
return 0, ErrGasUintOverflow
|
||||
}
|
||||
return gas, nil
|
||||
}
|
||||
@@ -320,7 +320,7 @@ func gasExpEIP158(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memor
|
||||
overflow bool
|
||||
)
|
||||
if gas, overflow = math.SafeAdd(gas, params.ExpGas); overflow {
|
||||
return 0, errGasUintOverflow
|
||||
return 0, ErrGasUintOverflow
|
||||
}
|
||||
return gas, nil
|
||||
}
|
||||
@@ -347,7 +347,7 @@ func gasCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize
|
||||
}
|
||||
var overflow bool
|
||||
if gas, overflow = math.SafeAdd(gas, memoryGas); overflow {
|
||||
return 0, errGasUintOverflow
|
||||
return 0, ErrGasUintOverflow
|
||||
}
|
||||
|
||||
evm.callGasTemp, err = callGas(evm.chainRules.IsEIP150, contract.Gas, gas, stack.Back(0))
|
||||
@@ -355,7 +355,7 @@ func gasCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize
|
||||
return 0, err
|
||||
}
|
||||
if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow {
|
||||
return 0, errGasUintOverflow
|
||||
return 0, ErrGasUintOverflow
|
||||
}
|
||||
return gas, nil
|
||||
}
|
||||
@@ -373,14 +373,14 @@ func gasCallCode(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memory
|
||||
gas += params.CallValueTransferGas
|
||||
}
|
||||
if gas, overflow = math.SafeAdd(gas, memoryGas); overflow {
|
||||
return 0, errGasUintOverflow
|
||||
return 0, ErrGasUintOverflow
|
||||
}
|
||||
evm.callGasTemp, err = callGas(evm.chainRules.IsEIP150, contract.Gas, gas, stack.Back(0))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow {
|
||||
return 0, errGasUintOverflow
|
||||
return 0, ErrGasUintOverflow
|
||||
}
|
||||
return gas, nil
|
||||
}
|
||||
@@ -396,7 +396,7 @@ func gasDelegateCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, me
|
||||
}
|
||||
var overflow bool
|
||||
if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow {
|
||||
return 0, errGasUintOverflow
|
||||
return 0, ErrGasUintOverflow
|
||||
}
|
||||
return gas, nil
|
||||
}
|
||||
@@ -412,7 +412,7 @@ func gasStaticCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memo
|
||||
}
|
||||
var overflow bool
|
||||
if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow {
|
||||
return 0, errGasUintOverflow
|
||||
return 0, ErrGasUintOverflow
|
||||
}
|
||||
return gas, nil
|
||||
}
|
||||
|
@@ -39,8 +39,8 @@ func TestMemoryGasCost(t *testing.T) {
|
||||
}
|
||||
for i, tt := range tests {
|
||||
v, err := memoryGasCost(&Memory{}, tt.size)
|
||||
if (err == errGasUintOverflow) != tt.overflow {
|
||||
t.Errorf("test %d: overflow mismatch: have %v, want %v", i, err == errGasUintOverflow, tt.overflow)
|
||||
if (err == ErrGasUintOverflow) != tt.overflow {
|
||||
t.Errorf("test %d: overflow mismatch: have %v, want %v", i, err == ErrGasUintOverflow, tt.overflow)
|
||||
}
|
||||
if v != tt.cost {
|
||||
t.Errorf("test %d: gas cost mismatch: have %v, want %v", i, v, tt.cost)
|
||||
|
@@ -17,7 +17,6 @@
|
||||
package vm
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
@@ -28,13 +27,8 @@ import (
|
||||
)
|
||||
|
||||
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")
|
||||
errInvalidJump = errors.New("evm: invalid jump destination")
|
||||
bigZero = new(big.Int)
|
||||
tt255 = math.BigPow(2, 255)
|
||||
)
|
||||
|
||||
func opAdd(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) {
|
||||
@@ -468,7 +462,7 @@ func opReturnDataCopy(pc *uint64, interpreter *EVMInterpreter, callContext *call
|
||||
defer interpreter.intPool.put(memOffset, dataOffset, length, end)
|
||||
|
||||
if !end.IsUint64() || uint64(len(interpreter.returnData)) < end.Uint64() {
|
||||
return nil, errReturnDataOutOfBounds
|
||||
return nil, ErrReturnDataOutOfBounds
|
||||
}
|
||||
callContext.memory.Set(memOffset.Uint64(), length.Uint64(), interpreter.returnData[dataOffset.Uint64():end.Uint64()])
|
||||
|
||||
@@ -643,7 +637,7 @@ func opSstore(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]
|
||||
func opJump(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) {
|
||||
pos := callContext.stack.pop()
|
||||
if !callContext.contract.validJumpdest(pos) {
|
||||
return nil, errInvalidJump
|
||||
return nil, ErrInvalidJump
|
||||
}
|
||||
*pc = pos.Uint64()
|
||||
|
||||
@@ -655,7 +649,7 @@ func opJumpi(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]b
|
||||
pos, cond := callContext.stack.pop(), callContext.stack.pop()
|
||||
if cond.Sign() != 0 {
|
||||
if !callContext.contract.validJumpdest(pos) {
|
||||
return nil, errInvalidJump
|
||||
return nil, ErrInvalidJump
|
||||
}
|
||||
*pc = pos.Uint64()
|
||||
} else {
|
||||
@@ -712,7 +706,7 @@ func opCreate(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]
|
||||
callContext.contract.Gas += returnGas
|
||||
interpreter.intPool.put(value, offset, size)
|
||||
|
||||
if suberr == errExecutionReverted {
|
||||
if suberr == ErrExecutionReverted {
|
||||
return res, nil
|
||||
}
|
||||
return nil, nil
|
||||
@@ -740,7 +734,7 @@ func opCreate2(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([
|
||||
callContext.contract.Gas += returnGas
|
||||
interpreter.intPool.put(endowment, offset, size, salt)
|
||||
|
||||
if suberr == errExecutionReverted {
|
||||
if suberr == ErrExecutionReverted {
|
||||
return res, nil
|
||||
}
|
||||
return nil, nil
|
||||
@@ -766,7 +760,7 @@ func opCall(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]by
|
||||
} else {
|
||||
callContext.stack.push(interpreter.intPool.get().SetUint64(1))
|
||||
}
|
||||
if err == nil || err == errExecutionReverted {
|
||||
if err == nil || err == ErrExecutionReverted {
|
||||
callContext.memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
|
||||
}
|
||||
callContext.contract.Gas += returnGas
|
||||
@@ -795,7 +789,7 @@ func opCallCode(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) (
|
||||
} else {
|
||||
callContext.stack.push(interpreter.intPool.get().SetUint64(1))
|
||||
}
|
||||
if err == nil || err == errExecutionReverted {
|
||||
if err == nil || err == ErrExecutionReverted {
|
||||
callContext.memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
|
||||
}
|
||||
callContext.contract.Gas += returnGas
|
||||
@@ -820,7 +814,7 @@ func opDelegateCall(pc *uint64, interpreter *EVMInterpreter, callContext *callCt
|
||||
} else {
|
||||
callContext.stack.push(interpreter.intPool.get().SetUint64(1))
|
||||
}
|
||||
if err == nil || err == errExecutionReverted {
|
||||
if err == nil || err == ErrExecutionReverted {
|
||||
callContext.memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
|
||||
}
|
||||
callContext.contract.Gas += returnGas
|
||||
@@ -845,7 +839,7 @@ func opStaticCall(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx)
|
||||
} else {
|
||||
callContext.stack.push(interpreter.intPool.get().SetUint64(1))
|
||||
}
|
||||
if err == nil || err == errExecutionReverted {
|
||||
if err == nil || err == ErrExecutionReverted {
|
||||
callContext.memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
|
||||
}
|
||||
callContext.contract.Gas += returnGas
|
||||
|
@@ -17,7 +17,6 @@
|
||||
package vm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"hash"
|
||||
"sync/atomic"
|
||||
|
||||
@@ -137,7 +136,7 @@ func NewEVMInterpreter(evm *EVM, cfg Config) *EVMInterpreter {
|
||||
//
|
||||
// It's important to note that any errors returned by the interpreter should be
|
||||
// considered a revert-and-consume-all-gas operation except for
|
||||
// errExecutionReverted which means revert-and-keep-gas-left.
|
||||
// ErrExecutionReverted which means revert-and-keep-gas-left.
|
||||
func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (ret []byte, err error) {
|
||||
if in.intPool == nil {
|
||||
in.intPool = poolOfIntPools.get()
|
||||
@@ -223,13 +222,13 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
|
||||
op = contract.GetOp(pc)
|
||||
operation := in.cfg.JumpTable[op]
|
||||
if !operation.valid {
|
||||
return nil, fmt.Errorf("invalid opcode 0x%x", int(op))
|
||||
return nil, &ErrInvalidOpCode{opcode: op}
|
||||
}
|
||||
// Validate stack
|
||||
if sLen := stack.len(); sLen < operation.minStack {
|
||||
return nil, fmt.Errorf("stack underflow (%d <=> %d)", sLen, operation.minStack)
|
||||
return nil, &ErrStackUnderflow{stackLen: sLen, required: operation.minStack}
|
||||
} else if sLen > operation.maxStack {
|
||||
return nil, fmt.Errorf("stack limit reached %d (%d)", sLen, operation.maxStack)
|
||||
return nil, &ErrStackOverflow{stackLen: sLen, limit: operation.maxStack}
|
||||
}
|
||||
// If the operation is valid, enforce and write restrictions
|
||||
if in.readOnly && in.evm.chainRules.IsByzantium {
|
||||
@@ -239,7 +238,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
|
||||
// account to the others means the state is modified and should also
|
||||
// return with an error.
|
||||
if operation.writes || (op == CALL && stack.Back(2).Sign() != 0) {
|
||||
return nil, errWriteProtection
|
||||
return nil, ErrWriteProtection
|
||||
}
|
||||
}
|
||||
// Static portion of gas
|
||||
@@ -256,12 +255,12 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
|
||||
if operation.memorySize != nil {
|
||||
memSize, overflow := operation.memorySize(stack)
|
||||
if overflow {
|
||||
return nil, errGasUintOverflow
|
||||
return nil, ErrGasUintOverflow
|
||||
}
|
||||
// memory is expanded in words of 32 bytes. Gas
|
||||
// is also calculated in words.
|
||||
if memorySize, overflow = math.SafeMul(toWordSize(memSize), 32); overflow {
|
||||
return nil, errGasUintOverflow
|
||||
return nil, ErrGasUintOverflow
|
||||
}
|
||||
}
|
||||
// Dynamic portion of gas
|
||||
@@ -301,7 +300,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
|
||||
case err != nil:
|
||||
return nil, err
|
||||
case operation.reverts:
|
||||
return res, errExecutionReverted
|
||||
return res, ErrExecutionReverted
|
||||
case operation.halts:
|
||||
return res, nil
|
||||
case !operation.jumps:
|
||||
|
@@ -17,8 +17,6 @@
|
||||
package vm
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
@@ -29,8 +27,6 @@ type (
|
||||
memorySizeFunc func(*Stack) (size uint64, overflow bool)
|
||||
)
|
||||
|
||||
var errGasUintOverflow = errors.New("gas uint64 overflow")
|
||||
|
||||
type operation struct {
|
||||
// execute is the operation function
|
||||
execute executionFunc
|
||||
|
@@ -18,6 +18,7 @@ package vm
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/big"
|
||||
@@ -29,6 +30,8 @@ import (
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
)
|
||||
|
||||
var errTraceLimitReached = errors.New("the number of logs reached the specified limit")
|
||||
|
||||
// Storage represents a contract's storage.
|
||||
type Storage map[common.Hash]common.Hash
|
||||
|
||||
@@ -140,7 +143,7 @@ func (l *StructLogger) CaptureStart(from common.Address, to common.Address, crea
|
||||
func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, contract *Contract, depth int, err error) error {
|
||||
// check if already accumulated the specified number of logs
|
||||
if l.cfg.Limit != 0 && l.cfg.Limit <= len(l.logs) {
|
||||
return ErrTraceLimitReached
|
||||
return errTraceLimitReached
|
||||
}
|
||||
|
||||
// initialise new changed values storage container for this contract
|
||||
|
@@ -389,7 +389,7 @@ var opCodeToString = map[OpCode]string{
|
||||
func (op OpCode) String() string {
|
||||
str := opCodeToString[op]
|
||||
if len(str) == 0 {
|
||||
return fmt.Sprintf("Missing opcode 0x%x", int(op))
|
||||
return fmt.Sprintf("opcode 0x%x not defined", int(op))
|
||||
}
|
||||
|
||||
return str
|
||||
|
Reference in New Issue
Block a user