Fix EVM tracer: capture exception properly

Also fix EVM to support new tracer
This commit is contained in:
jangko 2023-08-27 13:13:37 +07:00
parent 465d694834
commit 80aec9ccd9
No known key found for this signature in database
GPG Key ID: 31702AE10541E6B9
23 changed files with 382 additions and 295 deletions

View File

@ -396,9 +396,6 @@ proc traceOpCodeStarted*(c: Computation, op: Op): int {.gcsafe, raises: [].} =
c.gasMeter.gasRemaining, c.gasMeter.gasRemaining,
c.msg.depth + 1) c.msg.depth + 1)
proc traceCallFamilyGas*(c: Computation, op: Op, gas: GasInt) {.gcsafe, raises: [].} =
c.vmState.callFamilyGas(c, op, gas, c.msg.depth + 1)
proc traceOpCodeEnded*(c: Computation, op: Op, opIndex: int) {.gcsafe, raises: [].} = proc traceOpCodeEnded*(c: Computation, op: Op, opIndex: int) {.gcsafe, raises: [].} =
c.vmState.captureOpEnd( c.vmState.captureOpEnd(
c, c,
@ -424,6 +421,15 @@ proc traceError*(c: Computation) {.gcsafe, raises: [].} =
proc prepareTracer*(c: Computation) = proc prepareTracer*(c: Computation) =
c.vmState.capturePrepare(c, c.msg.depth) c.vmState.capturePrepare(c, c.msg.depth)
proc opcodeGastCost*(c: Computation, op: Op, gasCost: GasInt, reason: string) {.gcsafe, raises: [OutOfGas, ValueError].} =
c.vmState.captureGasCost(
c,
op,
gasCost,
c.gasMeter.gasRemaining,
c.msg.depth + 1)
c.gasMeter.consumeGas(gasCost, reason)
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# End # End
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------

View File

@ -94,7 +94,8 @@ type
GckFixed, GckFixed,
GckDynamic, GckDynamic,
GckMemExpansion, GckMemExpansion,
GckComplex GckComplex,
GckLater
GasResult = tuple[gasCost, gasRefund: GasInt] GasResult = tuple[gasCost, gasRefund: GasInt]
@ -102,7 +103,7 @@ type
case kind*: GasCostKind case kind*: GasCostKind
of GckInvalidOp: of GckInvalidOp:
discard discard
of GckFixed: of GckFixed, GckLater:
cost*: GasInt cost*: GasInt
of GckDynamic: of GckDynamic:
d_handler*: proc(value: UInt256): GasInt d_handler*: proc(value: UInt256): GasInt
@ -535,6 +536,13 @@ template gasCosts(fork: EVMFork, prefix, ResultGasCostsName: untyped) =
func fixed(gasFeeKind: static[GasFeeKind]): GasCost = func fixed(gasFeeKind: static[GasFeeKind]): GasCost =
GasCost(kind: GckFixed, cost: static(FeeSchedule[gasFeeKind])) GasCost(kind: GckFixed, cost: static(FeeSchedule[gasFeeKind]))
func fixedOrLater(gasFeeKind: static[GasFeeKind]): GasCost =
when fork < FkBerlin:
GasCost(kind: GckFixed, cost: static(FeeSchedule[gasFeeKind]))
else:
# GckLater is processed by the opcode
GasCost(kind: GckLater, cost: static(FeeSchedule[gasFeeKind]))
func dynamic(handler: proc(value: UInt256): GasInt func dynamic(handler: proc(value: UInt256): GasInt
{.nimcall, gcsafe, raises: [CatchableError].}): GasCost = {.nimcall, gcsafe, raises: [CatchableError].}): GasCost =
GasCost(kind: GckDynamic, d_handler: handler) GasCost(kind: GckDynamic, d_handler: handler)
@ -585,7 +593,7 @@ template gasCosts(fork: EVMFork, prefix, ResultGasCostsName: untyped) =
# 30s: Environmental Information # 30s: Environmental Information
Address: fixed GasBase, Address: fixed GasBase,
Balance: fixed GasBalance, Balance: fixedOrLater GasBalance,
Origin: fixed GasBase, Origin: fixed GasBase,
Caller: fixed GasBase, Caller: fixed GasBase,
CallValue: fixed GasBase, CallValue: fixed GasBase,
@ -595,11 +603,11 @@ template gasCosts(fork: EVMFork, prefix, ResultGasCostsName: untyped) =
CodeSize: fixed GasBase, CodeSize: fixed GasBase,
CodeCopy: memExpansion `prefix gasCopy`, CodeCopy: memExpansion `prefix gasCopy`,
GasPrice: fixed GasBase, GasPrice: fixed GasBase,
ExtCodeSize: fixed GasExtCode, ExtCodeSize: fixedOrLater GasExtCode,
ExtCodeCopy: memExpansion `prefix gasExtCodeCopy`, ExtCodeCopy: memExpansion `prefix gasExtCodeCopy`,
ReturnDataSize: fixed GasBase, ReturnDataSize: fixed GasBase,
ReturnDataCopy: memExpansion `prefix gasCopy`, ReturnDataCopy: memExpansion `prefix gasCopy`,
ExtCodeHash: fixed GasExtCodeHash, ExtCodeHash: fixedOrLater GasExtCodeHash,
# 40s: Block Information # 40s: Block Information
Blockhash: fixed GasBlockhash, Blockhash: fixed GasBlockhash,
@ -618,7 +626,7 @@ template gasCosts(fork: EVMFork, prefix, ResultGasCostsName: untyped) =
Mload: memExpansion `prefix gasLoadStore`, Mload: memExpansion `prefix gasLoadStore`,
Mstore: memExpansion `prefix gasLoadStore`, Mstore: memExpansion `prefix gasLoadStore`,
Mstore8: memExpansion `prefix gasLoadStore`, Mstore8: memExpansion `prefix gasLoadStore`,
Sload: fixed GasSload, Sload: fixedOrLater GasSload,
Sstore: complex `prefix gasSstore`, Sstore: complex `prefix gasSstore`,
Jump: fixed GasMid, Jump: fixed GasMid,
JumpI: fixed GasHigh, JumpI: fixed GasHigh,

View File

@ -47,7 +47,7 @@ template handleFixedGasCostsDirective(fork: EVMFork; op: Op; k: var Vm2Ctx) =
if k.cpt.tracingEnabled: if k.cpt.tracingEnabled:
k.cpt.opIndex = k.cpt.traceOpCodeStarted(op) k.cpt.opIndex = k.cpt.traceOpCodeStarted(op)
k.cpt.gasMeter.consumeGas(k.cpt.gasCosts[op].cost, reason = $op) k.cpt.opcodeGastCost(op, k.cpt.gasCosts[op].cost, reason = $op)
vmOpHandlers[fork][op].run(k) vmOpHandlers[fork][op].run(k)
# If continuation is not nil, traceOpCodeEnded will be called in executeOpcodes. # If continuation is not nil, traceOpCodeEnded will be called in executeOpcodes.

View File

@ -20,7 +20,6 @@ import
../../types, ../../types,
../op_codes, ../op_codes,
../gas_costs, ../gas_costs,
../gas_meter,
../utils/utils_numeric, ../utils/utils_numeric,
./oph_defs, ./oph_defs,
eth/common eth/common
@ -131,7 +130,7 @@ const
## 0x0A, Exponentiation ## 0x0A, Exponentiation
let (base, exponent) = k.cpt.stack.popInt(2) let (base, exponent) = k.cpt.stack.popInt(2)
k.cpt.gasMeter.consumeGas( k.cpt.opcodeGastCost(Exp,
k.cpt.gasCosts[Exp].d_handler(exponent), k.cpt.gasCosts[Exp].d_handler(exponent),
reason = "EXP: exponent bytes") reason = "EXP: exponent bytes")

View File

@ -56,6 +56,7 @@ type
memOffset: int memOffset: int
memLength: int memLength: int
contractAddress: EthAddress contractAddress: EthAddress
gasCallEIP2929: GasInt
proc updateStackAndParams(q: var LocalParams; c: Computation) = proc updateStackAndParams(q: var LocalParams; c: Computation) =
@ -79,9 +80,7 @@ proc updateStackAndParams(q: var LocalParams; c: Computation) =
if FkBerlin <= c.fork: if FkBerlin <= c.fork:
when evmc_enabled: when evmc_enabled:
if c.host.accessAccount(q.codeAddress) == EVMC_ACCESS_COLD: if c.host.accessAccount(q.codeAddress) == EVMC_ACCESS_COLD:
c.gasMeter.consumeGas( q.gasCallEIP2929 = ColdAccountAccessCost - WarmStorageReadCost
ColdAccountAccessCost - WarmStorageReadCost,
reason = "EIP2929 gasCall")
else: else:
c.vmState.mutateStateDB: c.vmState.mutateStateDB:
if not db.inAccessList(q.codeAddress): if not db.inAccessList(q.codeAddress):
@ -89,9 +88,7 @@ proc updateStackAndParams(q: var LocalParams; c: Computation) =
# The WarmStorageReadCostEIP2929 (100) is already deducted in # The WarmStorageReadCostEIP2929 (100) is already deducted in
# the form of a constant `gasCall` # the form of a constant `gasCall`
c.gasMeter.consumeGas( q.gasCallEIP2929 = ColdAccountAccessCost - WarmStorageReadCost
ColdAccountAccessCost - WarmStorageReadCost,
reason = "EIP2929 gasCall")
proc callParams(c: Computation): LocalParams = proc callParams(c: Computation): LocalParams =
@ -205,7 +202,6 @@ const
"Cannot modify state while inside of a STATICCALL context") "Cannot modify state while inside of a STATICCALL context")
let let
gasAtStart = cpt.gasMeter.gasRemaining
p = cpt.callParams p = cpt.callParams
cpt.asyncChainTo(ifNecessaryGetAccounts(cpt.vmState, @[p.sender])): cpt.asyncChainTo(ifNecessaryGetAccounts(cpt.vmState, @[p.sender])):
@ -215,17 +211,15 @@ const
GasParams( GasParams(
kind: Call, kind: Call,
c_isNewAccount: not cpt.accountExists(p.contractAddress), c_isNewAccount: not cpt.accountExists(p.contractAddress),
c_gasBalance: cpt.gasMeter.gasRemaining, c_gasBalance: cpt.gasMeter.gasRemaining - p.gasCallEIP2929,
c_contractGas: p.gas, c_contractGas: p.gas,
c_currentMemSize: cpt.memory.len, c_currentMemSize: cpt.memory.len,
c_memOffset: p.memOffset, c_memOffset: p.memOffset,
c_memLength: p.memLength)) c_memLength: p.memLength))
# EIP 2046: temporary disabled gasCost += p.gasCallEIP2929
# reduce gas fee for precompiles
# from 700 to 40
if gasCost >= 0: if gasCost >= 0:
cpt.gasMeter.consumeGas(gasCost, reason = $Call) cpt.opcodeGastCost(Call, gasCost, reason = $Call)
cpt.returnData.setLen(0) cpt.returnData.setLen(0)
@ -241,17 +235,11 @@ const
raise newException( raise newException(
OutOfGas, "Gas not enough to perform calculation (call)") OutOfGas, "Gas not enough to perform calculation (call)")
gasCost = gasAtStart - cpt.gasMeter.gasRemaining
cpt.traceCallFamilyGas(Call, gasCost)
cpt.memory.extend(p.memInPos, p.memInLen) cpt.memory.extend(p.memInPos, p.memInLen)
cpt.memory.extend(p.memOutPos, p.memOutLen) cpt.memory.extend(p.memOutPos, p.memOutLen)
let senderBalance = cpt.getBalance(p.sender) let senderBalance = cpt.getBalance(p.sender)
if senderBalance < p.value: if senderBalance < p.value:
#debug "Insufficient funds",
# available = senderBalance,
# needed = cpt.msg.value
cpt.gasMeter.returnGas(childGasLimit) cpt.gasMeter.returnGas(childGasLimit)
return return
@ -293,7 +281,6 @@ const
## 0xf2, Message-call into this account with an alternative account's code. ## 0xf2, Message-call into this account with an alternative account's code.
let let
cpt = k.cpt cpt = k.cpt
gasAtStart = cpt.gasMeter.gasRemaining
p = cpt.callCodeParams p = cpt.callCodeParams
cpt.asyncChainTo(ifNecessaryGetAccounts(cpt.vmState, @[p.sender])): cpt.asyncChainTo(ifNecessaryGetAccounts(cpt.vmState, @[p.sender])):
@ -303,17 +290,15 @@ const
GasParams( GasParams(
kind: CallCode, kind: CallCode,
c_isNewAccount: not cpt.accountExists(p.contractAddress), c_isNewAccount: not cpt.accountExists(p.contractAddress),
c_gasBalance: cpt.gasMeter.gasRemaining, c_gasBalance: cpt.gasMeter.gasRemaining - p.gasCallEIP2929,
c_contractGas: p.gas, c_contractGas: p.gas,
c_currentMemSize: cpt.memory.len, c_currentMemSize: cpt.memory.len,
c_memOffset: p.memOffset, c_memOffset: p.memOffset,
c_memLength: p.memLength)) c_memLength: p.memLength))
# EIP 2046: temporary disabled gasCost += p.gasCallEIP2929
# reduce gas fee for precompiles
# from 700 to 40
if gasCost >= 0: if gasCost >= 0:
cpt.gasMeter.consumeGas(gasCost, reason = $CallCode) cpt.opcodeGastCost(CallCode, gasCost, reason = $CallCode)
cpt.returnData.setLen(0) cpt.returnData.setLen(0)
@ -325,24 +310,15 @@ const
cpt.gasMeter.returnGas(childGasLimit) cpt.gasMeter.returnGas(childGasLimit)
return return
# EIP 2046: temporary disabled
# reduce gas fee for precompiles
# from 700 to 40
if gasCost < 0 and childGasLimit <= 0: if gasCost < 0 and childGasLimit <= 0:
raise newException( raise newException(
OutOfGas, "Gas not enough to perform calculation (callCode)") OutOfGas, "Gas not enough to perform calculation (callCode)")
gasCost = gasAtStart - cpt.gasMeter.gasRemaining
cpt.traceCallFamilyGas(CallCode, gasCost)
cpt.memory.extend(p.memInPos, p.memInLen) cpt.memory.extend(p.memInPos, p.memInLen)
cpt.memory.extend(p.memOutPos, p.memOutLen) cpt.memory.extend(p.memOutPos, p.memOutLen)
let senderBalance = cpt.getBalance(p.sender) let senderBalance = cpt.getBalance(p.sender)
if senderBalance < p.value: if senderBalance < p.value:
#debug "Insufficient funds",
# available = senderBalance,
# needed = cpt.msg.value
cpt.gasMeter.returnGas(childGasLimit) cpt.gasMeter.returnGas(childGasLimit)
return return
@ -385,7 +361,6 @@ const
## code, but persisting the current values for sender and value. ## code, but persisting the current values for sender and value.
let let
cpt = k.cpt cpt = k.cpt
gasAtStart = cpt.gasMeter.gasRemaining
p = cpt.delegateCallParams p = cpt.delegateCallParams
cpt.asyncChainTo(ifNecessaryGetAccounts(cpt.vmState, @[p.sender])): cpt.asyncChainTo(ifNecessaryGetAccounts(cpt.vmState, @[p.sender])):
@ -395,17 +370,15 @@ const
GasParams( GasParams(
kind: DelegateCall, kind: DelegateCall,
c_isNewAccount: not cpt.accountExists(p.contractAddress), c_isNewAccount: not cpt.accountExists(p.contractAddress),
c_gasBalance: cpt.gasMeter.gasRemaining, c_gasBalance: cpt.gasMeter.gasRemaining - p.gasCallEIP2929,
c_contractGas: p.gas, c_contractGas: p.gas,
c_currentMemSize: cpt.memory.len, c_currentMemSize: cpt.memory.len,
c_memOffset: p.memOffset, c_memOffset: p.memOffset,
c_memLength: p.memLength)) c_memLength: p.memLength))
# EIP 2046: temporary disabled gasCost += p.gasCallEIP2929
# reduce gas fee for precompiles
# from 700 to 40
if gasCost >= 0: if gasCost >= 0:
cpt.gasMeter.consumeGas(gasCost, reason = $DelegateCall) cpt.opcodeGastCost(DelegateCall, gasCost, reason = $DelegateCall)
cpt.returnData.setLen(0) cpt.returnData.setLen(0)
if cpt.msg.depth >= MaxCallDepth: if cpt.msg.depth >= MaxCallDepth:
@ -420,9 +393,6 @@ const
raise newException( raise newException(
OutOfGas, "Gas not enough to perform calculation (delegateCall)") OutOfGas, "Gas not enough to perform calculation (delegateCall)")
gasCost = gasAtStart - cpt.gasMeter.gasRemaining
cpt.traceCallFamilyGas(DelegateCall, gasCost)
cpt.memory.extend(p.memInPos, p.memInLen) cpt.memory.extend(p.memInPos, p.memInLen)
cpt.memory.extend(p.memOutPos, p.memOutLen) cpt.memory.extend(p.memOutPos, p.memOutLen)
@ -465,7 +435,6 @@ const
let let
cpt = k.cpt cpt = k.cpt
gasAtStart = cpt.gasMeter.gasRemaining
p = cpt.staticCallParams p = cpt.staticCallParams
cpt.asyncChainTo(ifNecessaryGetAccounts(cpt.vmState, @[p.sender])): cpt.asyncChainTo(ifNecessaryGetAccounts(cpt.vmState, @[p.sender])):
@ -475,21 +444,15 @@ const
GasParams( GasParams(
kind: StaticCall, kind: StaticCall,
c_isNewAccount: not cpt.accountExists(p.contractAddress), c_isNewAccount: not cpt.accountExists(p.contractAddress),
c_gasBalance: cpt.gasMeter.gasRemaining, c_gasBalance: cpt.gasMeter.gasRemaining - p.gasCallEIP2929,
c_contractGas: p.gas, c_contractGas: p.gas,
c_currentMemSize: cpt.memory.len, c_currentMemSize: cpt.memory.len,
c_memOffset: p.memOffset, c_memOffset: p.memOffset,
c_memLength: p.memLength)) c_memLength: p.memLength))
# EIP 2046: temporary disabled gasCost += p.gasCallEIP2929
# reduce gas fee for precompiles
# from 700 to 40
#
# when opCode == StaticCall:
# if cpt.fork >= FkBerlin and codeAddress.toInt <= MaxPrecompilesAddr:
# gasCost = gasCost - 660.GasInt
if gasCost >= 0: if gasCost >= 0:
cpt.gasMeter.consumeGas(gasCost, reason = $StaticCall) cpt.opcodeGastCost(StaticCall, gasCost, reason = $StaticCall)
cpt.returnData.setLen(0) cpt.returnData.setLen(0)
@ -505,9 +468,6 @@ const
raise newException( raise newException(
OutOfGas, "Gas not enough to perform calculation (staticCall)") OutOfGas, "Gas not enough to perform calculation (staticCall)")
gasCost = gasAtStart - cpt.gasMeter.gasRemaining
cpt.traceCallFamilyGas(StaticCall, gasCost)
cpt.memory.extend(p.memInPos, p.memInLen) cpt.memory.extend(p.memInPos, p.memInLen)
cpt.memory.extend(p.memOutPos, p.memOutLen) cpt.memory.extend(p.memOutPos, p.memOutLen)

View File

@ -87,41 +87,42 @@ const
checkInStaticContext(k.cpt) checkInStaticContext(k.cpt)
let let
endowment = k.cpt.stack.popInt() cpt = k.cpt
memPos = k.cpt.stack.popInt().safeInt endowment = cpt.stack.popInt()
memLen = k.cpt.stack.peekInt().safeInt memPos = cpt.stack.popInt().safeInt
memLen = cpt.stack.peekInt().safeInt
k.cpt.stack.top(0) cpt.stack.top(0)
# EIP-3860 # EIP-3860
if k.cpt.fork >= FkShanghai and memLen > EIP3860_MAX_INITCODE_SIZE: if cpt.fork >= FkShanghai and memLen > EIP3860_MAX_INITCODE_SIZE:
trace "Initcode size exceeds maximum", initcodeSize = memLen trace "Initcode size exceeds maximum", initcodeSize = memLen
raise newException(InitcodeError, raise newException(InitcodeError,
&"CREATE: have {memLen}, max {EIP3860_MAX_INITCODE_SIZE}") &"CREATE: have {memLen}, max {EIP3860_MAX_INITCODE_SIZE}")
let let
gasAtStart = k.cpt.gasMeter.gasRemaining
gasParams = GasParams( gasParams = GasParams(
kind: Create, kind: Create,
cr_currentMemSize: k.cpt.memory.len, cr_currentMemSize: cpt.memory.len,
cr_memOffset: memPos, cr_memOffset: memPos,
cr_memLength: memLen) cr_memLength: memLen)
var gasCost = k.cpt.gasCosts[Create].c_handler(1.u256, gasParams).gasCost let gasCost = cpt.gasCosts[Create].c_handler(1.u256, gasParams).gasCost
k.cpt.gasMeter.consumeGas(
gasCost, reason = &"CREATE: GasCreate + {memLen} * memory expansion")
k.cpt.memory.extend(memPos, memLen)
k.cpt.returnData.setLen(0)
if k.cpt.msg.depth >= MaxCallDepth: cpt.opcodeGastCost(Create,
gasCost, reason = &"CREATE: GasCreate + {memLen} * memory expansion")
cpt.memory.extend(memPos, memLen)
cpt.returnData.setLen(0)
if cpt.msg.depth >= MaxCallDepth:
debug "Computation Failure", debug "Computation Failure",
reason = "Stack too deep", reason = "Stack too deep",
maxDepth = MaxCallDepth, maxDepth = MaxCallDepth,
depth = k.cpt.msg.depth depth = cpt.msg.depth
return return
if endowment != 0: if endowment != 0:
let senderBalance = k.cpt.getBalance(k.cpt.msg.contractAddress) let senderBalance = cpt.getBalance(cpt.msg.contractAddress)
if senderBalance < endowment: if senderBalance < endowment:
debug "Computation Failure", debug "Computation Failure",
reason = "Insufficient funds available to transfer", reason = "Insufficient funds available to transfer",
@ -129,38 +130,35 @@ const
balance = senderBalance balance = senderBalance
return return
var createMsgGas = k.cpt.gasMeter.gasRemaining var createMsgGas = cpt.gasMeter.gasRemaining
if k.cpt.fork >= FkTangerine: if cpt.fork >= FkTangerine:
createMsgGas -= createMsgGas div 64 createMsgGas -= createMsgGas div 64
k.cpt.gasMeter.consumeGas(createMsgGas, reason = "CREATE") cpt.gasMeter.consumeGas(createMsgGas, reason = "CREATE msg gas")
gasCost = gasAtStart - k.cpt.gasMeter.gasRemaining
k.cpt.traceCallFamilyGas(Create, gasCost)
when evmc_enabled: when evmc_enabled:
let let
msg = new(nimbus_message) msg = new(nimbus_message)
c = k.cpt c = cpt
msg[] = nimbus_message( msg[] = nimbus_message(
kind: evmcCreate.ord.evmc_call_kind, kind: evmcCreate.ord.evmc_call_kind,
depth: (k.cpt.msg.depth + 1).int32, depth: (cpt.msg.depth + 1).int32,
gas: createMsgGas, gas: createMsgGas,
sender: k.cpt.msg.contractAddress, sender: cpt.msg.contractAddress,
input_data: k.cpt.memory.readPtr(memPos), input_data: cpt.memory.readPtr(memPos),
input_size: memLen.uint, input_size: memLen.uint,
value: toEvmc(endowment), value: toEvmc(endowment),
create2_salt: toEvmc(ZERO_CONTRACTSALT), create2_salt: toEvmc(ZERO_CONTRACTSALT),
) )
c.execSubCreate(msg) c.execSubCreate(msg)
else: else:
k.cpt.execSubCreate( cpt.execSubCreate(
childMsg = Message( childMsg = Message(
kind: evmcCreate, kind: evmcCreate,
depth: k.cpt.msg.depth + 1, depth: cpt.msg.depth + 1,
gas: createMsgGas, gas: createMsgGas,
sender: k.cpt.msg.contractAddress, sender: cpt.msg.contractAddress,
value: endowment, value: endowment,
data: k.cpt.memory.read(memPos, memLen))) data: cpt.memory.read(memPos, memLen)))
# --------------------- # ---------------------
@ -169,44 +167,44 @@ const
checkInStaticContext(k.cpt) checkInStaticContext(k.cpt)
let let
endowment = k.cpt.stack.popInt() cpt = k.cpt
memPos = k.cpt.stack.popInt().safeInt endowment = cpt.stack.popInt()
memLen = k.cpt.stack.popInt().safeInt memPos = cpt.stack.popInt().safeInt
salt = ContractSalt(bytes: k.cpt.stack.peekInt().toBytesBE) memLen = cpt.stack.popInt().safeInt
salt = ContractSalt(bytes: cpt.stack.peekInt().toBytesBE)
k.cpt.stack.top(0) cpt.stack.top(0)
# EIP-3860 # EIP-3860
if k.cpt.fork >= FkShanghai and memLen > EIP3860_MAX_INITCODE_SIZE: if cpt.fork >= FkShanghai and memLen > EIP3860_MAX_INITCODE_SIZE:
trace "Initcode size exceeds maximum", initcodeSize = memLen trace "Initcode size exceeds maximum", initcodeSize = memLen
raise newException(InitcodeError, raise newException(InitcodeError,
&"CREATE2: have {memLen}, max {EIP3860_MAX_INITCODE_SIZE}") &"CREATE2: have {memLen}, max {EIP3860_MAX_INITCODE_SIZE}")
let let
gasAtStart = k.cpt.gasMeter.gasRemaining
gasParams = GasParams( gasParams = GasParams(
kind: Create, kind: Create,
cr_currentMemSize: k.cpt.memory.len, cr_currentMemSize: cpt.memory.len,
cr_memOffset: memPos, cr_memOffset: memPos,
cr_memLength: memLen) cr_memLength: memLen)
var gasCost = k.cpt.gasCosts[Create].c_handler(1.u256, gasParams).gasCost var gasCost = cpt.gasCosts[Create].c_handler(1.u256, gasParams).gasCost
gasCost = gasCost + k.cpt.gasCosts[Create2].m_handler(0, 0, memLen) gasCost = gasCost + cpt.gasCosts[Create2].m_handler(0, 0, memLen)
k.cpt.gasMeter.consumeGas( cpt.opcodeGastCost(Create2,
gasCost, reason = &"CREATE2: GasCreate + {memLen} * memory expansion") gasCost, reason = &"CREATE2: GasCreate + {memLen} * memory expansion")
k.cpt.memory.extend(memPos, memLen) cpt.memory.extend(memPos, memLen)
k.cpt.returnData.setLen(0) cpt.returnData.setLen(0)
if k.cpt.msg.depth >= MaxCallDepth: if cpt.msg.depth >= MaxCallDepth:
debug "Computation Failure", debug "Computation Failure",
reason = "Stack too deep", reason = "Stack too deep",
maxDepth = MaxCallDepth, maxDepth = MaxCallDepth,
depth = k.cpt.msg.depth depth = cpt.msg.depth
return return
if endowment != 0: if endowment != 0:
let senderBalance = k.cpt.getBalance(k.cpt.msg.contractAddress) let senderBalance = cpt.getBalance(cpt.msg.contractAddress)
if senderBalance < endowment: if senderBalance < endowment:
debug "Computation Failure", debug "Computation Failure",
reason = "Insufficient funds available to transfer", reason = "Insufficient funds available to transfer",
@ -214,39 +212,36 @@ const
balance = senderBalance balance = senderBalance
return return
var createMsgGas = k.cpt.gasMeter.gasRemaining var createMsgGas = cpt.gasMeter.gasRemaining
if k.cpt.fork >= FkTangerine: if cpt.fork >= FkTangerine:
createMsgGas -= createMsgGas div 64 createMsgGas -= createMsgGas div 64
k.cpt.gasMeter.consumeGas(createMsgGas, reason = "CREATE2") cpt.gasMeter.consumeGas(createMsgGas, reason = "CREATE2 msg gas")
gasCost = gasAtStart - k.cpt.gasMeter.gasRemaining
k.cpt.traceCallFamilyGas(Create2, gasCost)
when evmc_enabled: when evmc_enabled:
let let
msg = new(nimbus_message) msg = new(nimbus_message)
c = k.cpt c = cpt
msg[] = nimbus_message( msg[] = nimbus_message(
kind: evmcCreate2.ord.evmc_call_kind, kind: evmcCreate2.ord.evmc_call_kind,
depth: (k.cpt.msg.depth + 1).int32, depth: (cpt.msg.depth + 1).int32,
gas: createMsgGas, gas: createMsgGas,
sender: k.cpt.msg.contractAddress, sender: cpt.msg.contractAddress,
input_data: k.cpt.memory.readPtr(memPos), input_data: cpt.memory.readPtr(memPos),
input_size: memLen.uint, input_size: memLen.uint,
value: toEvmc(endowment), value: toEvmc(endowment),
create2_salt: toEvmc(salt), create2_salt: toEvmc(salt),
) )
c.execSubCreate(msg) c.execSubCreate(msg)
else: else:
k.cpt.execSubCreate( cpt.execSubCreate(
salt = salt, salt = salt,
childMsg = Message( childMsg = Message(
kind: evmcCreate2, kind: evmcCreate2,
depth: k.cpt.msg.depth + 1, depth: cpt.msg.depth + 1,
gas: createMsgGas, gas: createMsgGas,
sender: k.cpt.msg.contractAddress, sender: cpt.msg.contractAddress,
value: endowment, value: endowment,
data: k.cpt.memory.read(memPos, memLen))) data: cpt.memory.read(memPos, memLen)))
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Public, op exec table entries # Public, op exec table entries

View File

@ -20,7 +20,6 @@ import
../../stack, ../../stack,
../../async/operations, ../../async/operations,
../gas_costs, ../gas_costs,
../gas_meter,
../op_codes, ../op_codes,
../utils/utils_numeric, ../utils/utils_numeric,
./oph_defs, ./oph_defs,
@ -84,7 +83,8 @@ const
let address = cpt.stack.popAddress() let address = cpt.stack.popAddress()
cpt.asyncChainTo(ifNecessaryGetAccount(cpt.vmState, address)): cpt.asyncChainTo(ifNecessaryGetAccount(cpt.vmState, address)):
cpt.gasEip2929AccountCheck(address) let gasCost = cpt.gasCosts[Balance].cost + cpt.gasEip2929AccountCheck(address)
cpt.opcodeGastCost(Balance, gasCost, reason = "Balance EIP2929")
cpt.stack.push: cpt.stack.push:
cpt.getBalance(address) cpt.getBalance(address)
@ -140,7 +140,7 @@ const
let (memPos, copyPos, len) = let (memPos, copyPos, len) =
(memStartPos.cleanMemRef, copyStartPos.cleanMemRef, size.cleanMemRef) (memStartPos.cleanMemRef, copyStartPos.cleanMemRef, size.cleanMemRef)
k.cpt.gasMeter.consumeGas( k.cpt.opcodeGastCost(CallDataCopy,
k.cpt.gasCosts[CallDataCopy].m_handler(k.cpt.memory.len, memPos, len), k.cpt.gasCosts[CallDataCopy].m_handler(k.cpt.memory.len, memPos, len),
reason = "CallDataCopy fee") reason = "CallDataCopy fee")
@ -165,7 +165,7 @@ const
let (memPos, copyPos, len) = let (memPos, copyPos, len) =
(memStartPos.cleanMemRef, copyStartPos.cleanMemRef, size.cleanMemRef) (memStartPos.cleanMemRef, copyStartPos.cleanMemRef, size.cleanMemRef)
cpt.gasMeter.consumeGas( cpt.opcodeGastCost(CodeCopy,
cpt.gasCosts[CodeCopy].m_handler(cpt.memory.len, memPos, len), cpt.gasCosts[CodeCopy].m_handler(cpt.memory.len, memPos, len),
reason = "CodeCopy fee") reason = "CodeCopy fee")
@ -193,7 +193,8 @@ const
let address = cpt.stack.popAddress() let address = cpt.stack.popAddress()
cpt.asyncChainTo(ifNecessaryGetCode(cpt.vmState, address)): cpt.asyncChainTo(ifNecessaryGetCode(cpt.vmState, address)):
cpt.gasEip2929AccountCheck(address) let gasCost = cpt.gasCosts[ExtCodeSize].cost + cpt.gasEip2929AccountCheck(address)
cpt.opcodeGastCost(ExtCodeSize, gasCost, reason = "ExtCodeSize EIP2929")
cpt.stack.push: cpt.stack.push:
cpt.getCodeSize(address) cpt.getCodeSize(address)
@ -209,7 +210,7 @@ const
let (memPos, codePos, len) = let (memPos, codePos, len) =
(memStartPos.cleanMemRef, codeStartPos.cleanMemRef, size.cleanMemRef) (memStartPos.cleanMemRef, codeStartPos.cleanMemRef, size.cleanMemRef)
cpt.gasMeter.consumeGas( cpt.opcodeGastCost(ExtCodeCopy,
cpt.gasCosts[ExtCodeCopy].m_handler(cpt.memory.len, memPos, len), cpt.gasCosts[ExtCodeCopy].m_handler(cpt.memory.len, memPos, len),
reason = "ExtCodeCopy fee") reason = "ExtCodeCopy fee")
@ -226,11 +227,10 @@ const
let (memStartPos, codeStartPos, size) = cpt.stack.popInt(3) let (memStartPos, codeStartPos, size) = cpt.stack.popInt(3)
let (memPos, codePos, len) = (memStartPos.cleanMemRef, let (memPos, codePos, len) = (memStartPos.cleanMemRef,
codeStartPos.cleanMemRef, size.cleanMemRef) codeStartPos.cleanMemRef, size.cleanMemRef)
cpt.gasMeter.consumeGas(
cpt.gasCosts[ExtCodeCopy].m_handler(cpt.memory.len, memPos, len),
reason = "ExtCodeCopy fee")
let gasCost = cpt.gasCosts[ExtCodeCopy].m_handler(cpt.memory.len, memPos, len) +
cpt.gasEip2929AccountCheck(address) cpt.gasEip2929AccountCheck(address)
cpt.opcodeGastCost(ExtCodeCopy, gasCost, reason = "ExtCodeCopy EIP2929")
let codeBytes = cpt.getCode(address) let codeBytes = cpt.getCode(address)
cpt.memory.writePaddedResult(codeBytes, memPos, codePos, len) cpt.memory.writePaddedResult(codeBytes, memPos, codePos, len)
@ -253,7 +253,7 @@ const
let gasCost = k.cpt.gasCosts[ReturnDataCopy].m_handler( let gasCost = k.cpt.gasCosts[ReturnDataCopy].m_handler(
k.cpt.memory.len, memPos, len) k.cpt.memory.len, memPos, len)
k.cpt.gasMeter.consumeGas(gasCost, reason = "returnDataCopy fee") k.cpt.opcodeGastCost(ReturnDataCopy, gasCost, reason = "returnDataCopy fee")
if copyPos + len > k.cpt.returnData.len: if copyPos + len > k.cpt.returnData.len:
raise newException( raise newException(
@ -280,7 +280,8 @@ const
let address = k.cpt.stack.popAddress() let address = k.cpt.stack.popAddress()
cpt.asyncChainTo(ifNecessaryGetCode(cpt.vmState, address)): cpt.asyncChainTo(ifNecessaryGetCode(cpt.vmState, address)):
cpt.gasEip2929AccountCheck(address) let gasCost = cpt.gasCosts[ExtCodeHash].cost + cpt.gasEip2929AccountCheck(address)
cpt.opcodeGastCost(ExtCodeHash, gasCost, reason = "ExtCodeHash EIP2929")
cpt.stack.push: cpt.stack.push:
cpt.getCodeHash(address) cpt.getCodeHash(address)

View File

@ -19,7 +19,6 @@ import
../../memory, ../../memory,
../../stack, ../../stack,
../gas_costs, ../gas_costs,
../gas_meter,
../op_codes, ../op_codes,
../utils/utils_numeric, ../utils/utils_numeric,
./oph_defs, ./oph_defs,
@ -40,7 +39,7 @@ const
if pos < 0 or len < 0 or pos > 2147483648'i64: if pos < 0 or len < 0 or pos > 2147483648'i64:
raise newException(OutOfBoundsRead, "Out of bounds memory access") raise newException(OutOfBoundsRead, "Out of bounds memory access")
k.cpt.gasMeter.consumeGas( k.cpt.opcodeGastCost(Op.Sha3,
k.cpt.gasCosts[Op.Sha3].m_handler(k.cpt.memory.len, pos, len), k.cpt.gasCosts[Op.Sha3].m_handler(k.cpt.memory.len, pos, len),
reason = "SHA3: word gas cost") reason = "SHA3: word gas cost")

View File

@ -18,7 +18,6 @@ import
../../../errors, ../../../errors,
../../types, ../../types,
../gas_costs, ../gas_costs,
../gas_meter,
eth/common, eth/common,
eth/common/eth_types, eth/common/eth_types,
macros, macros,
@ -35,26 +34,33 @@ else:
# Public # Public
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
proc gasEip2929AccountCheck*(c: Computation; address: EthAddress) = proc gasEip2929AccountCheck*(c: Computation; address: EthAddress): GasInt =
when defined(evmc_enabled): when defined(evmc_enabled):
let gasCost = if c.host.accessAccount(address) == EVMC_ACCESS_COLD: result = if c.host.accessAccount(address) == EVMC_ACCESS_COLD:
ColdAccountAccessCost ColdAccountAccessCost
else: else:
WarmStorageReadCost WarmStorageReadCost
c.gasMeter.consumeGas(
gasCost,
reason = "gasEIP2929AccountCheck")
else: else:
c.vmState.mutateStateDB: c.vmState.mutateStateDB:
let gasCost = if not db.inAccessList(address): result = if not db.inAccessList(address):
db.accessList(address) db.accessList(address)
ColdAccountAccessCost ColdAccountAccessCost
else: else:
WarmStorageReadCost WarmStorageReadCost
c.gasMeter.consumeGas( proc gasEip2929AccountCheck*(c: Computation; address: EthAddress, slot: UInt256): GasInt =
gasCost, when defined(evmc_enabled):
reason = "gasEIP2929AccountCheck") result = if c.host.accessStorage(address, slot) == EVMC_ACCESS_COLD:
ColdSloadCost
else:
WarmStorageReadCost
else:
c.vmState.mutateStateDB:
result = if not db.inAccessList(address, slot):
db.accessList(address, slot)
ColdSloadCost
else:
WarmStorageReadCost
template checkInStaticContext*(c: Computation) = template checkInStaticContext*(c: Computation) =
## Verify static context in handler function, raise an error otherwise ## Verify static context in handler function, raise an error otherwise

View File

@ -20,7 +20,6 @@ import
../../stack, ../../stack,
../../types, ../../types,
../gas_costs, ../gas_costs,
../gas_meter,
../op_codes, ../op_codes,
../utils/utils_numeric, ../utils/utils_numeric,
./oph_defs, ./oph_defs,
@ -59,7 +58,7 @@ proc logImpl(c: Computation, opcode: Op, topicCount: int) =
if memPos < 0 or len < 0: if memPos < 0 or len < 0:
raise newException(OutOfBoundsRead, "Out of bounds memory access") raise newException(OutOfBoundsRead, "Out of bounds memory access")
c.gasMeter.consumeGas( c.opcodeGastCost(opcode,
c.gasCosts[opcode].m_handler(c.memory.len, memPos, len), c.gasCosts[opcode].m_handler(c.memory.len, memPos, len),
reason = "Memory expansion, Log topic and data gas cost") reason = "Memory expansion, Log topic and data gas cost")
c.memory.extend(memPos, len) c.memory.extend(memPos, len)

View File

@ -41,15 +41,14 @@ when not defined(evmc_enabled):
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
when evmc_enabled: when evmc_enabled:
proc sstoreEvmc(c: Computation, slot, newValue: UInt256) = proc sstoreEvmc(c: Computation, slot, newValue: UInt256, coldAccess = 0.GasInt) =
let let
currentValue = c.getStorage(slot) currentValue = c.getStorage(slot)
status = c.host.setStorage(c.msg.contractAddress, slot, newValue) status = c.host.setStorage(c.msg.contractAddress, slot, newValue)
gasParam = GasParams(kind: Op.Sstore, s_status: status) gasParam = GasParams(kind: Op.Sstore, s_status: status)
gasCost = c.gasCosts[Sstore].c_handler(newValue, gasParam)[0] gasCost = c.gasCosts[Sstore].c_handler(newValue, gasParam)[0] + coldAccess
c.gasMeter.consumeGas( c.opcodeGastCost(Sstore, gasCost, "SSTORE")
gasCost, "SSTORE")
else: else:
proc sstoreImpl(c: Computation, slot, newValue: UInt256) = proc sstoreImpl(c: Computation, slot, newValue: UInt256) =
@ -62,8 +61,7 @@ else:
(gasCost, gasRefund) = (gasCost, gasRefund) =
c.gasCosts[Sstore].c_handler(newValue, gasParam) c.gasCosts[Sstore].c_handler(newValue, gasParam)
c.gasMeter.consumeGas( c.opcodeGastCost(Sstore, gasCost, "SSTORE")
gasCost, "SSTORE")
if gasRefund > 0: if gasRefund > 0:
c.gasMeter.refundGas(gasRefund) c.gasMeter.refundGas(gasRefund)
@ -71,7 +69,7 @@ else:
db.setStorage(c.msg.contractAddress, slot, newValue) db.setStorage(c.msg.contractAddress, slot, newValue)
proc sstoreNetGasMeteringImpl(c: Computation; slot, newValue: UInt256) = proc sstoreNetGasMeteringImpl(c: Computation; slot, newValue: UInt256, coldAccess = 0.GasInt) =
let let
stateDB = c.vmState.readOnlyStateDB stateDB = c.vmState.readOnlyStateDB
currentValue = c.getStorage(slot) currentValue = c.getStorage(slot)
@ -81,17 +79,21 @@ else:
s_currentValue: currentValue, s_currentValue: currentValue,
s_originalValue: stateDB.getCommittedStorage(c.msg.contractAddress, slot)) s_originalValue: stateDB.getCommittedStorage(c.msg.contractAddress, slot))
(gasCost, gasRefund) = c.gasCosts[Sstore].c_handler(newValue, gasParam) res = c.gasCosts[Sstore].c_handler(newValue, gasParam)
c.gasMeter.consumeGas( c.opcodeGastCost(Sstore, res.gasCost + coldAccess, "SSTORE")
gasCost, "SSTORE EIP2200")
if gasRefund != 0: if res.gasRefund != 0:
c.gasMeter.refundGas(gasRefund) c.gasMeter.refundGas(res.gasRefund)
c.vmState.mutateStateDB: c.vmState.mutateStateDB:
db.setStorage(c.msg.contractAddress, slot, newValue) db.setStorage(c.msg.contractAddress, slot, newValue)
template sstoreEvmcOrNetGasMetering(cpt, slot, newValue: untyped, coldAccess = 0.GasInt) =
when evmc_enabled:
sstoreEvmc(cpt, slot, newValue, coldAccess)
else:
sstoreNetGasMeteringImpl(cpt, slot, newValue, coldAccess)
proc jumpImpl(c: Computation; jumpTarget: UInt256) = proc jumpImpl(c: Computation; jumpTarget: UInt256) =
if jumpTarget >= c.code.len.u256: if jumpTarget >= c.code.len.u256:
@ -124,7 +126,7 @@ const
let (memStartPos) = k.cpt.stack.popInt(1) let (memStartPos) = k.cpt.stack.popInt(1)
let memPos = memStartPos.cleanMemRef let memPos = memStartPos.cleanMemRef
k.cpt.gasMeter.consumeGas( k.cpt.opcodeGastCost(Mload,
k.cpt.gasCosts[Mload].m_handler(k.cpt.memory.len, memPos, 32), k.cpt.gasCosts[Mload].m_handler(k.cpt.memory.len, memPos, 32),
reason = "MLOAD: GasVeryLow + memory expansion") reason = "MLOAD: GasVeryLow + memory expansion")
@ -138,7 +140,7 @@ const
let (memStartPos, value) = k.cpt.stack.popInt(2) let (memStartPos, value) = k.cpt.stack.popInt(2)
let memPos = memStartPos.cleanMemRef let memPos = memStartPos.cleanMemRef
k.cpt.gasMeter.consumeGas( k.cpt.opcodeGastCost(Mstore,
k.cpt.gasCosts[Mstore].m_handler(k.cpt.memory.len, memPos, 32), k.cpt.gasCosts[Mstore].m_handler(k.cpt.memory.len, memPos, 32),
reason = "MSTORE: GasVeryLow + memory expansion") reason = "MSTORE: GasVeryLow + memory expansion")
@ -151,8 +153,8 @@ const
let (memStartPos, value) = k.cpt.stack.popInt(2) let (memStartPos, value) = k.cpt.stack.popInt(2)
let memPos = memStartPos.cleanMemRef let memPos = memStartPos.cleanMemRef
k.cpt.gasMeter.consumeGas( k.cpt.opcodeGastCost(Mstore8,
k.cpt.gasCosts[Mstore].m_handler(k.cpt.memory.len, memPos, 1), k.cpt.gasCosts[Mstore8].m_handler(k.cpt.memory.len, memPos, 1),
reason = "MSTORE8: GasVeryLow + memory expansion") reason = "MSTORE8: GasVeryLow + memory expansion")
k.cpt.memory.extend(memPos, 1) k.cpt.memory.extend(memPos, 1)
@ -174,20 +176,9 @@ const
let (slot) = cpt.stack.popInt(1) let (slot) = cpt.stack.popInt(1)
cpt.asyncChainTo(ifNecessaryGetSlot(cpt.vmState, cpt.msg.contractAddress, slot)): cpt.asyncChainTo(ifNecessaryGetSlot(cpt.vmState, cpt.msg.contractAddress, slot)):
when evmc_enabled: let gasCost = cpt.gasEip2929AccountCheck(cpt.msg.contractAddress, slot) +
let gasCost = if cpt.host.accessStorage(cpt.msg.contractAddress, slot) == EVMC_ACCESS_COLD: cpt.gasCosts[Sload].cost
ColdSloadCost cpt.opcodeGastCost(Sload, gasCost, reason = "sloadEIP2929")
else:
WarmStorageReadCost
cpt.gasMeter.consumeGas(gasCost, reason = "sloadEIP2929")
else:
cpt.vmState.mutateStateDB:
let gasCost = if not db.inAccessList(cpt.msg.contractAddress, slot):
db.accessList(cpt.msg.contractAddress, slot)
ColdSloadCost
else:
WarmStorageReadCost
cpt.gasMeter.consumeGas(gasCost, reason = "sloadEIP2929")
cpt.stack.push: cpt.stack.push:
cpt.getStorage(slot) cpt.getStorage(slot)
@ -200,10 +191,7 @@ const
checkInStaticContext(cpt) checkInStaticContext(cpt)
cpt.asyncChainTo(ifNecessaryGetSlot(cpt.vmState, cpt.msg.contractAddress, slot)): cpt.asyncChainTo(ifNecessaryGetSlot(cpt.vmState, cpt.msg.contractAddress, slot)):
when evmc_enabled: sstoreEvmcOrNetGasMetering(cpt, slot, newValue)
sstoreEvmc(cpt, slot, newValue)
else:
sstoreImpl(cpt, slot, newValue)
sstoreEIP1283Op: Vm2OpFn = proc (k: var Vm2Ctx) = sstoreEIP1283Op: Vm2OpFn = proc (k: var Vm2Ctx) =
@ -213,10 +201,7 @@ const
checkInStaticContext(cpt) checkInStaticContext(cpt)
cpt.asyncChainTo(ifNecessaryGetSlot(cpt.vmState, cpt.msg.contractAddress, slot)): cpt.asyncChainTo(ifNecessaryGetSlot(cpt.vmState, cpt.msg.contractAddress, slot)):
when evmc_enabled: sstoreEvmcOrNetGasMetering(cpt, slot, newValue)
sstoreEvmc(cpt, slot, newValue)
else:
sstoreNetGasMeteringImpl(cpt, slot, newValue)
sstoreEIP2200Op: Vm2OpFn = proc (k: var Vm2Ctx) = sstoreEIP2200Op: Vm2OpFn = proc (k: var Vm2Ctx) =
@ -233,10 +218,7 @@ const
"Gas not enough to perform EIP2200 SSTORE") "Gas not enough to perform EIP2200 SSTORE")
cpt.asyncChainTo(ifNecessaryGetSlot(cpt.vmState, cpt.msg.contractAddress, slot)): cpt.asyncChainTo(ifNecessaryGetSlot(cpt.vmState, cpt.msg.contractAddress, slot)):
when evmc_enabled: sstoreEvmcOrNetGasMetering(cpt, slot, newValue)
sstoreEvmc(cpt, slot, newValue)
else:
sstoreNetGasMeteringImpl(cpt, slot, newValue)
sstoreEIP2929Op: Vm2OpFn = proc (k: var Vm2Ctx) = sstoreEIP2929Op: Vm2OpFn = proc (k: var Vm2Ctx) =
@ -252,19 +234,17 @@ const
raise newException(OutOfGas, "Gas not enough to perform EIP2200 SSTORE") raise newException(OutOfGas, "Gas not enough to perform EIP2200 SSTORE")
cpt.asyncChainTo(ifNecessaryGetSlot(cpt.vmState, cpt.msg.contractAddress, slot)): cpt.asyncChainTo(ifNecessaryGetSlot(cpt.vmState, cpt.msg.contractAddress, slot)):
var coldAccessGas = 0.GasInt
when evmc_enabled: when evmc_enabled:
if cpt.host.accessStorage(cpt.msg.contractAddress, slot) == EVMC_ACCESS_COLD: if cpt.host.accessStorage(cpt.msg.contractAddress, slot) == EVMC_ACCESS_COLD:
cpt.gasMeter.consumeGas(ColdSloadCost, reason = "sstoreEIP2929") coldAccessGas = ColdSloadCost
else: else:
cpt.vmState.mutateStateDB: cpt.vmState.mutateStateDB:
if not db.inAccessList(cpt.msg.contractAddress, slot): if not db.inAccessList(cpt.msg.contractAddress, slot):
db.accessList(cpt.msg.contractAddress, slot) db.accessList(cpt.msg.contractAddress, slot)
cpt.gasMeter.consumeGas(ColdSloadCost, reason = "sstoreEIP2929") coldAccessGas = ColdSloadCost
when evmc_enabled: sstoreEvmcOrNetGasMetering(cpt, slot, newValue, coldAccessGas)
sstoreEvmc(cpt, slot, newValue)
else:
sstoreNetGasMeteringImpl(cpt, slot, newValue)
# ------- # -------
@ -324,7 +304,7 @@ const
let (dstPos, srcPos, len) = let (dstPos, srcPos, len) =
(dst.cleanMemRef, src.cleanMemRef, size.cleanMemRef) (dst.cleanMemRef, src.cleanMemRef, size.cleanMemRef)
k.cpt.gasMeter.consumeGas( k.cpt.opcodeGastCost(Mcopy,
k.cpt.gasCosts[Mcopy].m_handler(k.cpt.memory.len, max(dstPos, srcPos), len), k.cpt.gasCosts[Mcopy].m_handler(k.cpt.memory.len, max(dstPos, srcPos), len),
reason = "Mcopy fee") reason = "Mcopy fee")

View File

@ -20,7 +20,6 @@ import
../../types, ../../types,
../../async/operations, ../../async/operations,
../gas_costs, ../gas_costs,
../gas_meter,
../op_codes, ../op_codes,
../utils/utils_numeric, ../utils/utils_numeric,
./oph_defs, ./oph_defs,
@ -45,7 +44,7 @@ const
let (startPos, size) = k.cpt.stack.popInt(2) let (startPos, size) = k.cpt.stack.popInt(2)
let (pos, len) = (startPos.cleanMemRef, size.cleanMemRef) let (pos, len) = (startPos.cleanMemRef, size.cleanMemRef)
k.cpt.gasMeter.consumeGas( k.cpt.opcodeGastCost(Return,
k.cpt.gasCosts[Return].m_handler(k.cpt.memory.len, pos, len), k.cpt.gasCosts[Return].m_handler(k.cpt.memory.len, pos, len),
reason = "RETURN") reason = "RETURN")
k.cpt.memory.extend(pos, len) k.cpt.memory.extend(pos, len)
@ -58,7 +57,7 @@ const
let (startPos, size) = k.cpt.stack.popInt(2) let (startPos, size) = k.cpt.stack.popInt(2)
let (pos, len) = (startPos.cleanMemRef, size.cleanMemRef) let (pos, len) = (startPos.cleanMemRef, size.cleanMemRef)
k.cpt.gasMeter.consumeGas( k.cpt.opcodeGastCost(Revert,
k.cpt.gasCosts[Revert].m_handler(k.cpt.memory.len, pos, len), k.cpt.gasCosts[Revert].m_handler(k.cpt.memory.len, pos, len),
reason = "REVERT") reason = "REVERT")
@ -95,7 +94,7 @@ const
let gasCost = let gasCost =
cpt.gasCosts[SelfDestruct].c_handler(0.u256, gasParams).gasCost cpt.gasCosts[SelfDestruct].c_handler(0.u256, gasParams).gasCost
cpt.gasMeter.consumeGas( cpt.opcodeGastCost(SelfDestruct,
gasCost, reason = "SELFDESTRUCT EIP150") gasCost, reason = "SELFDESTRUCT EIP150")
cpt.selfDestruct(beneficiary) cpt.selfDestruct(beneficiary)
@ -117,7 +116,7 @@ const
let gasCost = let gasCost =
cpt.gasCosts[SelfDestruct].c_handler(0.u256, gasParams).gasCost cpt.gasCosts[SelfDestruct].c_handler(0.u256, gasParams).gasCost
cpt.gasMeter.consumeGas( cpt.opcodeGastCost(SelfDestruct,
gasCost, reason = "SELFDESTRUCT EIP161") gasCost, reason = "SELFDESTRUCT EIP161")
cpt.selfDestruct(beneficiary) cpt.selfDestruct(beneficiary)
@ -149,7 +148,7 @@ const
db.accessList(beneficiary) db.accessList(beneficiary)
gasCost = gasCost + ColdAccountAccessCost gasCost = gasCost + ColdAccountAccessCost
cpt.gasMeter.consumeGas( cpt.opcodeGastCost(SelfDestruct,
gasCost, reason = "SELFDESTRUCT EIP2929") gasCost, reason = "SELFDESTRUCT EIP2929")
cpt.selfDestruct(beneficiary) cpt.selfDestruct(beneficiary)

