Add current computation to each EVM tracer interface (#1712)

This commit is contained in:
andri lim 2023-08-25 16:07:20 +07:00 committed by GitHub
parent 7aead6151e
commit 91704cd3ae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 65 additions and 76 deletions

View File

@ -107,9 +107,11 @@ proc asyncProcessTransactionImpl(
vmState.stateDB.clearTransientStorage() vmState.stateDB.clearTransientStorage()
# Execute the transaction. # Execute the transaction.
vmState.captureTxStart(tx.gasLimit)
let let
accTx = vmState.stateDB.beginSavepoint accTx = vmState.stateDB.beginSavepoint
gasBurned = tx.txCallEvm(sender, vmState, fork) gasBurned = tx.txCallEvm(sender, vmState, fork)
vmState.captureTxEnd(tx.gasLimit - gasBurned)
res = commitOrRollbackDependingOnGasUsed(vmState, accTx, header, tx, gasBurned, priorityFee) res = commitOrRollbackDependingOnGasUsed(vmState, accTx, header, tx, gasBurned, priorityFee)
else: else:

View File

@ -390,16 +390,18 @@ proc tracingEnabled*(c: Computation): bool =
proc traceOpCodeStarted*(c: Computation, op: Op): int {.gcsafe, raises: [].} = proc traceOpCodeStarted*(c: Computation, op: Op): int {.gcsafe, raises: [].} =
c.vmState.captureOpStart( c.vmState.captureOpStart(
c,
c.code.pc - 1, c.code.pc - 1,
op, op,
c.gasMeter.gasRemaining, c.gasMeter.gasRemaining,
c.msg.depth + 1) c.msg.depth + 1)
proc traceCallFamilyGas*(c: Computation, op: Op, gas: GasInt) {.gcsafe, raises: [].} = 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: [].} = proc traceOpCodeEnded*(c: Computation, op: Op, opIndex: int) {.gcsafe, raises: [].} =
c.vmState.captureOpEnd( c.vmState.captureOpEnd(
c,
c.code.pc - 1, c.code.pc - 1,
op, op,
c.gasMeter.gasRemaining, c.gasMeter.gasRemaining,
@ -410,6 +412,7 @@ proc traceOpCodeEnded*(c: Computation, op: Op, opIndex: int) {.gcsafe, raises: [
proc traceError*(c: Computation) {.gcsafe, raises: [].} = proc traceError*(c: Computation) {.gcsafe, raises: [].} =
c.vmState.captureFault( c.vmState.captureFault(
c,
c.code.pc - 1, c.code.pc - 1,
c.instr, c.instr,
c.gasMeter.gasRemaining, c.gasMeter.gasRemaining,
@ -419,7 +422,7 @@ proc traceError*(c: Computation) {.gcsafe, raises: [].} =
some(c.error.info)) some(c.error.info))
proc prepareTracer*(c: Computation) = proc prepareTracer*(c: Computation) =
c.vmState.capturePrepare(c.msg.depth) c.vmState.capturePrepare(c, c.msg.depth)
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# End # End

View File

@ -190,7 +190,8 @@ proc beforeExec(c: Computation): bool
{.gcsafe, raises: [ValueError].} = {.gcsafe, raises: [ValueError].} =
if c.msg.depth > 0: 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.sender, c.msg.contractAddress,
c.msg.data, c.msg.gas, c.msg.data, c.msg.gas,
c.msg.value) c.msg.value)
@ -215,7 +216,7 @@ proc afterExec(c: Computation)
some(c.error.info) some(c.error.info)
else: else:
none(string) none(string)
c.vmState.captureExit(c.output, gasUsed, error) c.vmState.captureExit(c, c.output, gasUsed, error)
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Public functions # Public functions

View File

@ -363,56 +363,57 @@ proc captureTxEnd*(vmState: BaseVMState, restGas: GasInt) =
if vmState.tracingEnabled: if vmState.tracingEnabled:
vmState.tracer.captureTxEnd(restGas) vmState.tracer.captureTxEnd(restGas)
proc captureStart*(vmState: BaseVMState, c: Computation, proc captureStart*(vmState: BaseVMState, comp: Computation,
sender: EthAddress, to: EthAddress, sender: EthAddress, to: EthAddress,
create: bool, input: openArray[byte], create: bool, input: openArray[byte],
gas: GasInt, value: UInt256) = gasLimit: GasInt, value: UInt256) =
if vmState.tracingEnabled: 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]) = gasUsed: GasInt, error: Option[string]) =
if vmState.tracingEnabled: 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, sender: EthAddress, to: EthAddress,
input: openArray[byte], gas: GasInt, input: openArray[byte], gasLimit: GasInt,
value: UInt256) = value: UInt256) =
if vmState.tracingEnabled: 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]) = gasUsed: GasInt, error: Option[string]) =
if vmState.tracingEnabled: 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, op: Op, gas: GasInt,
depth: int): int = depth: int): int =
if vmState.tracingEnabled: if vmState.tracingEnabled:
result = vmState.tracer.captureOpStart(pc, op, gas, depth) result = vmState.tracer.captureOpStart(comp, pc, op, gas, depth)
proc callFamilyGas*(vmState: BaseVMState, proc callFamilyGas*(vmState: BaseVMState,
comp: Computation,
op: Op, gas: GasInt, op: Op, gas: GasInt,
depth: int) = depth: int) =
if vmState.tracingEnabled: 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, 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(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, 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(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: if vmState.tracingEnabled:
vmState.tracer.capturePrepare(depth) vmState.tracer.capturePrepare(comp, depth)

View File

@ -23,7 +23,6 @@ type
JsonTracer* = ref object of TracerRef JsonTracer* = ref object of TracerRef
stream: Stream stream: Stream
pretty: bool pretty: bool
comp: Computation
gas: GasInt gas: GasInt
pc: int pc: int
stack: JsonNode stack: JsonNode
@ -76,13 +75,12 @@ iterator storage(ctx: JsonTracer, compDepth: int): UInt256 =
for key in ctx.storageKeys[compDepth]: for key in ctx.storageKeys[compDepth]:
yield key yield key
proc captureOpImpl(ctx: JsonTracer, 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
c = ctx.comp
var res = %{ var res = %{
"pc": %(ctx.pc), "pc": %(ctx.pc),
@ -139,7 +137,7 @@ proc newJsonTracer*(stream: Stream, flags: set[TracerFlags], pretty: bool): Json
pretty: pretty pretty: pretty
) )
method capturePrepare*(ctx: JsonTracer, depth: int) {.gcsafe.} = method capturePrepare*(ctx: JsonTracer, comp: Computation, depth: int) {.gcsafe.} =
if depth >= ctx.storageKeys.len: if depth >= ctx.storageKeys.len:
let prevLen = ctx.storageKeys.len let prevLen = ctx.storageKeys.len
ctx.storageKeys.setLen(depth + 1) ctx.storageKeys.setLen(depth + 1)
@ -149,13 +147,13 @@ method capturePrepare*(ctx: JsonTracer, depth: int) {.gcsafe.} =
ctx.storageKeys[depth] = initHashSet[UInt256]() ctx.storageKeys[depth] = initHashSet[UInt256]()
# Top call frame # Top call frame
method captureStart*(ctx: JsonTracer, c: Computation, method captureStart*(ctx: JsonTracer, comp: Computation,
sender: EthAddress, to: EthAddress, sender: EthAddress, to: EthAddress,
create: bool, input: openArray[byte], create: bool, input: openArray[byte],
gas: GasInt, value: UInt256) {.gcsafe.} = gasLimit: GasInt, value: UInt256) {.gcsafe.} =
ctx.comp = c discard
method captureEnd*(ctx: JsonTracer, output: openArray[byte], 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),
@ -166,21 +164,19 @@ method captureEnd*(ctx: JsonTracer, output: openArray[byte],
ctx.writeJson(res) ctx.writeJson(res)
# Opcode level # Opcode level
method captureOpStart*(ctx: JsonTracer, pc: int, method captureOpStart*(ctx: JsonTracer, c: Computation, pc: int,
op: Op, gas: GasInt, op: Op, gas: GasInt,
depth: int): int {.gcsafe.} = depth: int): int {.gcsafe.} =
ctx.gas = gas ctx.gas = gas
ctx.pc = pc ctx.pc = pc
if TracerFlags.DisableStack notin ctx.flags: if TracerFlags.DisableStack notin ctx.flags:
let c = ctx.comp
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(%("0x" & v.dumpHex.stripLeadingZeros))
if TracerFlags.DisableStorage notin ctx.flags and op == SSTORE: if TracerFlags.DisableStorage notin ctx.flags and op == SSTORE:
try: try:
let c = ctx.comp
if c.stack.values.len > 1: if c.stack.values.len > 1:
ctx.rememberStorageKey(c.msg.depth, c.stack[^1, UInt256]) ctx.rememberStorageKey(c.msg.depth, c.stack[^1, UInt256])
except InsufficientStack as ex: except InsufficientStack as ex:
@ -190,7 +186,7 @@ method captureOpStart*(ctx: JsonTracer, pc: int,
if op in callFamily: if op in callFamily:
try: try:
ctx.captureOpImpl(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 captureOpEnd", msg=ex.msg
@ -198,7 +194,7 @@ method captureOpStart*(ctx: JsonTracer, pc: int,
result = ctx.index result = ctx.index
inc ctx.index inc ctx.index
method callFamilyGas*(ctx: JsonTracer, method callFamilyGas*(ctx: JsonTracer, comp: Computation,
op: Op, gas: GasInt, op: Op, gas: GasInt,
depth: int) {.gcsafe.} = depth: int) {.gcsafe.} =
doAssert(op in callFamily) doAssert(op in callFamily)
@ -207,7 +203,7 @@ method callFamilyGas*(ctx: JsonTracer,
res["gasCost"] = encodeHexInt(gas) res["gasCost"] = encodeHexInt(gas)
ctx.writeJson(res) ctx.writeJson(res)
method captureOpEnd*(ctx: JsonTracer, pc: int, method captureOpEnd*(ctx: JsonTracer, 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) {.gcsafe.} = depth: int, opIndex: int) {.gcsafe.} =
@ -217,16 +213,16 @@ method captureOpEnd*(ctx: JsonTracer, pc: int,
return return
try: 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: except RlpError as ex:
error "JsonTracer captureOpEnd", msg=ex.msg 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, 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:
ctx.captureOpImpl(pc, op, gas, refund, rData, depth, error) ctx.captureOpImpl(comp, pc, op, gas, refund, rData, depth, error)
except RlpError as ex: except RlpError as ex:
error "JsonTracer captureOpEnd", msg=ex.msg error "JsonTracer captureOpEnd", msg=ex.msg

View File

@ -24,7 +24,6 @@ type
trace: JsonNode trace: JsonNode
accounts: HashSet[EthAddress] accounts: HashSet[EthAddress]
storageKeys: seq[HashSet[UInt256]] storageKeys: seq[HashSet[UInt256]]
comp: Computation
gas: GasInt gas: GasInt
proc hash*(x: UInt256): Hash = proc hash*(x: UInt256): Hash =
@ -62,7 +61,7 @@ proc newLegacyTracer*(flags: set[TracerFlags]): LegacyTracer =
trace: trace trace: trace
) )
method capturePrepare*(ctx: LegacyTracer, depth: int) {.gcsafe.} = method capturePrepare*(ctx: LegacyTracer, comp: Computation, depth: int) {.gcsafe.} =
if depth >= ctx.storageKeys.len: if depth >= ctx.storageKeys.len:
let prevLen = ctx.storageKeys.len let prevLen = ctx.storageKeys.len
ctx.storageKeys.setLen(depth + 1) ctx.storageKeys.setLen(depth + 1)
@ -71,25 +70,13 @@ method capturePrepare*(ctx: LegacyTracer, depth: int) {.gcsafe.} =
ctx.storageKeys[depth] = initHashSet[UInt256]() 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 # Opcode level
method captureOpStart*(ctx: LegacyTracer, pc: int, method captureOpStart*(ctx: LegacyTracer, c: Computation, pc: int,
op: Op, gas: GasInt, op: Op, gas: GasInt,
depth: int): int {.gcsafe.} = depth: int): int {.gcsafe.} =
try: try:
let let
j = newJObject() j = newJObject()
c = ctx.comp
ctx.trace["structLogs"].add(j) ctx.trace["structLogs"].add(j)
j["op"] = %(($op).toUpperAscii) j["op"] = %(($op).toUpperAscii)
@ -139,14 +126,13 @@ method captureOpStart*(ctx: LegacyTracer, 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, pc: int, method captureOpEnd*(ctx: LegacyTracer, c: 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) {.gcsafe.} = depth: int, opIndex: int) {.gcsafe.} =
try: try:
let let
j = ctx.trace["structLogs"].elems[opIndex] j = ctx.trace["structLogs"].elems[opIndex]
c = ctx.comp
# TODO: figure out how to get storage # TODO: figure out how to get storage
# when contract execution interrupted by exception # when contract execution interrupted by exception
@ -170,15 +156,14 @@ method captureOpEnd*(ctx: LegacyTracer, 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, pc: int, method captureFault*(ctx: LegacyTracer, 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]) {.gcsafe.} = depth: int, error: Option[string]) {.gcsafe.} =
try: try:
let c = ctx.comp
if ctx.trace["structLogs"].elems.len > 0: if ctx.trace["structLogs"].elems.len > 0:
let j = ctx.trace["structLogs"].elems[^1] let j = ctx.trace["structLogs"].elems[^1]
j["error"] = %(c.error.info) j["error"] = %(comp.error.info)
j["gasCost"] = %(ctx.gas - gas) j["gasCost"] = %(ctx.gas - gas)
ctx.trace["failed"] = %true ctx.trace["failed"] = %true

View File

@ -139,6 +139,7 @@ type
flags*: set[TracerFlags] flags*: set[TracerFlags]
# Transaction level # Transaction level
# This is called once fo each transaction
method captureTxStart*(ctx: TracerRef, gasLimit: GasInt) {.base, gcsafe.} = method captureTxStart*(ctx: TracerRef, gasLimit: GasInt) {.base, gcsafe.} =
discard discard
@ -146,50 +147,50 @@ method captureTxEnd*(ctx: TracerRef, restGas: GasInt) {.base, gcsafe.} =
discard discard
# Top call frame # Top call frame
method captureStart*(ctx: TracerRef, c: Computation, method captureStart*(ctx: TracerRef, comp: Computation,
sender: EthAddress, to: EthAddress, sender: EthAddress, to: EthAddress,
create: bool, input: openArray[byte], create: bool, input: openArray[byte],
gas: GasInt, value: UInt256) {.base, gcsafe.} = gasLimit: GasInt, value: UInt256) {.base, gcsafe.} =
discard discard
method captureEnd*(ctx: TracerRef, output: openArray[byte], method captureEnd*(ctx: TracerRef, comp: Computation, output: openArray[byte],
gasUsed: GasInt, error: Option[string]) {.base, gcsafe.} = gasUsed: GasInt, error: Option[string]) {.base, gcsafe.} =
discard discard
# Rest of call frames # Rest of call frames
method captureEnter*(ctx: TracerRef, op: Op, method captureEnter*(ctx: TracerRef, comp: Computation, op: Op,
sender: EthAddress, to: EthAddress, sender: EthAddress, to: EthAddress,
input: openArray[byte], gas: GasInt, input: openArray[byte], gasLimit: GasInt,
value: UInt256) {.base, gcsafe.} = value: UInt256) {.base, gcsafe.} =
discard discard
method captureExit*(ctx: TracerRef, output: openArray[byte], method captureExit*(ctx: TracerRef, comp: Computation, output: openArray[byte],
gasUsed: GasInt, error: Option[string]) {.base, gcsafe.} = gasUsed: GasInt, error: Option[string]) {.base, gcsafe.} =
discard discard
# Opcode level # Opcode level
method captureOpStart*(ctx: TracerRef, pc: int, method captureOpStart*(ctx: TracerRef, comp: Computation, pc: int,
op: Op, gas: GasInt, op: Op, gas: GasInt,
depth: int): int {.base, gcsafe.} = depth: int): int {.base, gcsafe.} =
discard discard
method callFamilyGas*(ctx: TracerRef, method callFamilyGas*(ctx: TracerRef, comp: Computation,
op: Op, gas: GasInt, op: Op, gas: GasInt,
depth: int) {.base, gcsafe.} = depth: int) {.base, gcsafe.} =
discard discard
method captureOpEnd*(ctx: TracerRef, pc: int, method captureOpEnd*(ctx: TracerRef, 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) {.base, gcsafe.} = depth: int, opIndex: int) {.base, gcsafe.} =
discard discard
method captureFault*(ctx: TracerRef, pc: int, method captureFault*(ctx: TracerRef, 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]) {.base, gcsafe.} = depth: int, error: Option[string]) {.base, gcsafe.} =
discard discard
method capturePrepare*(ctx: TracerRef, depth: int) {.base, gcsafe.} = method capturePrepare*(ctx: TracerRef, comp: Computation, depth: int) {.base, gcsafe.} =
discard discard

View File

@ -283,7 +283,7 @@ proc finishRunningComputation(host: TransactionHost, call: CallParams): CallResu
else: else:
none(string) none(string)
host.vmState.captureEnd(c.output, gasUsed, error) host.vmState.captureEnd(c, c.output, gasUsed, error)
result.isError = c.isError result.isError = c.isError
result.gasUsed = call.gasLimit - gasRemaining result.gasUsed = call.gasLimit - gasRemaining

View File

@ -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":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":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":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":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"} {"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"} {"output":"","gasUsed":"0x79bf88","error":"Opcode Dispatch Error: Stack underflow for SWAP9, depth=1"}