mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-24 13:46:43 +00:00
core/vm, eth/tracers: move dynamic gas and memory handling to opcode handlers
This commit is contained in:
parent
e3ebb95289
commit
cbe64f51c7
9 changed files with 978 additions and 297 deletions
2
cmd/evm/testdata/evmrun/7.out.2.txt
vendored
2
cmd/evm/testdata/evmrun/7.out.2.txt
vendored
|
|
@ -910,7 +910,7 @@ Pre-execution info:
|
|||
| 20 | PUSH1 | 3 | 19900 |[0x0,0x0,0x0,0x0,0x0] |
|
||||
| 22 | GAS | 2 | 19900 |[0x0,0x0,0x0,0x0,0x0,0xf9] |
|
||||
| 23 | CALLCODE | 100 | 19900 |[0x0,0x0,0x0,0x0,0x0,0xf9,0x885] |
|
||||
Error: out of gas: out of gas
|
||||
Error: at pc=23, op=242: out of gas: out of gas
|
||||
| 1786 | POP | 2 | 0 |[0x94a843a7335fc63be036fbdecc40b1365f3c5f26,0x0] |
|
||||
| 1787 | POP | 2 | 0 |[0x94a843a7335fc63be036fbdecc40b1365f3c5f26] |
|
||||
| 1788 | STOP | 0 | 0 | [] |
|
||||
|
|
|
|||
|
|
@ -217,6 +217,17 @@ type Hooks struct {
|
|||
OnBlockHashRead BlockHashReadHook
|
||||
}
|
||||
|
||||
// HooksVM returns if any of the VM events are being hooked
|
||||
func (h *Hooks) HooksVM() bool {
|
||||
return h.OnTxStart != nil ||
|
||||
h.OnTxEnd != nil ||
|
||||
h.OnEnter != nil ||
|
||||
h.OnExit != nil ||
|
||||
h.OnOpcode != nil ||
|
||||
h.OnFault != nil ||
|
||||
h.OnGasChange != nil
|
||||
}
|
||||
|
||||
// HooksState returns if any of the state events are being hooked
|
||||
func (h *Hooks) HooksState() bool {
|
||||
return h.OnBalanceChange != nil ||
|
||||
|
|
|
|||
|
|
@ -25,29 +25,26 @@ import (
|
|||
|
||||
// calcMemSize64 calculates the required memory size, and returns
|
||||
// the size and whether the result overflowed uint64
|
||||
func calcMemSize64(off, l *uint256.Int) (uint64, bool) {
|
||||
if !l.IsUint64() {
|
||||
return 0, true
|
||||
func calcMemSize64(off, len *uint256.Int) (uint64, bool) {
|
||||
lenOverflowed := (len[1] | len[2] | len[3]) != 0
|
||||
// if length is zero, memsize is always zero, regardless of offset
|
||||
if len[0] == 0 {
|
||||
return 0, lenOverflowed
|
||||
}
|
||||
return calcMemSize64WithUint(off, l.Uint64())
|
||||
offOverflowed := (off[1] | off[2] | off[3]) != 0
|
||||
memSize := off[0] + len[0]
|
||||
// if value < either of it's parts, then it overflowed
|
||||
return memSize, lenOverflowed || offOverflowed || memSize < off[0]
|
||||
}
|
||||
|
||||
// calcMemSize64WithUint calculates the required memory size, and returns
|
||||
// the size and whether the result overflowed uint64
|
||||
// Identical to calcMemSize64, but length is a uint64
|
||||
func calcMemSize64WithUint(off *uint256.Int, length64 uint64) (uint64, bool) {
|
||||
// if length is zero, memsize is always zero, regardless of offset
|
||||
if length64 == 0 {
|
||||
return 0, false
|
||||
}
|
||||
// Check that offset doesn't overflow
|
||||
offset64, overflow := off.Uint64WithOverflow()
|
||||
if overflow {
|
||||
return 0, true
|
||||
}
|
||||
val := offset64 + length64
|
||||
// Identical to calcMemSize64, but length is a uint64 and assumed to be non-zero
|
||||
func calcMemSize64WithUint(offset *uint256.Int, length64 uint64) (uint64, bool) {
|
||||
overflowed := (offset[1] | offset[2] | offset[3]) != 0
|
||||
memSize := offset[0] + length64
|
||||
// if value < either of it's parts, then it overflowed
|
||||
return val, val < offset64
|
||||
return memSize, overflowed || memSize < length64
|
||||
}
|
||||
|
||||
// getData returns a slice from the data based on the start and size and pads
|
||||
|
|
|
|||
161
core/vm/eips.go
161
core/vm/eips.go
|
|
@ -117,45 +117,45 @@ func opChainID(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]
|
|||
// enable2200 applies EIP-2200 (Rebalance net-metered SSTORE)
|
||||
func enable2200(jt *JumpTable) {
|
||||
jt[SLOAD].constantGas = params.SloadGasEIP2200
|
||||
jt[SSTORE].dynamicGas = gasSStoreEIP2200
|
||||
jt[SSTORE].execute = opSstoreEIP2200
|
||||
}
|
||||
|
||||
// enable2929 enables "EIP-2929: Gas cost increases for state access opcodes"
|
||||
// https://eips.ethereum.org/EIPS/eip-2929
|
||||
func enable2929(jt *JumpTable) {
|
||||
jt[SSTORE].dynamicGas = gasSStoreEIP2929
|
||||
jt[SSTORE].execute = opSstoreEIP2929
|
||||
|
||||
jt[SLOAD].constantGas = 0
|
||||
jt[SLOAD].dynamicGas = gasSLoadEIP2929
|
||||
jt[SLOAD].execute = opSLoadEIP2929
|
||||
|
||||
jt[EXTCODECOPY].constantGas = params.WarmStorageReadCostEIP2929
|
||||
jt[EXTCODECOPY].dynamicGas = gasExtCodeCopyEIP2929
|
||||
jt[EXTCODECOPY].execute = opExtCodeCopyEIP2929
|
||||
|
||||
jt[EXTCODESIZE].constantGas = params.WarmStorageReadCostEIP2929
|
||||
jt[EXTCODESIZE].dynamicGas = gasEip2929AccountCheck
|
||||
jt[EXTCODESIZE].execute = opExtCodeSizeEIP2929
|
||||
|
||||
jt[EXTCODEHASH].constantGas = params.WarmStorageReadCostEIP2929
|
||||
jt[EXTCODEHASH].dynamicGas = gasEip2929AccountCheck
|
||||
jt[EXTCODEHASH].execute = opExtCodeHashEIP2929
|
||||
|
||||
jt[BALANCE].constantGas = params.WarmStorageReadCostEIP2929
|
||||
jt[BALANCE].dynamicGas = gasEip2929AccountCheck
|
||||
jt[BALANCE].execute = opBalanceEIP2929
|
||||
|
||||
jt[CALL].constantGas = params.WarmStorageReadCostEIP2929
|
||||
jt[CALL].dynamicGas = gasCallEIP2929
|
||||
jt[CALL].execute = opCallEIP2929
|
||||
|
||||
jt[CALLCODE].constantGas = params.WarmStorageReadCostEIP2929
|
||||
jt[CALLCODE].dynamicGas = gasCallCodeEIP2929
|
||||
jt[CALLCODE].execute = opCallCodeEIP2929
|
||||
|
||||
jt[STATICCALL].constantGas = params.WarmStorageReadCostEIP2929
|
||||
jt[STATICCALL].dynamicGas = gasStaticCallEIP2929
|
||||
jt[STATICCALL].execute = opStaticCallEIP2929
|
||||
|
||||
jt[DELEGATECALL].constantGas = params.WarmStorageReadCostEIP2929
|
||||
jt[DELEGATECALL].dynamicGas = gasDelegateCallEIP2929
|
||||
jt[DELEGATECALL].execute = opDelegateCallEIP2929
|
||||
|
||||
// This was previously part of the dynamic cost, but we're using it as a constantGas
|
||||
// factor here
|
||||
jt[SELFDESTRUCT].constantGas = params.SelfdestructGasEIP150
|
||||
jt[SELFDESTRUCT].dynamicGas = gasSelfdestructEIP2929
|
||||
jt[SELFDESTRUCT].execute = opSelfdestructEIP2929
|
||||
}
|
||||
|
||||
// enable3529 enabled "EIP-3529: Reduction in refunds":
|
||||
|
|
@ -163,8 +163,8 @@ func enable2929(jt *JumpTable) {
|
|||
// - Reduces refunds for SSTORE
|
||||
// - Reduces max refunds to 20% gas
|
||||
func enable3529(jt *JumpTable) {
|
||||
jt[SSTORE].dynamicGas = gasSStoreEIP3529
|
||||
jt[SELFDESTRUCT].dynamicGas = gasSelfdestructEIP3529
|
||||
jt[SSTORE].execute = opSstoreEIP3529
|
||||
jt[SELFDESTRUCT].execute = opSelfdestructEIP3529
|
||||
}
|
||||
|
||||
// enable3198 applies EIP-3198 (BASEFEE Opcode)
|
||||
|
|
@ -245,8 +245,8 @@ func opPush0(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]by
|
|||
// enable3860 enables "EIP-3860: Limit and meter initcode"
|
||||
// https://eips.ethereum.org/EIPS/eip-3860
|
||||
func enable3860(jt *JumpTable) {
|
||||
jt[CREATE].dynamicGas = gasCreateEip3860
|
||||
jt[CREATE2].dynamicGas = gasCreate2Eip3860
|
||||
jt[CREATE].execute = opCreateEIP3860
|
||||
jt[CREATE2].execute = opCreate2EIP3860
|
||||
}
|
||||
|
||||
// enable5656 enables EIP-5656 (MCOPY opcode)
|
||||
|
|
@ -255,15 +255,26 @@ func enable5656(jt *JumpTable) {
|
|||
jt[MCOPY] = &operation{
|
||||
execute: opMcopy,
|
||||
constantGas: GasFastestStep,
|
||||
dynamicGas: gasMcopy,
|
||||
minStack: minStack(3, 0),
|
||||
maxStack: maxStack(3, 0),
|
||||
memorySize: memoryMcopy,
|
||||
}
|
||||
}
|
||||
|
||||
// opMcopy implements the MCOPY opcode (https://eips.ethereum.org/EIPS/eip-5656)
|
||||
func opMcopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
memorySize, err := calculateMemorySize(memoryMcopy, scope.Stack, scope.Memory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dynamicCost, err := gasMcopy(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, memorySize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
scope.Memory.Resize(memorySize)
|
||||
|
||||
var (
|
||||
dst = scope.Stack.pop()
|
||||
src = scope.Stack.pop()
|
||||
|
|
@ -334,8 +345,7 @@ func enable7516(jt *JumpTable) {
|
|||
// enable6780 applies EIP-6780 (deactivate SELFDESTRUCT)
|
||||
func enable6780(jt *JumpTable) {
|
||||
jt[SELFDESTRUCT] = &operation{
|
||||
execute: opSelfdestruct6780,
|
||||
dynamicGas: gasSelfdestructEIP3529,
|
||||
execute: opSelfdestructEIP6780,
|
||||
constantGas: params.SelfdestructGasEIP150,
|
||||
minStack: minStack(1, 0),
|
||||
maxStack: maxStack(1, 0),
|
||||
|
|
@ -343,6 +353,19 @@ func enable6780(jt *JumpTable) {
|
|||
}
|
||||
|
||||
func opExtCodeCopyEIP4762(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
memorySize, err := calculateMemorySize(memoryExtCodeCopy, scope.Stack, scope.Memory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dynamicCost, err := gasExtCodeCopyEIP4762(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, memorySize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
scope.Memory.Resize(memorySize)
|
||||
|
||||
var (
|
||||
stack = scope.Stack
|
||||
a = stack.pop()
|
||||
|
|
@ -425,112 +448,90 @@ func makePushEIP4762(size uint64, pushByteSize int) executionFunc {
|
|||
|
||||
func enable4762(jt *JumpTable) {
|
||||
jt[SSTORE] = &operation{
|
||||
dynamicGas: gasSStore4762,
|
||||
execute: opSstore,
|
||||
minStack: minStack(2, 0),
|
||||
maxStack: maxStack(2, 0),
|
||||
execute: opSstoreEIP4762,
|
||||
minStack: minStack(2, 0),
|
||||
maxStack: maxStack(2, 0),
|
||||
}
|
||||
jt[SLOAD] = &operation{
|
||||
dynamicGas: gasSLoad4762,
|
||||
execute: opSload,
|
||||
minStack: minStack(1, 1),
|
||||
maxStack: maxStack(1, 1),
|
||||
execute: opSLoadEIP4762,
|
||||
minStack: minStack(1, 1),
|
||||
maxStack: maxStack(1, 1),
|
||||
}
|
||||
|
||||
jt[BALANCE] = &operation{
|
||||
execute: opBalance,
|
||||
dynamicGas: gasBalance4762,
|
||||
minStack: minStack(1, 1),
|
||||
maxStack: maxStack(1, 1),
|
||||
execute: opBalanceEIP4762,
|
||||
minStack: minStack(1, 1),
|
||||
maxStack: maxStack(1, 1),
|
||||
}
|
||||
|
||||
jt[EXTCODESIZE] = &operation{
|
||||
execute: opExtCodeSize,
|
||||
dynamicGas: gasExtCodeSize4762,
|
||||
minStack: minStack(1, 1),
|
||||
maxStack: maxStack(1, 1),
|
||||
execute: opExtCodeSizeEIP4762,
|
||||
minStack: minStack(1, 1),
|
||||
maxStack: maxStack(1, 1),
|
||||
}
|
||||
|
||||
jt[EXTCODEHASH] = &operation{
|
||||
execute: opExtCodeHash,
|
||||
dynamicGas: gasExtCodeHash4762,
|
||||
minStack: minStack(1, 1),
|
||||
maxStack: maxStack(1, 1),
|
||||
execute: opExtCodeHashEIP4762,
|
||||
minStack: minStack(1, 1),
|
||||
maxStack: maxStack(1, 1),
|
||||
}
|
||||
|
||||
jt[EXTCODECOPY] = &operation{
|
||||
execute: opExtCodeCopyEIP4762,
|
||||
dynamicGas: gasExtCodeCopyEIP4762,
|
||||
minStack: minStack(4, 0),
|
||||
maxStack: maxStack(4, 0),
|
||||
memorySize: memoryExtCodeCopy,
|
||||
execute: opExtCodeCopyEIP4762,
|
||||
minStack: minStack(4, 0),
|
||||
maxStack: maxStack(4, 0),
|
||||
}
|
||||
|
||||
jt[CODECOPY] = &operation{
|
||||
execute: opCodeCopy,
|
||||
execute: opCodeCopyEIP4762,
|
||||
constantGas: GasFastestStep,
|
||||
dynamicGas: gasCodeCopyEip4762,
|
||||
minStack: minStack(3, 0),
|
||||
maxStack: maxStack(3, 0),
|
||||
memorySize: memoryCodeCopy,
|
||||
}
|
||||
|
||||
jt[SELFDESTRUCT] = &operation{
|
||||
execute: opSelfdestruct6780,
|
||||
dynamicGas: gasSelfdestructEIP4762,
|
||||
execute: opSelfdestructEIP4762,
|
||||
constantGas: params.SelfdestructGasEIP150,
|
||||
minStack: minStack(1, 0),
|
||||
maxStack: maxStack(1, 0),
|
||||
}
|
||||
|
||||
jt[CREATE] = &operation{
|
||||
execute: opCreate,
|
||||
execute: opCreateEIP3860,
|
||||
constantGas: params.CreateNGasEip4762,
|
||||
dynamicGas: gasCreateEip3860,
|
||||
minStack: minStack(3, 1),
|
||||
maxStack: maxStack(3, 1),
|
||||
memorySize: memoryCreate,
|
||||
}
|
||||
|
||||
jt[CREATE2] = &operation{
|
||||
execute: opCreate2,
|
||||
execute: opCreate2EIP3860,
|
||||
constantGas: params.CreateNGasEip4762,
|
||||
dynamicGas: gasCreate2Eip3860,
|
||||
minStack: minStack(4, 1),
|
||||
maxStack: maxStack(4, 1),
|
||||
memorySize: memoryCreate2,
|
||||
}
|
||||
|
||||
jt[CALL] = &operation{
|
||||
execute: opCall,
|
||||
dynamicGas: gasCallEIP4762,
|
||||
minStack: minStack(7, 1),
|
||||
maxStack: maxStack(7, 1),
|
||||
memorySize: memoryCall,
|
||||
execute: opCallEIP4762,
|
||||
minStack: minStack(7, 1),
|
||||
maxStack: maxStack(7, 1),
|
||||
}
|
||||
|
||||
jt[CALLCODE] = &operation{
|
||||
execute: opCallCode,
|
||||
dynamicGas: gasCallCodeEIP4762,
|
||||
minStack: minStack(7, 1),
|
||||
maxStack: maxStack(7, 1),
|
||||
memorySize: memoryCall,
|
||||
execute: opCallCodeEIP4762,
|
||||
minStack: minStack(7, 1),
|
||||
maxStack: maxStack(7, 1),
|
||||
}
|
||||
|
||||
jt[STATICCALL] = &operation{
|
||||
execute: opStaticCall,
|
||||
dynamicGas: gasStaticCallEIP4762,
|
||||
minStack: minStack(6, 1),
|
||||
maxStack: maxStack(6, 1),
|
||||
memorySize: memoryStaticCall,
|
||||
execute: opStaticCallEIP4762,
|
||||
minStack: minStack(6, 1),
|
||||
maxStack: maxStack(6, 1),
|
||||
}
|
||||
|
||||
jt[DELEGATECALL] = &operation{
|
||||
execute: opDelegateCall,
|
||||
dynamicGas: gasDelegateCallEIP4762,
|
||||
minStack: minStack(6, 1),
|
||||
maxStack: maxStack(6, 1),
|
||||
memorySize: memoryDelegateCall,
|
||||
execute: opDelegateCallEIP4762,
|
||||
minStack: minStack(6, 1),
|
||||
maxStack: maxStack(6, 1),
|
||||
}
|
||||
|
||||
jt[PUSH1] = &operation{
|
||||
|
|
@ -551,8 +552,8 @@ func enable4762(jt *JumpTable) {
|
|||
|
||||
// enable7702 the EIP-7702 changes to support delegation designators.
|
||||
func enable7702(jt *JumpTable) {
|
||||
jt[CALL].dynamicGas = gasCallEIP7702
|
||||
jt[CALLCODE].dynamicGas = gasCallCodeEIP7702
|
||||
jt[STATICCALL].dynamicGas = gasStaticCallEIP7702
|
||||
jt[DELEGATECALL].dynamicGas = gasDelegateCallEIP7702
|
||||
jt[CALL].execute = opCallEIP7702
|
||||
jt[CALLCODE].execute = opCallCodeEIP7702
|
||||
jt[STATICCALL].execute = opStaticCallEIP7702
|
||||
jt[DELEGATECALL].execute = opDelegateCallEIP7702
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
package vm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
|
|
@ -26,6 +27,19 @@ import (
|
|||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
||||
// calculateMemorySize calculates the required memory size
|
||||
// it is important that this function is inlinable
|
||||
func calculateMemorySize(memF memorySizeFunc, stack *Stack, mem *Memory) (uint64, error) {
|
||||
memSize, overflow := memF(stack)
|
||||
// memory is expanded in words of 32 bytes. Gas
|
||||
// is also calculated in words.
|
||||
if overflow || memSize > math.MaxUint64-31 {
|
||||
return 0, ErrGasUintOverflow
|
||||
}
|
||||
memorySize := ((memSize + 31) / 32) * 32
|
||||
return memorySize, nil
|
||||
}
|
||||
|
||||
func opAdd(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
x, y := scope.Stack.pop(), scope.Stack.peek()
|
||||
y.Add(&x, y)
|
||||
|
|
@ -68,6 +82,30 @@ func opSmod(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byt
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func opExpEIP158(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
dynamicCost, err := gasExpEIP158(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, 0)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
|
||||
return opExp(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opExpFrontier(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
dynamicCost, err := gasExpFrontier(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, 0)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
|
||||
return opExp(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opExp(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
base, exponent := scope.Stack.pop(), scope.Stack.peek()
|
||||
exponent.Exp(&base, exponent)
|
||||
|
|
@ -230,6 +268,19 @@ func opSAR(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte
|
|||
}
|
||||
|
||||
func opKeccak256(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
memorySize, err := calculateMemorySize(memoryKeccak256, scope.Stack, scope.Memory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dynamicCost, err := gasKeccak256(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, memorySize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
scope.Memory.Resize(memorySize)
|
||||
|
||||
offset, size := scope.Stack.pop(), scope.Stack.peek()
|
||||
data := scope.Memory.GetPtr(offset.Uint64(), size.Uint64())
|
||||
|
||||
|
|
@ -250,6 +301,30 @@ func opAddress(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func opBalanceEIP4762(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
dynamicCost, err := gasBalance4762(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, 0)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
|
||||
return opBalance(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opBalanceEIP2929(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
dynamicCost, err := gasEip2929AccountCheck(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, 0)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
|
||||
return opBalance(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opBalance(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
slot := scope.Stack.peek()
|
||||
address := common.Address(slot.Bytes20())
|
||||
|
|
@ -289,6 +364,19 @@ func opCallDataSize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext
|
|||
}
|
||||
|
||||
func opCallDataCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
memorySize, err := calculateMemorySize(memoryCallDataCopy, scope.Stack, scope.Memory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dynamicCost, err := gasCallDataCopy(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, memorySize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
scope.Memory.Resize(memorySize)
|
||||
|
||||
var (
|
||||
memOffset = scope.Stack.pop()
|
||||
dataOffset = scope.Stack.pop()
|
||||
|
|
@ -312,6 +400,19 @@ func opReturnDataSize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeConte
|
|||
}
|
||||
|
||||
func opReturnDataCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
memorySize, err := calculateMemorySize(memoryReturnDataCopy, scope.Stack, scope.Memory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dynamicCost, err := gasReturnDataCopy(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, memorySize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
scope.Memory.Resize(memorySize)
|
||||
|
||||
var (
|
||||
memOffset = scope.Stack.pop()
|
||||
dataOffset = scope.Stack.pop()
|
||||
|
|
@ -333,6 +434,28 @@ func opReturnDataCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeConte
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func opExtCodeSizeEIP4762(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
dynamicCost, err := gasExtCodeSize4762(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, 0)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
return opExtCodeSize(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opExtCodeSizeEIP2929(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
dynamicCost, err := gasEip2929AccountCheck(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, 0)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
return opExtCodeSize(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opExtCodeSize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
slot := scope.Stack.peek()
|
||||
slot.SetUint64(uint64(interpreter.evm.StateDB.GetCodeSize(slot.Bytes20())))
|
||||
|
|
@ -344,6 +467,38 @@ func opCodeSize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func opCodeCopyEIP4762(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
memorySize, err := calculateMemorySize(memoryCodeCopy, scope.Stack, scope.Memory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dynamicCost, err := gasCodeCopyEip4762(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, memorySize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
scope.Memory.Resize(memorySize)
|
||||
return opCodeCopy(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opCodeCopyFrontier(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
memorySize, err := calculateMemorySize(memoryCodeCopy, scope.Stack, scope.Memory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dynamicCost, err := gasCodeCopy(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, memorySize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
scope.Memory.Resize(memorySize)
|
||||
return opCodeCopy(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
var (
|
||||
memOffset = scope.Stack.pop()
|
||||
|
|
@ -360,6 +515,38 @@ func opCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func opExtCodeCopyEIP2929(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
memorySize, err := calculateMemorySize(memoryExtCodeCopy, scope.Stack, scope.Memory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dynamicCost, err := gasExtCodeCopyEIP2929(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, memorySize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
scope.Memory.Resize(memorySize)
|
||||
return opExtCodeCopy(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opExtCodeCopyFrontier(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
memorySize, err := calculateMemorySize(memoryExtCodeCopy, scope.Stack, scope.Memory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dynamicCost, err := gasExtCodeCopy(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, memorySize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
scope.Memory.Resize(memorySize)
|
||||
return opExtCodeCopy(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
var (
|
||||
stack = scope.Stack
|
||||
|
|
@ -380,6 +567,28 @@ func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext)
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func opExtCodeHashEIP4762(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
dynamicCost, err := gasExtCodeHash4762(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, 0)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
return opExtCodeHash(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opExtCodeHashEIP2929(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
dynamicCost, err := gasEip2929AccountCheck(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, 0)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
return opExtCodeHash(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
// opExtCodeHash returns the code hash of a specified account.
|
||||
// There are several cases when the function is called, while we can relay everything
|
||||
// to `state.GetCodeHash` function to ensure the correctness.
|
||||
|
|
@ -492,6 +701,19 @@ func opPop(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte
|
|||
}
|
||||
|
||||
func opMload(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
memorySize, err := calculateMemorySize(memoryMLoad, scope.Stack, scope.Memory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dynamicCost, err := gasMLoad(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, memorySize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
scope.Memory.Resize(memorySize)
|
||||
|
||||
v := scope.Stack.peek()
|
||||
offset := v.Uint64()
|
||||
v.SetBytes(scope.Memory.GetPtr(offset, 32))
|
||||
|
|
@ -499,17 +721,65 @@ func opMload(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]by
|
|||
}
|
||||
|
||||
func opMstore(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
memorySize, err := calculateMemorySize(memoryMStore, scope.Stack, scope.Memory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dynamicCost, err := gasMStore(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, memorySize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
scope.Memory.Resize(memorySize)
|
||||
|
||||
mStart, val := scope.Stack.pop(), scope.Stack.pop()
|
||||
scope.Memory.Set32(mStart.Uint64(), &val)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opMstore8(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
memorySize, err := calculateMemorySize(memoryMStore8, scope.Stack, scope.Memory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dynamicCost, err := gasMStore8(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, memorySize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
scope.Memory.Resize(memorySize)
|
||||
|
||||
off, val := scope.Stack.pop(), scope.Stack.pop()
|
||||
scope.Memory.store[off.Uint64()] = byte(val.Uint64())
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func opSLoadEIP4762(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
dynamicCost, err := gasSLoad4762(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, 0)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
return opSload(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opSLoadEIP2929(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
dynamicCost, err := gasSLoadEIP2929(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, 0)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
return opSload(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opSload(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
loc := scope.Stack.peek()
|
||||
hash := common.Hash(loc.Bytes32())
|
||||
|
|
@ -518,6 +788,66 @@ func opSload(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]by
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func opSstoreEIP4762(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
dynamicCost, err := gasSStore4762(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, 0)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
|
||||
return opSstore(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opSstoreEIP3529(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
dynamicCost, err := gasSStoreEIP3529(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, 0)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
|
||||
return opSstore(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opSstoreEIP2200(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
dynamicCost, err := gasSStoreEIP2200(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, 0)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
|
||||
return opSstore(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opSstoreEIP2929(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
dynamicCost, err := gasSStoreEIP2929(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, 0)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
|
||||
return opSstore(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opSstoreFrontier(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
dynamicCost, err := gasSStore(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, 0)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
|
||||
return opSstore(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opSstore(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
if interpreter.readOnly {
|
||||
return nil, ErrWriteProtection
|
||||
|
|
@ -653,10 +983,45 @@ func opSwap16(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]b
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func opCreateEIP3860(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
memorySize, err := calculateMemorySize(memoryCreate, scope.Stack, scope.Memory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dynamicCost, err := gasCreateEip3860(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, memorySize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
scope.Memory.Resize(memorySize)
|
||||
|
||||
return opCreate(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opCreateFrontier(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
memorySize, err := calculateMemorySize(memoryCreate, scope.Stack, scope.Memory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dynamicCost, err := gasCreate(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, memorySize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
scope.Memory.Resize(memorySize)
|
||||
|
||||
return opCreate(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opCreate(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
if interpreter.readOnly {
|
||||
return nil, ErrWriteProtection
|
||||
}
|
||||
|
||||
var (
|
||||
value = scope.Stack.pop()
|
||||
offset, size = scope.Stack.pop(), scope.Stack.pop()
|
||||
|
|
@ -696,6 +1061,40 @@ func opCreate(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]b
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func opCreate2EIP3860(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
memorySize, err := calculateMemorySize(memoryCreate2, scope.Stack, scope.Memory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dynamicCost, err := gasCreate2Eip3860(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, memorySize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
scope.Memory.Resize(memorySize)
|
||||
|
||||
return opCreate2(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opCreate2Constantinople(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
memorySize, err := calculateMemorySize(memoryCreate2, scope.Stack, scope.Memory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dynamicCost, err := gasCreate2(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, memorySize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
scope.Memory.Resize(memorySize)
|
||||
|
||||
return opCreate2(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opCreate2(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
if interpreter.readOnly {
|
||||
return nil, ErrWriteProtection
|
||||
|
|
@ -732,6 +1131,74 @@ func opCreate2(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func opCallEIP4762(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
memorySize, err := calculateMemorySize(memoryCall, scope.Stack, scope.Memory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dynamicCost, err := gasCallEIP4762(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, memorySize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
scope.Memory.Resize(memorySize)
|
||||
|
||||
return opCall(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opCallEIP7702(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
memorySize, err := calculateMemorySize(memoryCall, scope.Stack, scope.Memory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dynamicCost, err := gasCallEIP7702(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, memorySize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
scope.Memory.Resize(memorySize)
|
||||
|
||||
return opCall(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opCallEIP2929(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
memorySize, err := calculateMemorySize(memoryCall, scope.Stack, scope.Memory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dynamicCost, err := gasCallEIP2929(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, memorySize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
scope.Memory.Resize(memorySize)
|
||||
|
||||
return opCall(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opCallFrontier(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
memorySize, err := calculateMemorySize(memoryCall, scope.Stack, scope.Memory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dynamicCost, err := gasCall(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, memorySize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
scope.Memory.Resize(memorySize)
|
||||
|
||||
return opCall(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
stack := scope.Stack
|
||||
// Pop gas. The actual gas in interpreter.evm.callGasTemp.
|
||||
|
|
@ -768,6 +1235,74 @@ func opCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byt
|
|||
return ret, nil
|
||||
}
|
||||
|
||||
func opCallCodeEIP4762(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
memorySize, err := calculateMemorySize(memoryCall, scope.Stack, scope.Memory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dynamicCost, err := gasCallCodeEIP4762(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, memorySize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
scope.Memory.Resize(memorySize)
|
||||
|
||||
return opCallCode(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opCallCodeEIP7702(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
memorySize, err := calculateMemorySize(memoryCall, scope.Stack, scope.Memory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dynamicCost, err := gasCallCodeEIP7702(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, memorySize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
scope.Memory.Resize(memorySize)
|
||||
|
||||
return opCallCode(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opCallCodeEIP2929(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
memorySize, err := calculateMemorySize(memoryCall, scope.Stack, scope.Memory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dynamicCost, err := gasCallCodeEIP2929(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, memorySize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
scope.Memory.Resize(memorySize)
|
||||
|
||||
return opCallCode(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opCallCodeFrontier(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
memorySize, err := calculateMemorySize(memoryCall, scope.Stack, scope.Memory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dynamicCost, err := gasCallCode(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, memorySize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
scope.Memory.Resize(memorySize)
|
||||
|
||||
return opCallCode(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opCallCode(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
// Pop gas. The actual gas is in interpreter.evm.callGasTemp.
|
||||
stack := scope.Stack
|
||||
|
|
@ -801,6 +1336,57 @@ func opCallCode(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([
|
|||
return ret, nil
|
||||
}
|
||||
|
||||
func opDelegateCallEIP7702(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
memorySize, err := calculateMemorySize(memoryDelegateCall, scope.Stack, scope.Memory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dynamicCost, err := gasDelegateCallEIP7702(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, memorySize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
scope.Memory.Resize(memorySize)
|
||||
|
||||
return opDelegateCall(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opDelegateCallEIP2929(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
memorySize, err := calculateMemorySize(memoryDelegateCall, scope.Stack, scope.Memory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dynamicCost, err := gasDelegateCallEIP2929(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, memorySize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
scope.Memory.Resize(memorySize)
|
||||
|
||||
return opDelegateCall(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opDelegateCallEIP4762(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
memorySize, err := calculateMemorySize(memoryDelegateCall, scope.Stack, scope.Memory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dynamicCost, err := gasDelegateCallEIP4762(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, memorySize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
scope.Memory.Resize(memorySize)
|
||||
|
||||
return opDelegateCall(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opDelegateCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
stack := scope.Stack
|
||||
// Pop gas. The actual gas is in interpreter.evm.callGasTemp.
|
||||
|
|
@ -830,6 +1416,91 @@ func opDelegateCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext
|
|||
return ret, nil
|
||||
}
|
||||
|
||||
func opDelegateCallHomestead(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
memorySize, err := calculateMemorySize(memoryDelegateCall, scope.Stack, scope.Memory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dynamicCost, err := gasDelegateCall(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, memorySize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
scope.Memory.Resize(memorySize)
|
||||
|
||||
return opDelegateCall(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opStaticCallEIP7702(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
memorySize, err := calculateMemorySize(memoryStaticCall, scope.Stack, scope.Memory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dynamicCost, err := gasStaticCallEIP7702(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, memorySize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
scope.Memory.Resize(memorySize)
|
||||
|
||||
return opStaticCall(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opStaticCallByzantium(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
memorySize, err := calculateMemorySize(memoryStaticCall, scope.Stack, scope.Memory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dynamicCost, err := gasStaticCall(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, memorySize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
scope.Memory.Resize(memorySize)
|
||||
|
||||
return opStaticCall(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opStaticCallEIP2929(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
memorySize, err := calculateMemorySize(memoryStaticCall, scope.Stack, scope.Memory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dynamicCost, err := gasStaticCallEIP2929(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, memorySize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
scope.Memory.Resize(memorySize)
|
||||
|
||||
return opStaticCall(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opStaticCallEIP4762(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
memorySize, err := calculateMemorySize(memoryStaticCall, scope.Stack, scope.Memory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dynamicCost, err := gasStaticCallEIP4762(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, memorySize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
scope.Memory.Resize(memorySize)
|
||||
|
||||
return opStaticCall(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opStaticCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
// Pop gas. The actual gas is in interpreter.evm.callGasTemp.
|
||||
stack := scope.Stack
|
||||
|
|
@ -860,6 +1531,19 @@ func opStaticCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext)
|
|||
}
|
||||
|
||||
func opReturn(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
memorySize, err := calculateMemorySize(memoryReturn, scope.Stack, scope.Memory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dynamicCost, err := gasReturn(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, memorySize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
scope.Memory.Resize(memorySize)
|
||||
|
||||
offset, size := scope.Stack.pop(), scope.Stack.pop()
|
||||
ret := scope.Memory.GetCopy(offset.Uint64(), size.Uint64())
|
||||
|
||||
|
|
@ -867,6 +1551,19 @@ func opReturn(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]b
|
|||
}
|
||||
|
||||
func opRevert(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
memorySize, err := calculateMemorySize(memoryRevert, scope.Stack, scope.Memory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dynamicCost, err := gasRevert(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, memorySize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
scope.Memory.Resize(memorySize)
|
||||
|
||||
offset, size := scope.Stack.pop(), scope.Stack.pop()
|
||||
ret := scope.Memory.GetCopy(offset.Uint64(), size.Uint64())
|
||||
|
||||
|
|
@ -882,10 +1579,59 @@ func opStop(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byt
|
|||
return nil, errStopToken
|
||||
}
|
||||
|
||||
func opSelfdestructEIP6780(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
dynamicCost, err := gasSelfdestructEIP3529(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, 0)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
|
||||
return opSelfdestruct6780(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opSelfdestructEIP3529(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
dynamicCost, err := gasSelfdestructEIP3529(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, 0)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
|
||||
return opSelfdestruct(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opSelfdestructEIP2929(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
dynamicCost, err := gasSelfdestructEIP2929(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, 0)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
|
||||
return opSelfdestruct(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opSelfdestructFrontier(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
dynamicCost, err := gasSelfdestruct(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, 0)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
|
||||
return opSelfdestruct(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opSelfdestruct(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
if interpreter.readOnly {
|
||||
return nil, ErrWriteProtection
|
||||
}
|
||||
|
||||
beneficiary := scope.Stack.pop()
|
||||
balance := interpreter.evm.StateDB.GetBalance(scope.Contract.Address())
|
||||
interpreter.evm.StateDB.AddBalance(beneficiary.Bytes20(), balance, tracing.BalanceIncreaseSelfdestruct)
|
||||
|
|
@ -899,6 +1645,18 @@ func opSelfdestruct(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext
|
|||
return nil, errStopToken
|
||||
}
|
||||
|
||||
func opSelfdestructEIP4762(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
dynamicCost, err := gasSelfdestructEIP4762(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, 0)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
|
||||
return opSelfdestruct6780(pc, interpreter, scope)
|
||||
}
|
||||
|
||||
func opSelfdestruct6780(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
if interpreter.readOnly {
|
||||
return nil, ErrWriteProtection
|
||||
|
|
@ -921,10 +1679,24 @@ func opSelfdestruct6780(pc *uint64, interpreter *EVMInterpreter, scope *ScopeCon
|
|||
|
||||
// make log instruction function
|
||||
func makeLog(size int) executionFunc {
|
||||
logGas := makeGasLog(uint64(size))
|
||||
return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
if interpreter.readOnly {
|
||||
return nil, ErrWriteProtection
|
||||
}
|
||||
memorySize, err := calculateMemorySize(memoryLog, scope.Stack, scope.Memory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dynamicCost, err := logGas(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, memorySize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
if !scope.Contract.UseGas(dynamicCost, interpreter.evm.Config.Tracer.OnGasChange, tracing.GasChangeCallOpCodeDynamic) {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
scope.Memory.Resize(memorySize)
|
||||
|
||||
topics := make([]common.Hash, size)
|
||||
stack := scope.Stack
|
||||
mStart, mSize := stack.pop(), stack.pop()
|
||||
|
|
|
|||
|
|
@ -519,22 +519,24 @@ func BenchmarkOpIsZero(b *testing.B) {
|
|||
|
||||
func TestOpMstore(t *testing.T) {
|
||||
var (
|
||||
evm = NewEVM(BlockContext{}, nil, params.TestChainConfig, Config{})
|
||||
stack = newstack()
|
||||
mem = NewMemory()
|
||||
evm = NewEVM(BlockContext{}, nil, params.TestChainConfig, Config{})
|
||||
stack = newstack()
|
||||
mem = NewMemory()
|
||||
contract = &Contract{}
|
||||
)
|
||||
mem.Resize(64)
|
||||
pc := uint64(0)
|
||||
contract.Gas = 30_000_000
|
||||
v := "abcdef00000000000000abba000000000deaf000000c0de00100000000133700"
|
||||
stack.push(new(uint256.Int).SetBytes(common.Hex2Bytes(v)))
|
||||
stack.push(new(uint256.Int))
|
||||
opMstore(&pc, evm.interpreter, &ScopeContext{mem, stack, nil})
|
||||
opMstore(&pc, evm.interpreter, &ScopeContext{mem, stack, contract})
|
||||
if got := common.Bytes2Hex(mem.GetCopy(0, 32)); got != v {
|
||||
t.Fatalf("Mstore fail, got %v, expected %v", got, v)
|
||||
}
|
||||
stack.push(new(uint256.Int).SetUint64(0x1))
|
||||
stack.push(new(uint256.Int))
|
||||
opMstore(&pc, evm.interpreter, &ScopeContext{mem, stack, nil})
|
||||
opMstore(&pc, evm.interpreter, &ScopeContext{mem, stack, contract})
|
||||
if common.Bytes2Hex(mem.GetCopy(0, 32)) != "0000000000000000000000000000000000000000000000000000000000000001" {
|
||||
t.Fatalf("Mstore failed to overwrite previous value")
|
||||
}
|
||||
|
|
@ -846,10 +848,12 @@ func TestOpMCopy(t *testing.T) {
|
|||
},
|
||||
} {
|
||||
var (
|
||||
evm = NewEVM(BlockContext{}, nil, params.TestChainConfig, Config{})
|
||||
stack = newstack()
|
||||
pc = uint64(0)
|
||||
evm = NewEVM(BlockContext{}, nil, params.TestChainConfig, Config{})
|
||||
stack = newstack()
|
||||
pc = uint64(0)
|
||||
contract = &Contract{}
|
||||
)
|
||||
contract.Gas = 30_000_000
|
||||
data := common.FromHex(strings.ReplaceAll(tc.pre, " ", ""))
|
||||
// Set pre
|
||||
mem := NewMemory()
|
||||
|
|
@ -889,7 +893,7 @@ func TestOpMCopy(t *testing.T) {
|
|||
mem.Resize(memorySize)
|
||||
}
|
||||
// Do the copy
|
||||
opMcopy(&pc, evm.interpreter, &ScopeContext{mem, stack, nil})
|
||||
opMcopy(&pc, evm.interpreter, &ScopeContext{mem, stack, contract})
|
||||
want := common.FromHex(strings.ReplaceAll(tc.want, " ", ""))
|
||||
if have := mem.store; !bytes.Equal(want, have) {
|
||||
t.Errorf("case %d: \nwant: %#x\nhave: %#x\n", i, want, have)
|
||||
|
|
|
|||
|
|
@ -17,10 +17,7 @@
|
|||
package vm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/math"
|
||||
"github.com/ethereum/go-ethereum/core/tracing"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
|
|
@ -139,7 +136,7 @@ func NewEVMInterpreter(evm *EVM) *EVMInterpreter {
|
|||
table = &frontierInstructionSet
|
||||
}
|
||||
var extraEips []int
|
||||
if len(evm.Config.ExtraEips) > 0 {
|
||||
if len(evm.Config.ExtraEips) > 0 || evm.Config.Tracer.HooksVM() {
|
||||
// Deep-copy jumptable to prevent modification of opcodes in other tables
|
||||
table = copyJumpTable(table)
|
||||
}
|
||||
|
|
@ -151,10 +148,41 @@ func NewEVMInterpreter(evm *EVM) *EVMInterpreter {
|
|||
extraEips = append(extraEips, eip)
|
||||
}
|
||||
}
|
||||
if evm.Config.Tracer.HooksVM() {
|
||||
for _, op := range table {
|
||||
op.execute = executeWithTracer(&evm.Config.Tracer, op.execute)
|
||||
}
|
||||
}
|
||||
|
||||
evm.Config.ExtraEips = extraEips
|
||||
return &EVMInterpreter{evm: evm, table: table, hasher: crypto.NewKeccakState()}
|
||||
}
|
||||
|
||||
// executeWithTracer is a wrapper that enables tracing the given executionFunc
|
||||
func executeWithTracer(tracer *tracing.Hooks, execF executionFunc) executionFunc {
|
||||
return func(pc *uint64, interpreter *EVMInterpreter, callContext *ScopeContext) ([]byte, error) {
|
||||
pcCopy := *pc
|
||||
op := callContext.Contract.GetOp(pcCopy)
|
||||
operation := interpreter.table[op]
|
||||
cost := operation.constantGas
|
||||
gasCopy := callContext.Contract.Gas + cost
|
||||
|
||||
if tracer.OnGasChange != nil {
|
||||
tracer.OnGasChange(gasCopy, gasCopy-cost, tracing.GasChangeCallOpCode)
|
||||
}
|
||||
if tracer.OnOpcode != nil {
|
||||
tracer.OnOpcode(pcCopy, byte(op), gasCopy, cost, callContext, interpreter.returnData,
|
||||
interpreter.evm.depth, nil)
|
||||
}
|
||||
|
||||
ret, err := execF(pc, interpreter, callContext)
|
||||
if err != nil && err != errStopToken && tracer.OnFault != nil {
|
||||
tracer.OnFault(pcCopy, byte(op), gasCopy, gasCopy-callContext.Contract.Gas, callContext, interpreter.evm.depth, VMErrorFromErr(err))
|
||||
}
|
||||
return ret, err
|
||||
}
|
||||
}
|
||||
|
||||
// Run loops and evaluates the contract's code with the given input data and returns
|
||||
// the return byte-slice and an error if one occurred.
|
||||
//
|
||||
|
|
@ -195,13 +223,9 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
|
|||
// For optimisation reason we're using uint64 as the program counter.
|
||||
// It's theoretically possible to go above 2^64. The YP defines the PC
|
||||
// to be uint256. Practically much less so feasible.
|
||||
pc = uint64(0) // program counter
|
||||
cost, dynamicCost uint64
|
||||
// copies used by tracer
|
||||
pcCopy uint64 // needed for the deferred EVMLogger
|
||||
gasCopy uint64 // for EVMLogger to log gas remaining before execution
|
||||
logged bool // deferred EVMLogger should ignore already logged steps
|
||||
res []byte // result of the opcode execution function
|
||||
pc = uint64(0) // program counter
|
||||
cost uint64
|
||||
res []byte // result of the opcode execution function
|
||||
)
|
||||
// Don't move this deferred function, it's placed before the OnOpcode-deferred method,
|
||||
// so that it gets executed _after_: the OnOpcode needs the stacks before
|
||||
|
|
@ -212,26 +236,20 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
|
|||
}()
|
||||
contract.Input = input
|
||||
|
||||
defer func() { // this deferred method handles exit-with-error
|
||||
if err == nil {
|
||||
return
|
||||
// This is just temporary until we move everything that can error in to the execution function
|
||||
traceAndReturnError := func(err error) error {
|
||||
if in.evm.Config.Tracer.OnFault != nil {
|
||||
in.evm.Config.Tracer.OnFault(pc, byte(op), contract.Gas, cost, callContext, in.evm.depth, VMErrorFromErr(err))
|
||||
}
|
||||
if !logged && in.evm.Config.Tracer.OnOpcode != nil {
|
||||
in.evm.Config.Tracer.OnOpcode(pcCopy, byte(op), gasCopy, cost, callContext, in.returnData, in.evm.depth, VMErrorFromErr(err))
|
||||
}
|
||||
if logged && in.evm.Config.Tracer.OnFault != nil {
|
||||
in.evm.Config.Tracer.OnFault(pcCopy, byte(op), gasCopy, cost, callContext, in.evm.depth, VMErrorFromErr(err))
|
||||
}
|
||||
}()
|
||||
return err
|
||||
}
|
||||
|
||||
// The Interpreter main run loop (contextual). This loop runs until either an
|
||||
// explicit STOP, RETURN or SELFDESTRUCT is executed, an error occurred during
|
||||
// the execution of one of the operations or until the done flag is set by the
|
||||
// parent context.
|
||||
_ = jumpTable[0] // nil-check the jumpTable out of the loop
|
||||
for {
|
||||
// Capture pre-execution values for tracing.
|
||||
logged, pcCopy, gasCopy, dynamicCost = false, pc, contract.Gas, 0
|
||||
|
||||
if in.evm.chainRules.IsEIP4762 && !contract.IsDeployment && !contract.IsSystemCall {
|
||||
// if the PC ends up in a new "chunk" of verkleized code, charge the
|
||||
// associated costs.
|
||||
|
|
@ -239,7 +257,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
|
|||
consumed, wanted := in.evm.TxContext.AccessEvents.CodeChunksRangeGas(contractAddr, pc, 1, uint64(len(contract.Code)), false, contract.Gas)
|
||||
contract.UseGas(consumed, in.evm.Config.Tracer.OnGasChange, tracing.GasChangeWitnessCodeChunk)
|
||||
if consumed < wanted {
|
||||
return nil, ErrOutOfGas
|
||||
return nil, traceAndReturnError(ErrOutOfGas)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -250,67 +268,17 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
|
|||
cost = operation.constantGas // For tracing
|
||||
// Validate stack
|
||||
if sLen := stack.len(); sLen < operation.minStack {
|
||||
return nil, &ErrStackUnderflow{stackLen: sLen, required: operation.minStack}
|
||||
return nil, traceAndReturnError(&ErrStackUnderflow{stackLen: sLen, required: operation.minStack})
|
||||
} else if sLen > operation.maxStack {
|
||||
return nil, &ErrStackOverflow{stackLen: sLen, limit: operation.maxStack}
|
||||
return nil, traceAndReturnError(&ErrStackOverflow{stackLen: sLen, limit: operation.maxStack})
|
||||
}
|
||||
// for tracing: this gas consumption event is emitted below in the debug section.
|
||||
// for tracing: this gas consumption event is emitted in the executeWithTracer wrapper.
|
||||
if contract.Gas < cost {
|
||||
return nil, ErrOutOfGas
|
||||
return nil, traceAndReturnError(ErrOutOfGas)
|
||||
} else {
|
||||
contract.Gas -= cost
|
||||
}
|
||||
|
||||
// All ops with a dynamic memory usage also has a dynamic gas cost.
|
||||
var memorySize uint64
|
||||
if operation.dynamicGas != nil {
|
||||
// calculate the new memory size and expand the memory to fit
|
||||
// the operation
|
||||
// Memory check needs to be done prior to evaluating the dynamic gas portion,
|
||||
// to detect calculation overflows
|
||||
if operation.memorySize != nil {
|
||||
memSize, overflow := operation.memorySize(stack)
|
||||
if overflow {
|
||||
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
|
||||
}
|
||||
}
|
||||
// Consume the gas and return an error if not enough gas is available.
|
||||
// cost is explicitly set so that the capture state defer method can get the proper cost
|
||||
dynamicCost, err = operation.dynamicGas(in.evm, contract, stack, mem, memorySize)
|
||||
cost += dynamicCost // for tracing
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
// for tracing: this gas consumption event is emitted below in the debug section.
|
||||
if contract.Gas < dynamicCost {
|
||||
return nil, ErrOutOfGas
|
||||
} else {
|
||||
contract.Gas -= dynamicCost
|
||||
}
|
||||
}
|
||||
|
||||
// Do tracing before potential memory expansion
|
||||
if in.evm.Config.Tracer.OnGasChange != nil {
|
||||
// Trace the constant cost only
|
||||
in.evm.Config.Tracer.OnGasChange(gasCopy, gasCopy-operation.constantGas, tracing.GasChangeCallOpCode)
|
||||
}
|
||||
if in.evm.Config.Tracer.OnOpcode != nil {
|
||||
in.evm.Config.Tracer.OnOpcode(pc, byte(op), gasCopy, operation.constantGas, callContext, in.returnData, in.evm.depth, VMErrorFromErr(err))
|
||||
// If any, trace the dynamic cost as well
|
||||
if in.evm.Config.Tracer.OnGasChange != nil && dynamicCost > 0 {
|
||||
in.evm.Config.Tracer.OnGasChange(gasCopy-operation.constantGas, gasCopy-cost, tracing.GasChangeCallOpCodeDynamic)
|
||||
}
|
||||
logged = true
|
||||
}
|
||||
if memorySize > 0 {
|
||||
mem.Resize(memorySize)
|
||||
}
|
||||
|
||||
// execute the operation
|
||||
res, err = operation.execute(&pc, in, callContext)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -33,16 +33,12 @@ type operation struct {
|
|||
// execute is the operation function
|
||||
execute executionFunc
|
||||
constantGas uint64
|
||||
dynamicGas gasFunc
|
||||
// minStack tells how many stack items are required
|
||||
minStack int
|
||||
// maxStack specifies the max length the stack can have for this operation
|
||||
// to not overflow the stack.
|
||||
maxStack int
|
||||
|
||||
// memorySize returns the memory size required for the operation
|
||||
memorySize memorySizeFunc
|
||||
|
||||
// undefined denotes if the instruction is not officially defined in the jump table
|
||||
undefined bool
|
||||
}
|
||||
|
|
@ -73,15 +69,6 @@ func validate(jt JumpTable) JumpTable {
|
|||
if op == nil {
|
||||
panic(fmt.Sprintf("op %#x is not set", i))
|
||||
}
|
||||
// The interpreter has an assumption that if the memorySize function is
|
||||
// set, then the dynamicGas function is also set. This is a somewhat
|
||||
// arbitrary assumption, and can be removed if we need to -- but it
|
||||
// allows us to avoid a condition check. As long as we have that assumption
|
||||
// in there, this little sanity check prevents us from merging in a
|
||||
// change which violates it.
|
||||
if op.memorySize != nil && op.dynamicGas == nil {
|
||||
panic(fmt.Sprintf("op %v has dynamic memory but not dynamic gas", OpCode(i).String()))
|
||||
}
|
||||
}
|
||||
return jt
|
||||
}
|
||||
|
|
@ -191,12 +178,10 @@ func newConstantinopleInstructionSet() JumpTable {
|
|||
maxStack: maxStack(1, 1),
|
||||
}
|
||||
instructionSet[CREATE2] = &operation{
|
||||
execute: opCreate2,
|
||||
execute: opCreate2Constantinople,
|
||||
constantGas: params.Create2Gas,
|
||||
dynamicGas: gasCreate2,
|
||||
minStack: minStack(4, 1),
|
||||
maxStack: maxStack(4, 1),
|
||||
memorySize: memoryCreate2,
|
||||
}
|
||||
return validate(instructionSet)
|
||||
}
|
||||
|
|
@ -206,12 +191,10 @@ func newConstantinopleInstructionSet() JumpTable {
|
|||
func newByzantiumInstructionSet() JumpTable {
|
||||
instructionSet := newSpuriousDragonInstructionSet()
|
||||
instructionSet[STATICCALL] = &operation{
|
||||
execute: opStaticCall,
|
||||
execute: opStaticCallByzantium,
|
||||
constantGas: params.CallGasEIP150,
|
||||
dynamicGas: gasStaticCall,
|
||||
minStack: minStack(6, 1),
|
||||
maxStack: maxStack(6, 1),
|
||||
memorySize: memoryStaticCall,
|
||||
}
|
||||
instructionSet[RETURNDATASIZE] = &operation{
|
||||
execute: opReturnDataSize,
|
||||
|
|
@ -222,17 +205,13 @@ func newByzantiumInstructionSet() JumpTable {
|
|||
instructionSet[RETURNDATACOPY] = &operation{
|
||||
execute: opReturnDataCopy,
|
||||
constantGas: GasFastestStep,
|
||||
dynamicGas: gasReturnDataCopy,
|
||||
minStack: minStack(3, 0),
|
||||
maxStack: maxStack(3, 0),
|
||||
memorySize: memoryReturnDataCopy,
|
||||
}
|
||||
instructionSet[REVERT] = &operation{
|
||||
execute: opRevert,
|
||||
dynamicGas: gasRevert,
|
||||
minStack: minStack(2, 0),
|
||||
maxStack: maxStack(2, 0),
|
||||
memorySize: memoryRevert,
|
||||
execute: opRevert,
|
||||
minStack: minStack(2, 0),
|
||||
maxStack: maxStack(2, 0),
|
||||
}
|
||||
return validate(instructionSet)
|
||||
}
|
||||
|
|
@ -240,7 +219,7 @@ func newByzantiumInstructionSet() JumpTable {
|
|||
// EIP 158 a.k.a Spurious Dragon
|
||||
func newSpuriousDragonInstructionSet() JumpTable {
|
||||
instructionSet := newTangerineWhistleInstructionSet()
|
||||
instructionSet[EXP].dynamicGas = gasExpEIP158
|
||||
instructionSet[EXP].execute = opExpEIP158
|
||||
return validate(instructionSet)
|
||||
}
|
||||
|
||||
|
|
@ -262,12 +241,10 @@ func newTangerineWhistleInstructionSet() JumpTable {
|
|||
func newHomesteadInstructionSet() JumpTable {
|
||||
instructionSet := newFrontierInstructionSet()
|
||||
instructionSet[DELEGATECALL] = &operation{
|
||||
execute: opDelegateCall,
|
||||
dynamicGas: gasDelegateCall,
|
||||
execute: opDelegateCallHomestead,
|
||||
constantGas: params.CallGasFrontier,
|
||||
minStack: minStack(6, 1),
|
||||
maxStack: maxStack(6, 1),
|
||||
memorySize: memoryDelegateCall,
|
||||
}
|
||||
return validate(instructionSet)
|
||||
}
|
||||
|
|
@ -337,10 +314,9 @@ func newFrontierInstructionSet() JumpTable {
|
|||
maxStack: maxStack(3, 1),
|
||||
},
|
||||
EXP: {
|
||||
execute: opExp,
|
||||
dynamicGas: gasExpFrontier,
|
||||
minStack: minStack(2, 1),
|
||||
maxStack: maxStack(2, 1),
|
||||
execute: opExpFrontier,
|
||||
minStack: minStack(2, 1),
|
||||
maxStack: maxStack(2, 1),
|
||||
},
|
||||
SIGNEXTEND: {
|
||||
execute: opSignExtend,
|
||||
|
|
@ -417,10 +393,8 @@ func newFrontierInstructionSet() JumpTable {
|
|||
KECCAK256: {
|
||||
execute: opKeccak256,
|
||||
constantGas: params.Keccak256Gas,
|
||||
dynamicGas: gasKeccak256,
|
||||
minStack: minStack(2, 1),
|
||||
maxStack: maxStack(2, 1),
|
||||
memorySize: memoryKeccak256,
|
||||
},
|
||||
ADDRESS: {
|
||||
execute: opAddress,
|
||||
|
|
@ -467,10 +441,8 @@ func newFrontierInstructionSet() JumpTable {
|
|||
CALLDATACOPY: {
|
||||
execute: opCallDataCopy,
|
||||
constantGas: GasFastestStep,
|
||||
dynamicGas: gasCallDataCopy,
|
||||
minStack: minStack(3, 0),
|
||||
maxStack: maxStack(3, 0),
|
||||
memorySize: memoryCallDataCopy,
|
||||
},
|
||||
CODESIZE: {
|
||||
execute: opCodeSize,
|
||||
|
|
@ -479,12 +451,10 @@ func newFrontierInstructionSet() JumpTable {
|
|||
maxStack: maxStack(0, 1),
|
||||
},
|
||||
CODECOPY: {
|
||||
execute: opCodeCopy,
|
||||
execute: opCodeCopyFrontier,
|
||||
constantGas: GasFastestStep,
|
||||
dynamicGas: gasCodeCopy,
|
||||
minStack: minStack(3, 0),
|
||||
maxStack: maxStack(3, 0),
|
||||
memorySize: memoryCodeCopy,
|
||||
},
|
||||
GASPRICE: {
|
||||
execute: opGasprice,
|
||||
|
|
@ -499,12 +469,10 @@ func newFrontierInstructionSet() JumpTable {
|
|||
maxStack: maxStack(1, 1),
|
||||
},
|
||||
EXTCODECOPY: {
|
||||
execute: opExtCodeCopy,
|
||||
execute: opExtCodeCopyFrontier,
|
||||
constantGas: params.ExtcodeCopyBaseFrontier,
|
||||
dynamicGas: gasExtCodeCopy,
|
||||
minStack: minStack(4, 0),
|
||||
maxStack: maxStack(4, 0),
|
||||
memorySize: memoryExtCodeCopy,
|
||||
},
|
||||
BLOCKHASH: {
|
||||
execute: opBlockhash,
|
||||
|
|
@ -551,24 +519,18 @@ func newFrontierInstructionSet() JumpTable {
|
|||
MLOAD: {
|
||||
execute: opMload,
|
||||
constantGas: GasFastestStep,
|
||||
dynamicGas: gasMLoad,
|
||||
minStack: minStack(1, 1),
|
||||
maxStack: maxStack(1, 1),
|
||||
memorySize: memoryMLoad,
|
||||
},
|
||||
MSTORE: {
|
||||
execute: opMstore,
|
||||
constantGas: GasFastestStep,
|
||||
dynamicGas: gasMStore,
|
||||
minStack: minStack(2, 0),
|
||||
maxStack: maxStack(2, 0),
|
||||
memorySize: memoryMStore,
|
||||
},
|
||||
MSTORE8: {
|
||||
execute: opMstore8,
|
||||
constantGas: GasFastestStep,
|
||||
dynamicGas: gasMStore8,
|
||||
memorySize: memoryMStore8,
|
||||
minStack: minStack(2, 0),
|
||||
maxStack: maxStack(2, 0),
|
||||
},
|
||||
|
|
@ -579,10 +541,9 @@ func newFrontierInstructionSet() JumpTable {
|
|||
maxStack: maxStack(1, 1),
|
||||
},
|
||||
SSTORE: {
|
||||
execute: opSstore,
|
||||
dynamicGas: gasSStore,
|
||||
minStack: minStack(2, 0),
|
||||
maxStack: maxStack(2, 0),
|
||||
execute: opSstoreFrontier,
|
||||
minStack: minStack(2, 0),
|
||||
maxStack: maxStack(2, 0),
|
||||
},
|
||||
JUMP: {
|
||||
execute: opJump,
|
||||
|
|
@ -1005,76 +966,57 @@ func newFrontierInstructionSet() JumpTable {
|
|||
maxStack: maxSwapStack(17),
|
||||
},
|
||||
LOG0: {
|
||||
execute: makeLog(0),
|
||||
dynamicGas: makeGasLog(0),
|
||||
minStack: minStack(2, 0),
|
||||
maxStack: maxStack(2, 0),
|
||||
memorySize: memoryLog,
|
||||
execute: makeLog(0),
|
||||
minStack: minStack(2, 0),
|
||||
maxStack: maxStack(2, 0),
|
||||
},
|
||||
LOG1: {
|
||||
execute: makeLog(1),
|
||||
dynamicGas: makeGasLog(1),
|
||||
minStack: minStack(3, 0),
|
||||
maxStack: maxStack(3, 0),
|
||||
memorySize: memoryLog,
|
||||
execute: makeLog(1),
|
||||
minStack: minStack(3, 0),
|
||||
maxStack: maxStack(3, 0),
|
||||
},
|
||||
LOG2: {
|
||||
execute: makeLog(2),
|
||||
dynamicGas: makeGasLog(2),
|
||||
minStack: minStack(4, 0),
|
||||
maxStack: maxStack(4, 0),
|
||||
memorySize: memoryLog,
|
||||
execute: makeLog(2),
|
||||
minStack: minStack(4, 0),
|
||||
maxStack: maxStack(4, 0),
|
||||
},
|
||||
LOG3: {
|
||||
execute: makeLog(3),
|
||||
dynamicGas: makeGasLog(3),
|
||||
minStack: minStack(5, 0),
|
||||
maxStack: maxStack(5, 0),
|
||||
memorySize: memoryLog,
|
||||
execute: makeLog(3),
|
||||
minStack: minStack(5, 0),
|
||||
maxStack: maxStack(5, 0),
|
||||
},
|
||||
LOG4: {
|
||||
execute: makeLog(4),
|
||||
dynamicGas: makeGasLog(4),
|
||||
minStack: minStack(6, 0),
|
||||
maxStack: maxStack(6, 0),
|
||||
memorySize: memoryLog,
|
||||
execute: makeLog(4),
|
||||
minStack: minStack(6, 0),
|
||||
maxStack: maxStack(6, 0),
|
||||
},
|
||||
CREATE: {
|
||||
execute: opCreate,
|
||||
execute: opCreateFrontier,
|
||||
constantGas: params.CreateGas,
|
||||
dynamicGas: gasCreate,
|
||||
minStack: minStack(3, 1),
|
||||
maxStack: maxStack(3, 1),
|
||||
memorySize: memoryCreate,
|
||||
},
|
||||
CALL: {
|
||||
execute: opCall,
|
||||
execute: opCallFrontier,
|
||||
constantGas: params.CallGasFrontier,
|
||||
dynamicGas: gasCall,
|
||||
minStack: minStack(7, 1),
|
||||
maxStack: maxStack(7, 1),
|
||||
memorySize: memoryCall,
|
||||
},
|
||||
CALLCODE: {
|
||||
execute: opCallCode,
|
||||
execute: opCallCodeFrontier,
|
||||
constantGas: params.CallGasFrontier,
|
||||
dynamicGas: gasCallCode,
|
||||
minStack: minStack(7, 1),
|
||||
maxStack: maxStack(7, 1),
|
||||
memorySize: memoryCall,
|
||||
},
|
||||
RETURN: {
|
||||
execute: opReturn,
|
||||
dynamicGas: gasReturn,
|
||||
minStack: minStack(2, 0),
|
||||
maxStack: maxStack(2, 0),
|
||||
memorySize: memoryReturn,
|
||||
execute: opReturn,
|
||||
minStack: minStack(2, 0),
|
||||
maxStack: maxStack(2, 0),
|
||||
},
|
||||
SELFDESTRUCT: {
|
||||
execute: opSelfdestruct,
|
||||
dynamicGas: gasSelfdestruct,
|
||||
minStack: minStack(1, 0),
|
||||
maxStack: maxStack(1, 0),
|
||||
execute: opSelfdestructFrontier,
|
||||
minStack: minStack(1, 0),
|
||||
maxStack: maxStack(1, 0),
|
||||
},
|
||||
INVALID: {
|
||||
execute: opUndefined,
|
||||
|
|
|
|||
|
|
@ -62,17 +62,3 @@ func LookupInstructionSet(rules params.Rules) (JumpTable, error) {
|
|||
func (op *operation) Stack() (int, int) {
|
||||
return op.minStack, op.maxStack
|
||||
}
|
||||
|
||||
// HasCost returns true if the opcode has a cost. Opcodes which do _not_ have
|
||||
// a cost assigned are one of two things:
|
||||
// - undefined, a.k.a invalid opcodes,
|
||||
// - the STOP opcode.
|
||||
// This method can thus be used to check if an opcode is "Invalid (or STOP)".
|
||||
func (op *operation) HasCost() bool {
|
||||
// Ideally, we'd check this:
|
||||
// return op.execute == opUndefined
|
||||
// However, go-lang does now allow that. So we'll just check some other
|
||||
// 'indicators' that this is an invalid op. Alas, STOP is impossible to
|
||||
// filter out
|
||||
return op.dynamicGas != nil || op.constantGas != 0
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue