Add current computation to each EVM tracer interface (#1712)
This commit is contained in:
parent
7aead6151e
commit
91704cd3ae
|
@ -107,9 +107,11 @@ proc asyncProcessTransactionImpl(
|
|||
vmState.stateDB.clearTransientStorage()
|
||||
|
||||
# Execute the transaction.
|
||||
vmState.captureTxStart(tx.gasLimit)
|
||||
let
|
||||
accTx = vmState.stateDB.beginSavepoint
|
||||
gasBurned = tx.txCallEvm(sender, vmState, fork)
|
||||
vmState.captureTxEnd(tx.gasLimit - gasBurned)
|
||||
|
||||
res = commitOrRollbackDependingOnGasUsed(vmState, accTx, header, tx, gasBurned, priorityFee)
|
||||
else:
|
||||
|
|
|
@ -390,16 +390,18 @@ proc tracingEnabled*(c: Computation): bool =
|
|||
|
||||
proc traceOpCodeStarted*(c: Computation, op: Op): int {.gcsafe, raises: [].} =
|
||||
c.vmState.captureOpStart(
|
||||
c,
|
||||
c.code.pc - 1,
|
||||
op,
|
||||
c.gasMeter.gasRemaining,
|
||||
c.msg.depth + 1)
|
||||
|
||||
proc traceCallFamilyGas*(c: Computation, op: Op, gas: GasInt) {.gcsafe, raises: [].} =
|
||||
c.vmState.callFamilyGas(op, gas, c.msg.depth + 1)
|
||||
c.vmState.callFamilyGas(c, op, gas, c.msg.depth + 1)
|
||||
|
||||
proc traceOpCodeEnded*(c: Computation, op: Op, opIndex: int) {.gcsafe, raises: [].} =
|
||||
c.vmState.captureOpEnd(
|
||||
c,
|
||||
c.code.pc - 1,
|
||||
op,
|
||||
c.gasMeter.gasRemaining,
|
||||
|
@ -410,6 +412,7 @@ proc traceOpCodeEnded*(c: Computation, op: Op, opIndex: int) {.gcsafe, raises: [
|
|||
|
||||
proc traceError*(c: Computation) {.gcsafe, raises: [].} =
|
||||
c.vmState.captureFault(
|
||||
c,
|
||||
c.code.pc - 1,
|
||||
c.instr,
|
||||
c.gasMeter.gasRemaining,
|
||||
|
@ -419,7 +422,7 @@ proc traceError*(c: Computation) {.gcsafe, raises: [].} =
|
|||
some(c.error.info))
|
||||
|
||||
proc prepareTracer*(c: Computation) =
|
||||
c.vmState.capturePrepare(c.msg.depth)
|
||||
c.vmState.capturePrepare(c, c.msg.depth)
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# End
|
||||
|
|
|
@ -190,7 +190,8 @@ proc beforeExec(c: Computation): bool
|
|||
{.gcsafe, raises: [ValueError].} =
|
||||
|
||||
if c.msg.depth > 0:
|
||||
c.vmState.captureEnter(msgToOp(c.msg),
|
||||
c.vmState.captureEnter(c,
|
||||
msgToOp(c.msg),
|
||||
c.msg.sender, c.msg.contractAddress,
|
||||
c.msg.data, c.msg.gas,
|
||||
c.msg.value)
|
||||
|
@ -215,7 +216,7 @@ proc afterExec(c: Computation)
|
|||
some(c.error.info)
|
||||
else:
|
||||
none(string)
|
||||
c.vmState.captureExit(c.output, gasUsed, error)
|
||||
c.vmState.captureExit(c, c.output, gasUsed, error)
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Public functions
|
||||
|
|
|
@ -363,56 +363,57 @@ proc captureTxEnd*(vmState: BaseVMState, restGas: GasInt) =
|
|||
if vmState.tracingEnabled:
|
||||
vmState.tracer.captureTxEnd(restGas)
|
||||
|
||||
proc captureStart*(vmState: BaseVMState, c: Computation,
|
||||
proc captureStart*(vmState: BaseVMState, comp: Computation,
|
||||
sender: EthAddress, to: EthAddress,
|
||||
create: bool, input: openArray[byte],
|
||||
gas: GasInt, value: UInt256) =
|
||||
gasLimit: GasInt, value: UInt256) =
|
||||
if vmState.tracingEnabled:
|
||||
vmState.tracer.captureStart(c, sender, to, create, input, gas, value)
|
||||
vmState.tracer.captureStart(comp, sender, to, create, input, gasLimit, value)
|
||||
|
||||
proc captureEnd*(vmState: BaseVMState, output: openArray[byte],
|
||||
proc captureEnd*(vmState: BaseVMState, comp: Computation, output: openArray[byte],
|
||||
gasUsed: GasInt, error: Option[string]) =
|
||||
if vmState.tracingEnabled:
|
||||
vmState.tracer.captureEnd(output, gasUsed, error)
|
||||
vmState.tracer.captureEnd(comp, output, gasUsed, error)
|
||||
|
||||
proc captureEnter*(vmState: BaseVMState, op: Op,
|
||||
proc captureEnter*(vmState: BaseVMState, comp: Computation, op: Op,
|
||||
sender: EthAddress, to: EthAddress,
|
||||
input: openArray[byte], gas: GasInt,
|
||||
input: openArray[byte], gasLimit: GasInt,
|
||||
value: UInt256) =
|
||||
if vmState.tracingEnabled:
|
||||
vmState.tracer.captureEnter(op, sender, to, input, gas, value)
|
||||
vmState.tracer.captureEnter(comp, op, sender, to, input, gasLimit, value)
|
||||
|
||||
proc captureExit*(vmState: BaseVMState, output: openArray[byte],
|
||||
proc captureExit*(vmState: BaseVMState, comp: Computation, output: openArray[byte],
|
||||
gasUsed: GasInt, error: Option[string]) =
|
||||
if vmState.tracingEnabled:
|
||||
vmState.tracer.captureExit(output, gasUsed, error)
|
||||
vmState.tracer.captureExit(comp, output, gasUsed, error)
|
||||
|
||||
proc captureOpStart*(vmState: BaseVMState, pc: int,
|
||||
proc captureOpStart*(vmState: BaseVMState, comp: Computation, pc: int,
|
||||
op: Op, gas: GasInt,
|
||||
depth: int): int =
|
||||
if vmState.tracingEnabled:
|
||||
result = vmState.tracer.captureOpStart(pc, op, gas, depth)
|
||||
result = vmState.tracer.captureOpStart(comp, pc, op, gas, depth)
|
||||
|
||||
proc callFamilyGas*(vmState: BaseVMState,
|
||||
comp: Computation,
|
||||
op: Op, gas: GasInt,
|
||||
depth: int) =
|
||||
if vmState.tracingEnabled:
|
||||
vmState.tracer.callFamilyGas(op, gas, depth)
|
||||
vmState.tracer.callFamilyGas(comp, op, gas, depth)
|
||||
|
||||
proc captureOpEnd*(vmState: BaseVMState, pc: int,
|
||||
proc captureOpEnd*(vmState: BaseVMState, comp: Computation, pc: int,
|
||||
op: Op, gas: GasInt, refund: GasInt,
|
||||
rData: openArray[byte],
|
||||
depth: int, opIndex: int) =
|
||||
if vmState.tracingEnabled:
|
||||
vmState.tracer.captureOpEnd(pc, op, gas, refund, rData, depth, opIndex)
|
||||
vmState.tracer.captureOpEnd(comp, pc, op, gas, refund, rData, depth, opIndex)
|
||||
|
||||
proc captureFault*(vmState: BaseVMState, pc: int,
|
||||
proc captureFault*(vmState: BaseVMState, comp: Computation, pc: int,
|
||||
op: Op, gas: GasInt, refund: GasInt,
|
||||
rData: openArray[byte],
|
||||
depth: int, error: Option[string]) =
|
||||
if vmState.tracingEnabled:
|
||||
vmState.tracer.captureFault(pc, op, gas, refund, rData, depth, error)
|
||||
vmState.tracer.captureFault(comp, pc, op, gas, refund, rData, depth, error)
|
||||
|
||||
proc capturePrepare*(vmState: BaseVMState, depth: int) =
|
||||
proc capturePrepare*(vmState: BaseVMState, comp: Computation, depth: int) =
|
||||
if vmState.tracingEnabled:
|
||||
vmState.tracer.capturePrepare(depth)
|
||||
vmState.tracer.capturePrepare(comp, depth)
|
||||
|
|
|
@ -23,7 +23,6 @@ type
|
|||
JsonTracer* = ref object of TracerRef
|
||||
stream: Stream
|
||||
pretty: bool
|
||||
comp: Computation
|
||||
gas: GasInt
|
||||
pc: int
|
||||
stack: JsonNode
|
||||
|
@ -76,13 +75,12 @@ iterator storage(ctx: JsonTracer, compDepth: int): UInt256 =
|
|||
for key in ctx.storageKeys[compDepth]:
|
||||
yield key
|
||||
|
||||
proc captureOpImpl(ctx: JsonTracer, pc: int,
|
||||
proc captureOpImpl(ctx: JsonTracer, c: Computation, pc: int,
|
||||
op: Op, gas: GasInt, refund: GasInt,
|
||||
rData: openArray[byte],
|
||||
depth: int, error: Option[string]) {.gcsafe.} =
|
||||
let
|
||||
gasCost = ctx.gas - gas
|
||||
c = ctx.comp
|
||||
|
||||
var res = %{
|
||||
"pc": %(ctx.pc),
|
||||
|
@ -139,7 +137,7 @@ proc newJsonTracer*(stream: Stream, flags: set[TracerFlags], pretty: bool): Json
|
|||
pretty: pretty
|
||||
)
|
||||
|
||||
method capturePrepare*(ctx: JsonTracer, depth: int) {.gcsafe.} =
|
||||
method capturePrepare*(ctx: JsonTracer, comp: Computation, depth: int) {.gcsafe.} =
|
||||
if depth >= ctx.storageKeys.len:
|
||||
let prevLen = ctx.storageKeys.len
|
||||
ctx.storageKeys.setLen(depth + 1)
|
||||
|
@ -149,13 +147,13 @@ method capturePrepare*(ctx: JsonTracer, depth: int) {.gcsafe.} =
|
|||
ctx.storageKeys[depth] = initHashSet[UInt256]()
|
||||
|
||||
# Top call frame
|
||||
method captureStart*(ctx: JsonTracer, c: Computation,
|
||||
method captureStart*(ctx: JsonTracer, comp: Computation,
|
||||
sender: EthAddress, to: EthAddress,
|
||||
create: bool, input: openArray[byte],
|
||||
gas: GasInt, value: UInt256) {.gcsafe.} =
|
||||
ctx.comp = c
|
||||
gasLimit: GasInt, value: UInt256) {.gcsafe.} =
|
||||
discard
|
||||
|
||||
method captureEnd*(ctx: JsonTracer, output: openArray[byte],
|
||||
method captureEnd*(ctx: JsonTracer, comp: Computation, output: openArray[byte],
|
||||
gasUsed: GasInt, error: Option[string]) {.gcsafe.} =
|
||||
var res = %{
|
||||
"output": %(output),
|
||||
|
@ -166,21 +164,19 @@ method captureEnd*(ctx: JsonTracer, output: openArray[byte],
|
|||
ctx.writeJson(res)
|
||||
|
||||
# Opcode level
|
||||
method captureOpStart*(ctx: JsonTracer, pc: int,
|
||||
method captureOpStart*(ctx: JsonTracer, c: Computation, pc: int,
|
||||
op: Op, gas: GasInt,
|
||||
depth: int): int {.gcsafe.} =
|
||||
ctx.gas = gas
|
||||
ctx.pc = pc
|
||||
|
||||
if TracerFlags.DisableStack notin ctx.flags:
|
||||
let c = ctx.comp
|
||||
ctx.stack = newJArray()
|
||||
for v in c.stack.values:
|
||||
ctx.stack.add(%("0x" & v.dumpHex.stripLeadingZeros))
|
||||
|
||||
if TracerFlags.DisableStorage notin ctx.flags and op == SSTORE:
|
||||
try:
|
||||
let c = ctx.comp
|
||||
if c.stack.values.len > 1:
|
||||
ctx.rememberStorageKey(c.msg.depth, c.stack[^1, UInt256])
|
||||
except InsufficientStack as ex:
|
||||
|
@ -190,7 +186,7 @@ method captureOpStart*(ctx: JsonTracer, pc: int,
|
|||
|
||||
if op in callFamily:
|
||||
try:
|
||||
ctx.captureOpImpl(pc, op, 0, 0, [], depth, none(string))
|
||||
ctx.captureOpImpl(c, pc, op, 0, 0, [], depth, none(string))
|
||||
except RlpError as ex:
|
||||
error "JsonTracer captureOpEnd", msg=ex.msg
|
||||
|
||||
|
@ -198,7 +194,7 @@ method captureOpStart*(ctx: JsonTracer, pc: int,
|
|||
result = ctx.index
|
||||
inc ctx.index
|
||||
|
||||
method callFamilyGas*(ctx: JsonTracer,
|
||||
method callFamilyGas*(ctx: JsonTracer, comp: Computation,
|
||||
op: Op, gas: GasInt,
|
||||
depth: int) {.gcsafe.} =
|
||||
doAssert(op in callFamily)
|
||||
|
@ -207,7 +203,7 @@ method callFamilyGas*(ctx: JsonTracer,
|
|||
res["gasCost"] = encodeHexInt(gas)
|
||||
ctx.writeJson(res)
|
||||
|
||||
method captureOpEnd*(ctx: JsonTracer, pc: int,
|
||||
method captureOpEnd*(ctx: JsonTracer, comp: Computation, pc: int,
|
||||
op: Op, gas: GasInt, refund: GasInt,
|
||||
rData: openArray[byte],
|
||||
depth: int, opIndex: int) {.gcsafe.} =
|
||||
|
@ -217,16 +213,16 @@ method captureOpEnd*(ctx: JsonTracer, pc: int,
|
|||
return
|
||||
|
||||
try:
|
||||
ctx.captureOpImpl(pc, op, gas, refund, rData, depth, none(string))
|
||||
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, pc: int,
|
||||
method captureFault*(ctx: JsonTracer, comp: Computation, pc: int,
|
||||
op: Op, gas: GasInt, refund: GasInt,
|
||||
rData: openArray[byte],
|
||||
depth: int, error: Option[string]) {.gcsafe.} =
|
||||
try:
|
||||
ctx.captureOpImpl(pc, op, gas, refund, rData, depth, error)
|
||||
ctx.captureOpImpl(comp, pc, op, gas, refund, rData, depth, error)
|
||||
except RlpError as ex:
|
||||
error "JsonTracer captureOpEnd", msg=ex.msg
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@ type
|
|||
trace: JsonNode
|
||||
accounts: HashSet[EthAddress]
|
||||
storageKeys: seq[HashSet[UInt256]]
|
||||
comp: Computation
|
||||
gas: GasInt
|
||||
|
||||
proc hash*(x: UInt256): Hash =
|
||||
|
@ -62,7 +61,7 @@ proc newLegacyTracer*(flags: set[TracerFlags]): LegacyTracer =
|
|||
trace: trace
|
||||
)
|
||||
|
||||
method capturePrepare*(ctx: LegacyTracer, depth: int) {.gcsafe.} =
|
||||
method capturePrepare*(ctx: LegacyTracer, comp: Computation, depth: int) {.gcsafe.} =
|
||||
if depth >= ctx.storageKeys.len:
|
||||
let prevLen = ctx.storageKeys.len
|
||||
ctx.storageKeys.setLen(depth + 1)
|
||||
|
@ -71,25 +70,13 @@ method capturePrepare*(ctx: LegacyTracer, depth: int) {.gcsafe.} =
|
|||
|
||||
ctx.storageKeys[depth] = initHashSet[UInt256]()
|
||||
|
||||
# Top call frame
|
||||
method captureStart*(ctx: LegacyTracer, c: Computation,
|
||||
sender: EthAddress, to: EthAddress,
|
||||
create: bool, input: openArray[byte],
|
||||
gas: GasInt, value: UInt256) {.gcsafe.} =
|
||||
ctx.comp = c
|
||||
|
||||
method captureEnd*(ctx: LegacyTracer, output: openArray[byte],
|
||||
gasUsed: GasInt, error: Option[string]) {.gcsafe.} =
|
||||
discard
|
||||
|
||||
# Opcode level
|
||||
method captureOpStart*(ctx: LegacyTracer, pc: int,
|
||||
method captureOpStart*(ctx: LegacyTracer, c: Computation, pc: int,
|
||||
op: Op, gas: GasInt,
|
||||
depth: int): int {.gcsafe.} =
|
||||
try:
|
||||
let
|
||||
j = newJObject()
|
||||
c = ctx.comp
|
||||
ctx.trace["structLogs"].add(j)
|
||||
|
||||
j["op"] = %(($op).toUpperAscii)
|
||||
|
@ -139,14 +126,13 @@ method captureOpStart*(ctx: LegacyTracer, pc: int,
|
|||
except InsufficientStack as ex:
|
||||
error "LegacyTracer captureOpEnd", msg=ex.msg
|
||||
|
||||
method captureOpEnd*(ctx: LegacyTracer, pc: int,
|
||||
method captureOpEnd*(ctx: LegacyTracer, c: Computation, pc: int,
|
||||
op: Op, gas: GasInt, refund: GasInt,
|
||||
rData: openArray[byte],
|
||||
depth: int, opIndex: int) {.gcsafe.} =
|
||||
try:
|
||||
let
|
||||
j = ctx.trace["structLogs"].elems[opIndex]
|
||||
c = ctx.comp
|
||||
|
||||
# TODO: figure out how to get storage
|
||||
# when contract execution interrupted by exception
|
||||
|
@ -170,15 +156,14 @@ method captureOpEnd*(ctx: LegacyTracer, pc: int,
|
|||
except RlpError as ex:
|
||||
error "LegacyTracer captureOpEnd", msg=ex.msg
|
||||
|
||||
method captureFault*(ctx: LegacyTracer, pc: int,
|
||||
method captureFault*(ctx: LegacyTracer, comp: Computation, pc: int,
|
||||
op: Op, gas: GasInt, refund: GasInt,
|
||||
rData: openArray[byte],
|
||||
depth: int, error: Option[string]) {.gcsafe.} =
|
||||
try:
|
||||
let c = ctx.comp
|
||||
if ctx.trace["structLogs"].elems.len > 0:
|
||||
let j = ctx.trace["structLogs"].elems[^1]
|
||||
j["error"] = %(c.error.info)
|
||||
j["error"] = %(comp.error.info)
|
||||
j["gasCost"] = %(ctx.gas - gas)
|
||||
|
||||
ctx.trace["failed"] = %true
|
||||
|
|
|
@ -139,6 +139,7 @@ type
|
|||
flags*: set[TracerFlags]
|
||||
|
||||
# Transaction level
|
||||
# This is called once fo each transaction
|
||||
method captureTxStart*(ctx: TracerRef, gasLimit: GasInt) {.base, gcsafe.} =
|
||||
discard
|
||||
|
||||
|
@ -146,50 +147,50 @@ method captureTxEnd*(ctx: TracerRef, restGas: GasInt) {.base, gcsafe.} =
|
|||
discard
|
||||
|
||||
# Top call frame
|
||||
method captureStart*(ctx: TracerRef, c: Computation,
|
||||
method captureStart*(ctx: TracerRef, comp: Computation,
|
||||
sender: EthAddress, to: EthAddress,
|
||||
create: bool, input: openArray[byte],
|
||||
gas: GasInt, value: UInt256) {.base, gcsafe.} =
|
||||
gasLimit: GasInt, value: UInt256) {.base, gcsafe.} =
|
||||
discard
|
||||
|
||||
method captureEnd*(ctx: TracerRef, output: openArray[byte],
|
||||
method captureEnd*(ctx: TracerRef, comp: Computation, output: openArray[byte],
|
||||
gasUsed: GasInt, error: Option[string]) {.base, gcsafe.} =
|
||||
discard
|
||||
|
||||
# Rest of call frames
|
||||
method captureEnter*(ctx: TracerRef, op: Op,
|
||||
method captureEnter*(ctx: TracerRef, comp: Computation, op: Op,
|
||||
sender: EthAddress, to: EthAddress,
|
||||
input: openArray[byte], gas: GasInt,
|
||||
input: openArray[byte], gasLimit: GasInt,
|
||||
value: UInt256) {.base, gcsafe.} =
|
||||
discard
|
||||
|
||||
method captureExit*(ctx: TracerRef, output: openArray[byte],
|
||||
method captureExit*(ctx: TracerRef, comp: Computation, output: openArray[byte],
|
||||
gasUsed: GasInt, error: Option[string]) {.base, gcsafe.} =
|
||||
discard
|
||||
|
||||
# Opcode level
|
||||
method captureOpStart*(ctx: TracerRef, pc: int,
|
||||
method captureOpStart*(ctx: TracerRef, comp: Computation, pc: int,
|
||||
op: Op, gas: GasInt,
|
||||
depth: int): int {.base, gcsafe.} =
|
||||
discard
|
||||
|
||||
method callFamilyGas*(ctx: TracerRef,
|
||||
method callFamilyGas*(ctx: TracerRef, comp: Computation,
|
||||
op: Op, gas: GasInt,
|
||||
depth: int) {.base, gcsafe.} =
|
||||
discard
|
||||
|
||||
method captureOpEnd*(ctx: TracerRef, pc: int,
|
||||
method captureOpEnd*(ctx: TracerRef, comp: Computation, pc: int,
|
||||
op: Op, gas: GasInt, refund: GasInt,
|
||||
rData: openArray[byte],
|
||||
depth: int, opIndex: int) {.base, gcsafe.} =
|
||||
discard
|
||||
|
||||
method captureFault*(ctx: TracerRef, pc: int,
|
||||
method captureFault*(ctx: TracerRef, comp: Computation, pc: int,
|
||||
op: Op, gas: GasInt, refund: GasInt,
|
||||
rData: openArray[byte],
|
||||
depth: int, error: Option[string]) {.base, gcsafe.} =
|
||||
discard
|
||||
|
||||
|
||||
method capturePrepare*(ctx: TracerRef, depth: int) {.base, gcsafe.} =
|
||||
method capturePrepare*(ctx: TracerRef, comp: Computation, depth: int) {.base, gcsafe.} =
|
||||
discard
|
||||
|
|
|
@ -283,7 +283,7 @@ proc finishRunningComputation(host: TransactionHost, call: CallParams): CallResu
|
|||
else:
|
||||
none(string)
|
||||
|
||||
host.vmState.captureEnd(c.output, gasUsed, error)
|
||||
host.vmState.captureEnd(c, c.output, gasUsed, error)
|
||||
|
||||
result.isError = c.isError
|
||||
result.gasUsed = call.gasLimit - gasRemaining
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
{"pc":10,"op":96,"gas":"0x79bf79","gasCost":"0x3","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x0"],"depth":1,"refund":0,"opName":"PUSH1"}
|
||||
{"pc":12,"op":90,"gas":"0x79bf76","gasCost":"0x2","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x0","0xf3"],"depth":1,"refund":0,"opName":"GAS"}
|
||||
{"pc":13,"op":241,"gas":"0x79bf74","gasCost":"0x77d89f","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x0","0xf3","0x79bf74"],"depth":1,"refund":0,"opName":"CALL"}
|
||||
{"pc":0,"op":11,"gas":"0x77ce77","gasCost":"0x5","memSize":0,"stack":["0x0"],"depth":2,"refund":0,"opName":"SIGNEXTEND","error":"Opcode Dispatch Error: Stack underflow, expect 2, got 0, depth=2"}
|
||||
{"pc":0,"op":11,"gas":"0x77ce77","gasCost":"0x5","memSize":0,"stack":[],"depth":2,"refund":0,"opName":"SIGNEXTEND","error":"Opcode Dispatch Error: Stack underflow, expect 2, got 0, depth=2"}
|
||||
{"pc":14,"op":80,"gas":"0x1e6d5","gasCost":"0x2","memSize":0,"stack":["0x0"],"depth":1,"refund":0,"opName":"POP"}
|
||||
{"pc":15,"op":152,"gas":"0x1e6d3","gasCost":"0x3","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"SWAP9","error":"Opcode Dispatch Error: Stack underflow for SWAP9, depth=1"}
|
||||
{"output":"","gasUsed":"0x79bf88","error":"Opcode Dispatch Error: Stack underflow for SWAP9, depth=1"}
|
||||
|
|
Loading…
Reference in New Issue