View File

@ -34,6 +34,7 @@ type
paPairing = 0x08, paPairing = 0x08,
# Istanbul # Istanbul
paBlake2bf = 0x09, paBlake2bf = 0x09,
paPointEvaluation = 0x0A
# Berlin # Berlin
# EIP-2537: disabled # EIP-2537: disabled
# reason: not included in berlin # reason: not included in berlin
@ -47,7 +48,7 @@ type
# paBlsMapG1 # paBlsMapG1
# paBlsMapG2 # paBlsMapG2
# Cancun # Cancun
paPointEvaluation = 0x0A
proc getMaxPrecompileAddr(fork: EVMFork): PrecompileAddresses = proc getMaxPrecompileAddr(fork: EVMFork): PrecompileAddresses =
if fork < FkByzantium: paIdentity if fork < FkByzantium: paIdentity
@ -705,7 +706,7 @@ proc execPrecompiles*(computation: Computation, fork: EVMFork): bool {.inline.}
of paPairing: bn256ecPairing(computation, fork) of paPairing: bn256ecPairing(computation, fork)
of paBlake2bf: blake2bf(computation) of paBlake2bf: blake2bf(computation)
of paPointEvaluation: pointEvaluation(computation) of paPointEvaluation: pointEvaluation(computation)
else: discard #else: discard
# EIP 2537: disabled # EIP 2537: disabled
# reason: not included in berlin # reason: not included in berlin
# of paBlsG1Add: blsG1Add(computation) # of paBlsG1Add: blsG1Add(computation)

View File

@ -17,7 +17,7 @@ import
../db/accounts_cache, ../db/accounts_cache,
../common/[common, evmforks], ../common/[common, evmforks],
./async/data_sources, ./async/data_sources,
./interpreter/op_codes, ./interpreter/[op_codes, gas_costs],
./types ./types
proc init( proc init(
@ -391,28 +391,32 @@ proc captureOpStart*(vmState: BaseVMState, comp: Computation, pc: int,
op: Op, gas: GasInt, op: Op, gas: GasInt,
depth: int): int = depth: int): int =
if vmState.tracingEnabled: if vmState.tracingEnabled:
result = vmState.tracer.captureOpStart(comp, pc, op, gas, depth) let fixed = vmState.gasCosts[op].kind == GckFixed
result = vmState.tracer.captureOpStart(comp, fixed, pc, op, gas, depth)
proc callFamilyGas*(vmState: BaseVMState, proc captureGasCost*(vmState: BaseVMState,
comp: Computation, comp: Computation,
op: Op, gas: GasInt, op: Op, gasCost: GasInt, gasRemaining: GasInt,
depth: int) = depth: int) =
if vmState.tracingEnabled: if vmState.tracingEnabled:
vmState.tracer.callFamilyGas(comp, op, gas, depth) let fixed = vmState.gasCosts[op].kind == GckFixed
vmState.tracer.captureGasCost(comp, fixed, op, gasCost, gasRemaining, depth)
proc captureOpEnd*(vmState: BaseVMState, comp: Computation, pc: int, proc captureOpEnd*(vmState: BaseVMState, comp: Computation, pc: int,
op: Op, gas: GasInt, refund: GasInt, op: Op, gas: GasInt, refund: GasInt,
rData: openArray[byte], rData: openArray[byte],
depth: int, opIndex: int) = depth: int, opIndex: int) =
if vmState.tracingEnabled: if vmState.tracingEnabled:
vmState.tracer.captureOpEnd(comp, pc, op, gas, refund, rData, depth, opIndex) let fixed = vmState.gasCosts[op].kind == GckFixed
vmState.tracer.captureOpEnd(comp, fixed, pc, op, gas, refund, rData, depth, opIndex)
proc captureFault*(vmState: BaseVMState, comp: Computation, pc: int, proc captureFault*(vmState: BaseVMState, comp: Computation, pc: int,
op: Op, gas: GasInt, refund: GasInt, op: Op, gas: GasInt, refund: GasInt,
rData: openArray[byte], rData: openArray[byte],
depth: int, error: Option[string]) = depth: int, error: Option[string]) =
if vmState.tracingEnabled: if vmState.tracingEnabled:
vmState.tracer.captureFault(comp, pc, op, gas, refund, rData, depth, error) let fixed = vmState.gasCosts[op].kind == GckFixed
vmState.tracer.captureFault(comp, fixed, pc, op, gas, refund, rData, depth, error)
proc capturePrepare*(vmState: BaseVMState, comp: Computation, depth: int) = proc capturePrepare*(vmState: BaseVMState, comp: Computation, depth: int) =
if vmState.tracingEnabled: if vmState.tracingEnabled:

View File

@ -28,17 +28,7 @@ type
stack: JsonNode stack: JsonNode
storageKeys: seq[HashSet[UInt256]] storageKeys: seq[HashSet[UInt256]]
index: int index: int
callFamilyNode: JsonNode node: JsonNode
const
callFamily = [
Create,
Create2,
Call,
CallCode,
DelegateCall,
StaticCall,
]
template stripLeadingZeros(value: string): string = template stripLeadingZeros(value: string): string =
var cidx = 0 var cidx = 0
@ -47,9 +37,12 @@ template stripLeadingZeros(value: string): string =
cidx.inc cidx.inc
value[cidx .. ^1] value[cidx .. ^1]
proc encodeHexInt(x: SomeInteger): JsonNode = proc encodeHex(x: SomeInteger): JsonNode =
%("0x" & x.toHex.stripLeadingZeros.toLowerAscii) %("0x" & x.toHex.stripLeadingZeros.toLowerAscii)
proc encodeHex(x: UInt256): string =
"0x" & x.dumpHex.stripLeadingZeros
proc `%`(x: openArray[byte]): JsonNode = proc `%`(x: openArray[byte]): JsonNode =
if x.len == 0: if x.len == 0:
%("") %("")
@ -77,16 +70,15 @@ iterator storage(ctx: JsonTracer, compDepth: int): UInt256 =
proc captureOpImpl(ctx: JsonTracer, c: Computation, pc: int, proc captureOpImpl(ctx: JsonTracer, c: Computation, pc: int,
op: Op, gas: GasInt, refund: GasInt, op: Op, gas: GasInt, refund: GasInt,
rData: openArray[byte], rData: openArray[byte], depth: int, error: Option[string]) {.gcsafe.} =
depth: int, error: Option[string]) {.gcsafe.} =
let let
gasCost = ctx.gas - gas gasCost = ctx.gas - gas
var res = %{ var res = %{
"pc": %(ctx.pc), "pc": %(ctx.pc),
"op": %(op.int), "op": %(op.int),
"gas": encodeHexInt(ctx.gas), "gas": encodeHex(ctx.gas),
"gasCost": encodeHexInt(gasCost), "gasCost": encodeHex(gasCost),
"memSize": %(c.memory.len) "memSize": %(c.memory.len)
} }
@ -114,8 +106,7 @@ proc captureOpImpl(ctx: JsonTracer, c: Computation, pc: int,
var stateDB = c.vmState.stateDB var stateDB = c.vmState.stateDB
for key in ctx.storage(c.msg.depth): for key in ctx.storage(c.msg.depth):
let value = stateDB.getStorage(c.msg.contractAddress, key) let value = stateDB.getStorage(c.msg.contractAddress, key)
storage["0x" & key.dumpHex.stripLeadingZeros] = storage[key.encodeHex] = %(value.encodeHex)
%("0x" & value.dumpHex.stripLeadingZeros)
res["storage"] = storage res["storage"] = storage
res["depth"] = %(depth) res["depth"] = %(depth)
@ -125,10 +116,7 @@ proc captureOpImpl(ctx: JsonTracer, c: Computation, pc: int,
if error.isSome: if error.isSome:
res["error"] = %(error.get) res["error"] = %(error.get)
if op in callFamily: ctx.node = res
ctx.callFamilyNode = res
else:
ctx.writeJson(res)
proc newJsonTracer*(stream: Stream, flags: set[TracerFlags], pretty: bool): JsonTracer = proc newJsonTracer*(stream: Stream, flags: set[TracerFlags], pretty: bool): JsonTracer =
JsonTracer( JsonTracer(
@ -157,15 +145,15 @@ method captureEnd*(ctx: JsonTracer, comp: Computation, output: openArray[byte],
gasUsed: GasInt, error: Option[string]) {.gcsafe.} = gasUsed: GasInt, error: Option[string]) {.gcsafe.} =
var res = %{ var res = %{
"output": %(output), "output": %(output),
"gasUsed": encodeHexInt(gasUsed) "gasUsed": encodeHex(gasUsed)
} }
if error.isSome: if error.isSome:
res["error"] = %(error.get()) res["error"] = %(error.get())
ctx.writeJson(res) ctx.writeJson(res)
# Opcode level # Opcode level
method captureOpStart*(ctx: JsonTracer, c: Computation, pc: int, method captureOpStart*(ctx: JsonTracer, c: Computation,
op: Op, gas: GasInt, fixed: bool, pc: int, op: Op, gas: GasInt,
depth: int): int {.gcsafe.} = depth: int): int {.gcsafe.} =
ctx.gas = gas ctx.gas = gas
ctx.pc = pc ctx.pc = pc
@ -173,7 +161,7 @@ method captureOpStart*(ctx: JsonTracer, c: Computation, pc: int,
if TracerFlags.DisableStack notin ctx.flags: if TracerFlags.DisableStack notin ctx.flags:
ctx.stack = newJArray() ctx.stack = newJArray()
for v in c.stack.values: for v in c.stack.values:
ctx.stack.add(%("0x" & v.dumpHex.stripLeadingZeros)) ctx.stack.add(%(v.encodeHex))
if TracerFlags.DisableStorage notin ctx.flags and op == SSTORE: if TracerFlags.DisableStorage notin ctx.flags and op == SSTORE:
try: try:
@ -184,47 +172,71 @@ method captureOpStart*(ctx: JsonTracer, c: Computation, pc: int,
except ValueError as ex: except ValueError as ex:
error "JsonTracer captureOpStart", msg=ex.msg error "JsonTracer captureOpStart", msg=ex.msg
if op in callFamily:
try: try:
ctx.captureOpImpl(c, pc, op, 0, 0, [], depth, none(string)) ctx.captureOpImpl(c, pc, op, 0, 0, [], depth, none(string))
except RlpError as ex: except RlpError as ex:
error "JsonTracer captureOpEnd", msg=ex.msg error "JsonTracer captureOpStart", msg=ex.msg
# make sure captureOpEnd get the right opIndex # make sure captureOpEnd get the right opIndex
result = ctx.index result = ctx.index
inc ctx.index inc ctx.index
method callFamilyGas*(ctx: JsonTracer, comp: Computation, method captureGasCost*(ctx: JsonTracer, comp: Computation,
op: Op, gas: GasInt, fixed: bool, op: Op, gasCost: GasInt, gasRemaining: GasInt,
depth: int) {.gcsafe.} = depth: int) {.gcsafe.} =
doAssert(op in callFamily) doAssert(ctx.node.isNil.not)
doAssert(ctx.callFamilyNode.isNil.not) let res = ctx.node
let res = ctx.callFamilyNode res["gasCost"] = encodeHex(gasCost)
res["gasCost"] = encodeHexInt(gas)
ctx.writeJson(res)
method captureOpEnd*(ctx: JsonTracer, comp: Computation, pc: int, if gasCost <= gasRemaining and not fixed:
op: Op, gas: GasInt, refund: GasInt, ctx.writeJson(res)
ctx.node = nil
# else:
# OOG will be handled by captureFault
# opcode with fixed gasCost will be handled by captureOpEnd
method captureOpEnd*(ctx: JsonTracer, comp: Computation,
fixed: bool, pc: int, op: Op, gas: GasInt, refund: GasInt,
rData: openArray[byte], rData: openArray[byte],
depth: int, opIndex: int) {.gcsafe.} = depth: int, opIndex: int) {.gcsafe.} =
if fixed:
doAssert(ctx.node.isNil.not)
let res = ctx.node
res["refund"] = %(refund)
if op in callFamily: if TracerFlags.DisableReturnData notin ctx.flags:
# call family opcode is processed in captureOpStart res["returnData"] = %(rData)
ctx.writeJson(res)
ctx.node = nil
return
method captureFault*(ctx: JsonTracer, comp: Computation,
fixed: bool, pc: int, op: Op, gas: GasInt, refund: GasInt,
rData: openArray[byte],
depth: int, error: Option[string]) {.gcsafe.} =
if ctx.node.isNil.not:
let res = ctx.node
res["refund"] = %(refund)
if TracerFlags.DisableReturnData notin ctx.flags:
res["returnData"] = %(rData)
if error.isSome:
res["error"] = %(error.get)
ctx.writeJson(res)
ctx.node = nil
return return
try:
ctx.captureOpImpl(comp, pc, op, gas, refund, rData, depth, none(string))
except RlpError as ex:
error "JsonTracer captureOpEnd", msg=ex.msg
method captureFault*(ctx: JsonTracer, comp: Computation, pc: int,
op: Op, gas: GasInt, refund: GasInt,
rData: openArray[byte],
depth: int, error: Option[string]) {.gcsafe.} =
try: try:
ctx.captureOpImpl(comp, pc, op, gas, refund, rData, depth, error) ctx.captureOpImpl(comp, pc, op, gas, refund, rData, depth, error)
doAssert(ctx.node.isNil.not)
ctx.writeJson(ctx.node)
ctx.node = nil
except RlpError as ex: except RlpError as ex:
error "JsonTracer captureOpEnd", msg=ex.msg error "JsonTracer captureOpFault", msg=ex.msg
proc close*(ctx: JsonTracer) = proc close*(ctx: JsonTracer) =
ctx.stream.close() ctx.stream.close()

View File

@ -71,8 +71,8 @@ method capturePrepare*(ctx: LegacyTracer, comp: Computation, depth: int) {.gcsaf
ctx.storageKeys[depth] = initHashSet[UInt256]() ctx.storageKeys[depth] = initHashSet[UInt256]()
# Opcode level # Opcode level
method captureOpStart*(ctx: LegacyTracer, c: Computation, pc: int, method captureOpStart*(ctx: LegacyTracer, c: Computation,
op: Op, gas: GasInt, fixed: bool, pc: int, op: Op, gas: GasInt,
depth: int): int {.gcsafe.} = depth: int): int {.gcsafe.} =
try: try:
let let
@ -126,8 +126,8 @@ method captureOpStart*(ctx: LegacyTracer, c: Computation, pc: int,
except InsufficientStack as ex: except InsufficientStack as ex:
error "LegacyTracer captureOpEnd", msg=ex.msg error "LegacyTracer captureOpEnd", msg=ex.msg
method captureOpEnd*(ctx: LegacyTracer, c: Computation, pc: int, method captureOpEnd*(ctx: LegacyTracer, c: Computation,
op: Op, gas: GasInt, refund: GasInt, fixed: bool, pc: int, op: Op, gas: GasInt, refund: GasInt,
rData: openArray[byte], rData: openArray[byte],
depth: int, opIndex: int) {.gcsafe.} = depth: int, opIndex: int) {.gcsafe.} =
try: try:
@ -156,8 +156,8 @@ method captureOpEnd*(ctx: LegacyTracer, c: Computation, pc: int,
except RlpError as ex: except RlpError as ex:
error "LegacyTracer captureOpEnd", msg=ex.msg error "LegacyTracer captureOpEnd", msg=ex.msg
method captureFault*(ctx: LegacyTracer, comp: Computation, pc: int, method captureFault*(ctx: LegacyTracer, comp: Computation,
op: Op, gas: GasInt, refund: GasInt, fixed: bool, pc: int, op: Op, gas: GasInt, refund: GasInt,
rData: openArray[byte], rData: openArray[byte],
depth: int, error: Option[string]) {.gcsafe.} = depth: int, error: Option[string]) {.gcsafe.} =
try: try:

View File

@ -169,28 +169,28 @@ method captureExit*(ctx: TracerRef, comp: Computation, output: openArray[byte],
discard discard
# Opcode level # Opcode level
method captureOpStart*(ctx: TracerRef, comp: Computation, pc: int, method captureOpStart*(ctx: TracerRef, comp: Computation,
op: Op, gas: GasInt, fixed: bool, pc: int, op: Op, gas: GasInt,
depth: int): int {.base, gcsafe.} = depth: int): int {.base, gcsafe.} =
discard discard
method callFamilyGas*(ctx: TracerRef, comp: Computation, method captureGasCost*(ctx: TracerRef, comp: Computation,
op: Op, gas: GasInt, fixed: bool, op: Op, gasCost: GasInt,
depth: int) {.base, gcsafe.} = gasRemaining: GasInt, depth: int) {.base, gcsafe.} =
discard discard
method captureOpEnd*(ctx: TracerRef, comp: Computation, pc: int, method captureOpEnd*(ctx: TracerRef, comp: Computation,
op: Op, gas: GasInt, refund: GasInt, fixed: bool, pc: int, op: Op, gas: GasInt, refund: GasInt,
rData: openArray[byte], rData: openArray[byte],
depth: int, opIndex: int) {.base, gcsafe.} = depth: int, opIndex: int) {.base, gcsafe.} =
discard discard
method captureFault*(ctx: TracerRef, comp: Computation, pc: int, method captureFault*(ctx: TracerRef, comp: Computation,
op: Op, gas: GasInt, refund: GasInt, fixed: bool, pc: int, op: Op, gas: GasInt, refund: GasInt,
rData: openArray[byte], rData: openArray[byte],
depth: int, error: Option[string]) {.base, gcsafe.} = depth: int, error: Option[string]) {.base, gcsafe.} =
discard discard
# Called at the start of EVM interpreter loop
method capturePrepare*(ctx: TracerRef, comp: Computation, depth: int) {.base, gcsafe.} = method capturePrepare*(ctx: TracerRef, comp: Computation, depth: int) {.base, gcsafe.} =
discard discard

View File

@ -43,7 +43,7 @@ export
vms.captureEnter, vms.captureEnter,
vms.captureExit, vms.captureExit,
vms.captureOpStart, vms.captureOpStart,
vms.callFamilyGas, vms.captureGasCost,
vms.captureOpEnd, vms.captureOpEnd,
vms.captureFault, vms.captureFault,
vms.capturePrepare vms.capturePrepare

View File

@ -515,6 +515,15 @@ const
output: T8nOutput(trace: true, result: true), output: T8nOutput(trace: true, result: true),
expOut: "exp.txt", expOut: "exp.txt",
), ),
TestSpec(
name : "EVM tracer CALL family exception",
base : "testdata/00-521",
input : t8nInput(
"alloc.json", "txs.json", "env.json", "Shanghai", "0",
),
output: T8nOutput(trace: true, result: true),
expOut: "exp.txt",
),
] ]
proc main() = proc main() =

68
tools/t8n/testdata/00-521/alloc.json vendored Normal file
View File

@ -0,0 +1,68 @@
{
"0x00000000000000000000000000000000000000f1": {
"balance": "0x0",
"code": "0x600060006000600060fa5af4507f60095450600354506000600055600654507f60faff61507a6c957f60075450606000527fa06000536083600153600060025360f360036000527f536032600453600560606020527e527f055360606006536002600753606060085360006020527f6009536055606040527f0a536060600b536020527f6001600c536054600d536050600e536040527f60606060527f600f5360206010536060601153600060405260606060536012606153605360606080527f527f606253606060635360f3606453606060655360136066536053606753606060a0527f60686080527f5360146069536060606a536000606b5360f3606c536000606d6060c0527e6000f5600060a0527f6000600060006000855af15050823d76b158605c326060e0527e60006000600060006060c0527f095af250337583987e9360f4ff6000600060610100527e6000600060055af2509843046560e0527f468456603e5f3084576004545060610120527e600060006000600060f75af25091636563610100527f936a83180260006000610140527f60006000600060f85af2507e6001545060035450600060610120526000610140610160527f5360606101415360006101425360606101435360006101445360606101455360610180527f0561014653605a6101475360f461014853605061014953606061014a536000616101a0527f014b53606061014c53600461014d53605561014e53608d61014f53607d6101506101c0527f53605961015153607d61015253600961015353608f61015453606061015553606101e0527f0261015653606061015753600161015853605561015953606061015a5360206161020052600161022053605b61022153605361022253606061022353606061022453606161022553600161022653605c61022753605361022853606061022953600061022a53606161022b53600161022c53605d61022d53605361022e53606061022f5360fd61023053606161023153600161023253605e61023353605361023453606161023553600161023653605f6102375360606102385360006102395360f361023a53600061023b60006000f560006000600060006000855af25050",
"nonce": "0x0",
"storage": {}
},
"0x00000000000000000000000000000000000000f2": {
"balance": "0x0",
"code": "0x60045450600060006000600060f55af450600060025560f9ff068c6a914360016003551cfe5a8a5e68fe50201d4265600bff60206000fd",
"nonce": "0x0",
"storage": {}
},
"0x00000000000000000000000000000000000000f3": {
"balance": "0x0",
"code": "0x6001600255cf7f60005450600954506007545060065450600354507f6000600060006000600a5a6000527ff450600eff7f6000600355600354506002545060086000527f54507f7f6006546020527f507ff988b145087f887a6000527f34393a977050649aa3f47f6020527f6002606040527f015560066000527f546000527f50600554506020527f6000527f6004546040526060527f7f5060016003556001600255600060046020527f556000527f606040527f20526080527f7f6060527f6001600155600754506020527f600160045560026002556040527f60a0527f60016060526080527f7f600055600060006040527f556007546020527f50600360c0527f54506040527f60606060a0527f606080527f527f60005360026001536054600260e0527f536060527f605060035360506060c0527f045360616060a0527f40526080527f610100527f7f606060527f05536041600653605b600760e0527f6080527f53609f600860c0610120527f527f5360d760095360a0527f6060600a536000600b610100527f606080527f60610140527f527f536060606060e0527fa0527f0c536004600d5360c0527f60610120527f55610160527f600e536060600f536020601053606060610100527f60a0527f11536060c05261610180527f0140527f7f60805260e0527f600060a053606060a153601260a2610120527f536101a0527f605360a3610160527f53606060a4536060c05260e052610100527f7f7ffd60a56101c0527f53606060610140527f610180527fa653601360a753605360a853606060a953606101e0527f1460aa5360610120527f606101006101a0527f610160527f527f6060e0527fab610200527f53600060ac5360f360ad53600060ae600060006101c0527ff561014052610180610220527f527f7f600060006000610120527f6000600085610100527f6101e0527f5af150610240527f50507f918b6b6a6101a0527fa1610160527fa1760652600aff50103f45610200610260527f527f610140527ff1845e601917087f45796101c0527f61012052600b61018052610280527f7f61610220527f014053603761014153601461014253610160527f6101e0527f6102a0527f60136101435360610240527f5a6101446101a0527f53606061014553602061016102c0527f4653606061610200527f0147610260527f5360006101805260616101a05360616102e0527f01c0527f016101a15360486101a2536102610280527f20527f60536101a35360610300527f606101a45360f36101a5536061616101e0527f01a6536102a0527f6001616102610320527f40527f01a75360496101a85360536101a95360616101aa536001616102c0527f610340527f01ab610200527f53610260527f604a6101ac5360606101ad5360006101ae5360610360527f6102e0527ff36101af5360006101b0600061610280527f022052606061024053610380527f6000610241610300527f5360f56102425360606102435360006102446102a0526103a0527f7f536060610245536000610320527f61024653606061024753600061024853606103c0527f6061024953606102c0527e61024a53610340527f606061024b53600061024c536103e0527f608561024d53605a61024e5360f2616102e05260610360527f0261030053604f610400527f61030153605361030253606061030353605061030453606161610380527f0305610420527f53600261030653605061030753605361030853606061030953605061030a6103610440527fa0527f53606161030b53600261030c53605161030d53605361030e5360616103610460527f0f53606103c0527f026103105360526103115360606103125360006103135360610480527ff3610314536103156103e05260606104005360006104015360606104025360006104a0527f6104035360f061040453606061040553600061040653606061040753600061046104c0527f0853606061040953600061040a53606061040b53600061040c53606061040d536104e0527f600061040e53608561040f53605a6104105360f26104115360506104125360506105005260616105205360046105215360136105225360536105235360616105245360046105255360146105265360606105275360006105285360f36105295361052a60006000f06000600060006000845af45050",
"nonce": "0x0",
"storage": {}
},
"0x00000000000000000000000000000000000000f4": {
"balance": "0x0",
"code": "0x7f600260045560005450600054506052600053605960015360b0600253604860036000527f53606060045360006005536060600653600060075360606008536000600953606020527f60600a536000600b536060600c536000600d536060600e5360f7600f53605a606040527f105360f260115360506012536060601353602060145360606015536000601653606052606060805360f3608153606060825360176083536053608453606060855360186086536060608753600060885360f3608953608a60006000f060006000600060006000855af15050600060006000600060085af4509e6c9d1d971b000660f7ff600454506000600060006000600060025af2509c475968419b3aa08593a2600160015573723c5c93313020435e90136c69a060006000600060006000600b5af25082a34587374694600254502818e1600354506002ff60f6ff60025450600060006000600060085af45060006002555938175a79c36006ff60206000f3",
"nonce": "0x0",
"storage": {}
},
"0x00000000000000000000000000000000000000f5": {
"balance": "0x0",
"code": "0xf570b11897ff9b1da093177f645c31168c93a46000600455cd600060045560206000f3",
"nonce": "0x0",
"storage": {}
},
"0x00000000000000000000000000000000000000f6": {
"balance": "0x0",
"code": "0x60206000fd",
"nonce": "0x0",
"storage": {}
},
"0x00000000000000000000000000000000000000f7": {
"balance": "0x0",
"code": "0x7f6002545060006000556002600355600654506000600155600854507f60faff9b6000527f023f5bfa904270645484563c3af0748b956c546afdfa825b888a60066000527f6020527fff236000600060006000600060f25af2506000600060006000600060f95af2506040527f6020527f60025450676003545060006000600060006000600a5af1509c0238456060527fa1375d086040527f6a0173ff687402743080530196697c6000600060006000606080527ff75af450507965fe6060527f0360006000600060006000600d5af2507f60006060a0527e55600060025560035450606080527e6004556060600053602060015360606060c0527f60005260026020536053602153606060a0527f6022536000602353606060245360e0527f60036025536053602653606060275360f3602860c0527f536060602953600460610100527f2a536053602b536060602c536005602d536060602e536060e0527e602f5360f3610120527f6030536000603160006000f56000600060006000845af450501561010052609f610140527f6101205360876101215360646101225360536101235360606101245360006101610160527f2553606061012653600061012753606061012853600061012953606061012a53610180527f600061012b53606061012c53600061012d53606061012e5360f761012f53605a6101a0527f6101305360f161013153605061013253606061013353602061013453606061016101c05260356101e05360536101e15360606101e25360006101e35360616101e45360016101e55360366101e65360536101e75360606101e85360f36101e95360616101ea5360016101eb5360376101ec5360536101ed5360616101ee5360016101ef5360386101f05360606101f15360006101f25360f36101f3536101f460006000f06000600060006000845af45050",
"nonce": "0x0",
"storage": {}
},
"0x00000000000000000000000000000000000000f8": {
"balance": "0x0",
"code": "0x600060006000600060065af4506000600060006000600060f65af1507f600054507f663a148bfd0ba3396000600060006000600060f25af250600060006000527f60006000606000527e600c5af250600454507f7f9c757985621d9779001466466020527f78183760006002556020527faf60006003550047149a046000527ff06000527f6040527f080864543efe3f3f445803356040527f600354505a8e45a4b071383862fa19606060527f20527f9c5b7c52076020527f600160036060527f55b27f6007545060006004556080527f600260025560016040527f6002556007545060026080527f6040527f5450600160a0527f6002556000527f60065450600160016060527f556000545060a0527f6008545060c0527f600654506060527f60016004556007545060046020527f6080527f5460c0527f60e0527f506060600053600060015360606002536080527f600060035360606004536060610100527f60e0527fa0527e6005536040527f6060600653600060075360606060a0527f08610120527f53600060610100527f095360c0527f6060600a536006600b53605a6060527f60610140527f0c5360f2600d536060610120527fc0527f50600e60e0527f536060600f536020610160527f6010536060601153600060126080610140527f52605360a0536060e052610100610180527f527f7f6060a15360f360a253606060a3536013610160527f60a453605360a5536101a0527f606060a6536014610120527f60610100527fa753606060a8610180527f5360006101c0527f60a95360f360aa53600060ab60006000f5610140527f600060006000616101a06101e0527f527f0120527f6000845af450509e20915e89f0684660026000559a610160527f610200527f60006101c0527f600060006000600060610140527f0d5af15060016002556009610220527fff3f8c329761016101e0527f80527f7f60006002556000545060095450600161610240527f0160527f6003556000600055610200527f6000606101a0527f02556000545060610260527e527f600260035560026003557f610180610220527f527f6000600060006101610280527fc0527f6000600060035af25060005450600d60205260610240527fff604053606102a0527f60606101a0527f416101e0527f5360016042536060604353600260610260527f6102c0527f445360556045536060604653602060475361610200527f01c0527f60606048536102e0527f610280527f600060495360f3604a536060604b536000604c5360526061022052610300527f7f4d5360606102a0527f6101e0527f604e536020604f53606060505360006051610320527f5360f3605253610240526102c0527f7f605360006000f0600061020052606061610340527f0220536000610221536060610222536102e0527f60610260527e610223536060610360527f6102245360006102255360606102265360006102610300527f27536085616102610380527f80527f022853605a6102295360f161022a53605061022b5360610320527f50616103a0527f022c5361022d60006102a05260f36102c0536102c160006000f06000600061036103c0527f40526060610360536000610361536060610362536000610363536084610364536103e052606061040053605a6104015360616104025360036104035360656104045360536104055360606104065360f461040753606161040853600361040953606661040a53605361040b53606061040c53605061040d53606161040e53600361040f53606761041053605361041153606061041253605061041353606161041453600361041553606861041653605361041753606161041853600361041953606961041a53606061041b53600061041c5360f361041d5361041e60006000f060006000600060006000855af15050",
"nonce": "0x0",
"storage": {}
},
"0x00000000000000000000000000000000000000f9": {
"balance": "0x0",
"code": "0x9f9d404467600060006000600060f65af450533a9e7060006000600060006000600e5af150f5032095fd177d99306000600060006000600060005af1506000600060006000600d5af450916858b03c60006000600060006000600e5af25060206000f3",
"nonce": "0x0",
"storage": {}
},
"0x00000000000000000000000000000000000000fa": {
"balance": "0x0",
"code": "0x6000600060006000600060fa5af15060206000fd",
"nonce": "0x0",
"storage": {}
},
"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
"balance": "0xffffffffff",
"code": "0x",
"nonce": "0x0",
"storage": {}
}
}

10
tools/t8n/testdata/00-521/env.json vendored Normal file
View File

@ -0,0 +1,10 @@
{
"currentBaseFee": "0x10",
"currentCoinbase": "b94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"currentDifficulty": "0x0",
"currentGasLimit": "0x26e1f476fe1e22",
"currentNumber": "0x1",
"currentRandom": "0x0000000000000000000000000000000000000000000000000000000000020000",
"currentTimestamp": "0x3e8",
"withdrawals": [],
}

17
tools/t8n/testdata/00-521/exp.txt vendored Normal file
View File

@ -0,0 +1,17 @@
{"pc":0,"op":96,"gas":"0xa54","gasCost":"0x3","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"PUSH1"}
{"pc":2,"op":96,"gas":"0xa51","gasCost":"0x3","memSize":0,"stack":["0x0"],"depth":1,"refund":0,"opName":"PUSH1"}
{"pc":4,"op":96,"gas":"0xa4e","gasCost":"0x3","memSize":0,"stack":["0x0","0x0"],"depth":1,"refund":0,"opName":"PUSH1"}
{"pc":6,"op":96,"gas":"0xa4b","gasCost":"0x3","memSize":0,"stack":["0x0","0x0","0x0"],"depth":1,"refund":0,"opName":"PUSH1"}
{"pc":8,"op":96,"gas":"0xa48","gasCost":"0x3","memSize":0,"stack":["0x0","0x0","0x0","0x0"],"depth":1,"refund":0,"opName":"PUSH1"}
{"pc":10,"op":90,"gas":"0xa45","gasCost":"0x2","memSize":0,"stack":["0x0","0x0","0x0","0x0","0xfa"],"depth":1,"refund":0,"opName":"GAS"}
{"pc":11,"op":244,"gas":"0xa43","gasCost":"0xa43","memSize":0,"stack":["0x0","0x0","0x0","0x0","0xfa","0xa43"],"depth":1,"refund":0,"opName":"DELEGATECALL"}
{"pc":0,"op":96,"gas":"0x1b","gasCost":"0x3","memSize":0,"stack":[],"depth":2,"refund":0,"opName":"PUSH1"}
{"pc":2,"op":96,"gas":"0x18","gasCost":"0x3","memSize":0,"stack":["0x0"],"depth":2,"refund":0,"opName":"PUSH1"}
{"pc":4,"op":96,"gas":"0x15","gasCost":"0x3","memSize":0,"stack":["0x0","0x0"],"depth":2,"refund":0,"opName":"PUSH1"}
{"pc":6,"op":96,"gas":"0x12","gasCost":"0x3","memSize":0,"stack":["0x0","0x0","0x0"],"depth":2,"refund":0,"opName":"PUSH1"}
{"pc":8,"op":96,"gas":"0xf","gasCost":"0x3","memSize":0,"stack":["0x0","0x0","0x0","0x0"],"depth":2,"refund":0,"opName":"PUSH1"}
{"pc":10,"op":96,"gas":"0xc","gasCost":"0x3","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x0"],"depth":2,"refund":0,"opName":"PUSH1"}
{"pc":12,"op":90,"gas":"0x9","gasCost":"0x2","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x0","0xfa"],"depth":2,"refund":0,"opName":"GAS"}
{"pc":13,"op":241,"gas":"0x7","gasCost":"0x9","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x0","0xfa","0x7"],"depth":2,"refund":0,"opName":"CALL","error":"Opcode Dispatch Error: Out of gas: Needed 9 - Remaining 7 - Reason: Call, depth=2"}
{"pc":12,"op":80,"gas":"0x0","gasCost":"0x2","memSize":0,"stack":["0x0"],"depth":1,"refund":0,"opName":"POP","error":"Opcode Dispatch Error: Out of gas: Needed 2 - Remaining 0 - Reason: Pop, depth=1"}
{"output":"","gasUsed":"0xa54","error":"Opcode Dispatch Error: Out of gas: Needed 2 - Remaining 0 - Reason: Pop, depth=1"}

14
tools/t8n/testdata/00-521/txs.json vendored Normal file
View File

@ -0,0 +1,14 @@
[
{
"type": "0x0",
"chainId": "0x1",
"input": "0x4235beb96136f67f5076ae8700b86ef876b2b95037c04c311ea03790a15b97389485f03361",
"gas": "0x5ea0",
"gasPrice": "0x10",
"nonce": "0x0",
"secretKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"to": "0x00000000000000000000000000000000000000f1",
"value": "0x1a5474"
}
]