Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Utilize BalanceChangeReason in tracing #375

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions core/state_transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ func (st *StateTransition) buyGas() error {

// Arbitrum: record fee payment
if tracer := st.evm.Config.Tracer; tracer != nil && tracer.CaptureArbitrumTransfer != nil {
tracer.CaptureArbitrumTransfer(&st.msg.From, nil, mgval, true, "feePayment")
tracer.CaptureArbitrumTransfer(&st.msg.From, nil, mgval, true, tracing.BalanceDecreaseGasBuy)
}

return nil
Expand Down Expand Up @@ -529,7 +529,7 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {

// Arbitrum: record the tip
if tracer := st.evm.Config.Tracer; tracer != nil && !st.evm.ProcessingHook.DropTip() && tracer.CaptureArbitrumTransfer != nil {
tracer.CaptureArbitrumTransfer(nil, &tipReceipient, tipAmount, false, "tip")
tracer.CaptureArbitrumTransfer(nil, &tipReceipient, tipAmount, false, tracing.BalanceIncreaseRewardTransactionFee)
}

st.evm.ProcessingHook.EndTxHook(st.gasRemaining, vmerr == nil)
Expand All @@ -539,7 +539,7 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
suicides := st.evm.StateDB.GetSelfDestructs()
for i, address := range suicides {
balance := st.evm.StateDB.GetBalance(address)
tracer.CaptureArbitrumTransfer(&suicides[i], nil, balance.ToBig(), false, "selfDestruct")
tracer.CaptureArbitrumTransfer(&suicides[i], nil, balance.ToBig(), false, tracing.BalanceDecreaseSelfdestruct)
}
}

Expand Down Expand Up @@ -583,7 +583,7 @@ func (st *StateTransition) refundGas(refundQuotient uint64) uint64 {

// Arbitrum: record the gas refund
if tracer := st.evm.Config.Tracer; tracer != nil && tracer.CaptureArbitrumTransfer != nil {
tracer.CaptureArbitrumTransfer(nil, &st.msg.From, remaining.ToBig(), false, "gasRefund")
tracer.CaptureArbitrumTransfer(nil, &st.msg.From, remaining.ToBig(), false, tracing.BalanceIncreaseGasReturn)
}

// Also return remaining gas to the block gas counter so it is
Expand Down
107 changes: 106 additions & 1 deletion core/tracing/hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ type (
// LogHook is called when a log is emitted.
LogHook = func(log *types.Log)

CaptureArbitrumTransferHook = func(from, to *common.Address, value *big.Int, before bool, purpose string)
CaptureArbitrumTransferHook = func(from, to *common.Address, value *big.Int, before bool, reason BalanceChangeReason)
CaptureArbitrumStorageGetHook = func(key common.Hash, depth int, before bool)
CaptureArbitrumStorageSetHook = func(key, value common.Hash, depth int, before bool)

Expand Down Expand Up @@ -232,8 +232,113 @@ const (
// account within the same tx (captured at end of tx).
// Note it doesn't account for a self-destruct which appoints itself as recipient.
BalanceDecreaseSelfdestructBurn BalanceChangeReason = 14

// Arbitrum specific
BalanceIncreaseDeposit BalanceChangeReason = 15
ganeshvanahalli marked this conversation as resolved.
Show resolved Hide resolved
BalanceDecreaseWithdrawToL1 BalanceChangeReason = 16
BalanceIncreaseL1PosterFee BalanceChangeReason = 17
BalanceIncreaseInfraFee BalanceChangeReason = 18
BalanceIncreaseNetworkFee BalanceChangeReason = 19
BalanceIncreaseRetryTxPrepaid BalanceChangeReason = 20
BalanceDecreaseRetryTxUndoRefund BalanceChangeReason = 21

BalanceChangeTransferRetryTxToEscrow BalanceChangeReason = 22
BalanceChangeTransferRetryTxFromEscrow BalanceChangeReason = 23

BalanceChangeTransferRetryableToFeeRefundAddr BalanceChangeReason = 24
BalanceChangeTransferRetryableToEscrow BalanceChangeReason = 25

BalanceChangeTransferRetryableToInfra BalanceChangeReason = 26
BalanceChangeTransferRetryableFromInfra BalanceChangeReason = 27
BalanceChangeTransferRetryableToNetwork BalanceChangeReason = 28
BalanceChangeTransferRetryableFromNetwork BalanceChangeReason = 29

BalanceChangeTransferBatchposterReward BalanceChangeReason = 30
BalanceChangeTransferBatchposterRefund BalanceChangeReason = 31

// Stylus
BalanceChangeTransferActivationFee BalanceChangeReason = 32
BalanceChangeTransferActivationReimburse BalanceChangeReason = 33
)

func (b BalanceChangeReason) String(prev, new *big.Int) string {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the motivation for the new strings? Are they formatted after anything standard?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The thing is geth itself doesn't use BalanceChangeReason type for anything meaningful (as of 1.14.0) i.e in any of the tracing code, but gives us the freedom to decide how and where we use it.

They aren't formatted after anything standard but gives the reason for the balance change itself, which I thought we could use in tracing, let me know if I got it wrong.

For example geth's current master uses BalanceChangeReason this way https://github.com/ethereum/go-ethereum/blob/6d3d252a5ece0687dcaaf197e0bfc03466161ff1/eth/tracers/live/supply.go#L191-L208

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

earlier in the purpose field of beforeEVMTransfers and afterEVMTransfers we had single word strings like feeCollection, tip etc.. but now we could have a more descriptive reasons with the String() impl like in the above comment

...
...

{
    "beforeEVMTransfers": [
        {
            "purpose": "purchase of gas for execution of a transaction",
            "from": "0x26E554a8acF9003b83495c7f45F06edCB803d4e3",
            "to": null,
            "value": "0x0"
        }
    ],
    "afterEVMTransfers": [
        {
            "purpose": "refund for unused gas at the end of execution",
            "from": null,
            "to": "0x26E554a8acF9003b83495c7f45F06edCB803d4e3",
            "value": "0x0"
        },

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure, but I guess someone is already parsing the exiting short srings.
If they are - this change would hurt them, and I rather avoid it.
We could still have a "String" function but have it return the old string to avoid compatibility errors.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed the String() to be backwards compatible

// When both prev and new are nil, we only return the main reason without specifying if the balance incrased or decreased
// useful for CaptureArbitrumTransfer
var reason string

if prev != nil && new != nil {
if new.Cmp(prev) == 1 {
reason = "balance increase due to "
} else if new.Cmp(prev) == -1 {
reason = "balance decrease due to "
}
} else if new != nil {
reason = "balance increase due to "
} else if prev != nil {
reason = "balance decrease due to "
}

// Append main reason for the balance change
switch b {
case BalanceIncreaseRewardTransactionFee:
reason += "payment of transaction tip"
case BalanceDecreaseGasBuy:
reason += "purchase of gas for execution of a transaction"
case BalanceIncreaseGasReturn:
reason += "refund for unused gas at the end of execution"
case BalanceChangeTransfer:
reason += "transfer via a call"
case BalanceDecreaseSelfdestruct:
reason += "selfDestruct"
case BalanceIncreaseDeposit:
reason += "deposit"
case BalanceDecreaseWithdrawToL1:
reason += "withdrawal to L1"
case BalanceIncreaseL1PosterFee:
reason += "fee collection for L1 posting"
case BalanceIncreaseInfraFee:
reason += "fee collection by infrastructure fee account"
case BalanceIncreaseNetworkFee:
reason += "fee collection by network fee account"
// ArbitrumRetryTx
case BalanceIncreaseRetryTxPrepaid:
reason += "deposit of prepaid value in a tx of ArbitrumRetryTx type"
case BalanceDecreaseRetryTxUndoRefund:
reason += "undoing of Geth's refund for a tx of ArbitrumRetryTx type"
case BalanceChangeTransferRetryTxToEscrow:
reason += "transfer to escrow in a tx of ArbitrumRetryTx type"
case BalanceChangeTransferRetryTxFromEscrow:
reason += "transfer from escrow in a tx of ArbitrumRetryTx type"
// ArbitrumSubmitRetryableTx
case BalanceChangeTransferRetryableToFeeRefundAddr:
reason += "transfer to FeeRefundAddr in a tx of ArbitrumSubmitRetryableTx type"
case BalanceChangeTransferRetryableToEscrow:
reason += "transfer to escrow in a tx of ArbitrumSubmitRetryableTx type"
case BalanceChangeTransferRetryableToInfra:
reason += "transfer to infrastructure fee account in a tx of ArbitrumSubmitRetryableTx type"
case BalanceChangeTransferRetryableFromInfra:
reason += "transfer from infrastructure fee account in a tx of ArbitrumSubmitRetryableTx type"
case BalanceChangeTransferRetryableToNetwork:
reason += "transfer to network fee account in a tx of ArbitrumSubmitRetryableTx type"
case BalanceChangeTransferRetryableFromNetwork:
reason += "transfer from network fee account in a tx of ArbitrumSubmitRetryableTx type"
// Batchposter
case BalanceChangeTransferBatchposterReward:
reason += "transfer from L1PricerFundsPoolAddress as batchPosterReward"
case BalanceChangeTransferBatchposterRefund:
reason += "transfer from L1PricerFundsPoolAddress as batchPosterRefund"
// Stylus
case BalanceChangeTransferActivationFee:
reason += "transfer of activation fee to network fee account"
case BalanceChangeTransferActivationReimburse:
reason += "transfer of reimburse amount after charging the activation fee"
default:
return "unspecified"
}

return reason
}

// GasChangeReason is used to indicate the reason for a gas change, useful
// for tracing and reporting.
//
Expand Down
14 changes: 11 additions & 3 deletions eth/tracers/internal/tracetest/calltrace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,19 @@ type arbitrumTransfer struct {
Value string `json:"value"`
}

type balanceChange struct {
Addr string `json:"addr"`
Prev string `json:"prev"`
New string `json:"new"`
Reason string `json:"reason"`
}

// callTrace is the result of a callTracer run.
type callTrace struct {
// Arbitrum: we add these here due to the tracer returning the top frame
BeforeEVMTransfers *[]arbitrumTransfer `json:"beforeEVMTransfers,omitempty"`
AfterEVMTransfers *[]arbitrumTransfer `json:"afterEVMTransfers,omitempty"`
BalanceChanges *[]balanceChange `json:"balanceChanges,omitempty"`

From common.Address `json:"from"`
Gas *hexutil.Uint64 `json:"gas"`
Expand Down Expand Up @@ -301,13 +309,13 @@ func TestInternals(t *testing.T) {
byte(vm.CALL),
},
tracer: mkTracer("callTracer", nil),
want: fmt.Sprintf(`{"beforeEVMTransfers":[{"purpose":"feePayment","from":"%s","to":null,"value":"0x13880"}],"afterEVMTransfers":[{"purpose":"gasRefund","from":null,"to":"%s","value":"0xe3a8"},{"purpose":"tip","from":null,"to":"0x0000000000000000000000000000000000000000","value":"0x54d8"}],"from":"%s","gas":"0x13880","gasUsed":"0x54d8","to":"0x00000000000000000000000000000000deadbeef","input":"0x","calls":[{"from":"0x00000000000000000000000000000000deadbeef","gas":"0xe01a","gasUsed":"0x0","to":"0x00000000000000000000000000000000000000ff","input":"0x","value":"0x0","type":"CALL"}],"value":"0x0","type":"CALL"}`, origin.Hex(), origin.Hex(), originHex),
want: fmt.Sprintf(`{"beforeEVMTransfers":[{"purpose":"purchase of gas for execution of a transaction","from":"%s","to":null,"value":"0x13880"}],"afterEVMTransfers":[{"purpose":"refund for unused gas at the end of execution","from":null,"to":"%s","value":"0xe3a8"},{"purpose":"payment of transaction tip","from":null,"to":"0x0000000000000000000000000000000000000000","value":"0x54d8"}],"balanceChanges":[{"addr":"%s","prev":"0x1c6bf52634000","new":"0x1c6bf52620780","reason":"balance decrease due to purchase of gas for execution of a transaction"},{"addr":"%s","prev":"0x1c6bf52620780","new":"0x1c6bf5262eb28","reason":"balance increase due to refund for unused gas at the end of execution"},{"addr":"0x0000000000000000000000000000000000000000","prev":"0x0","new":"0x54d8","reason":"balance increase due to payment of transaction tip"}],"from":"%s","gas":"0x13880","gasUsed":"0x54d8","to":"0x00000000000000000000000000000000deadbeef","input":"0x","calls":[{"from":"0x00000000000000000000000000000000deadbeef","gas":"0xe01a","gasUsed":"0x0","to":"0x00000000000000000000000000000000000000ff","input":"0x","value":"0x0","type":"CALL"}],"value":"0x0","type":"CALL"}`, origin.Hex(), origin.Hex(), origin.Hex(), origin.Hex(), originHex),
},
{
name: "Stack depletion in LOG0",
code: []byte{byte(vm.LOG3)},
tracer: mkTracer("callTracer", json.RawMessage(`{ "withLog": true }`)),
want: fmt.Sprintf(`{"beforeEVMTransfers":[{"purpose":"feePayment","from":"%s","to":null,"value":"0x13880"}],"afterEVMTransfers":[{"purpose":"gasRefund","from":null,"to":"%s","value":"0x0"},{"purpose":"tip","from":null,"to":"0x0000000000000000000000000000000000000000","value":"0x13880"}],"from":"%s","gas":"0x13880","gasUsed":"0x13880","to":"0x00000000000000000000000000000000deadbeef","input":"0x","error":"stack underflow (0 \u003c=\u003e 5)","value":"0x0","type":"CALL"}`, origin.Hex(), origin.Hex(), originHex),
want: fmt.Sprintf(`{"beforeEVMTransfers":[{"purpose":"purchase of gas for execution of a transaction","from":"%s","to":null,"value":"0x13880"}],"afterEVMTransfers":[{"purpose":"refund for unused gas at the end of execution","from":null,"to":"%s","value":"0x0"},{"purpose":"payment of transaction tip","from":null,"to":"0x0000000000000000000000000000000000000000","value":"0x13880"}],"balanceChanges":[{"addr":"%s","prev":"0x1c6bf52634000","new":"0x1c6bf52620780","reason":"balance decrease due to purchase of gas for execution of a transaction"},{"addr":"0x0000000000000000000000000000000000000000","prev":"0x0","new":"0x13880","reason":"balance increase due to payment of transaction tip"}],"from":"%s","gas":"0x13880","gasUsed":"0x13880","to":"0x00000000000000000000000000000000deadbeef","input":"0x","error":"stack underflow (0 \u003c=\u003e 5)","value":"0x0","type":"CALL"}`, origin.Hex(), origin.Hex(), origin.Hex(), originHex),
},
{
name: "Mem expansion in LOG0",
Expand All @@ -320,7 +328,7 @@ func TestInternals(t *testing.T) {
byte(vm.LOG0),
},
tracer: mkTracer("callTracer", json.RawMessage(`{ "withLog": true }`)),
want: fmt.Sprintf(`{"beforeEVMTransfers":[{"purpose":"feePayment","from":"%s","to":null,"value":"0x13880"}],"afterEVMTransfers":[{"purpose":"gasRefund","from":null,"to":"%s","value":"0xdce2"},{"purpose":"tip","from":null,"to":"0x0000000000000000000000000000000000000000","value":"0x5b9e"}],"from":"%s","gas":"0x13880","gasUsed":"0x5b9e","to":"0x00000000000000000000000000000000deadbeef","input":"0x","logs":[{"address":"0x00000000000000000000000000000000deadbeef","topics":[],"data":"0x000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","position":"0x0"}],"value":"0x0","type":"CALL"}`, origin.Hex(), origin.Hex(), originHex),
want: fmt.Sprintf(`{"beforeEVMTransfers":[{"purpose":"purchase of gas for execution of a transaction","from":"%s","to":null,"value":"0x13880"}],"afterEVMTransfers":[{"purpose":"refund for unused gas at the end of execution","from":null,"to":"%s","value":"0xdce2"},{"purpose":"payment of transaction tip","from":null,"to":"0x0000000000000000000000000000000000000000","value":"0x5b9e"}],"balanceChanges":[{"addr":"%s","prev":"0x1c6bf52634000","new":"0x1c6bf52620780","reason":"balance decrease due to purchase of gas for execution of a transaction"},{"addr":"%s","prev":"0x1c6bf52620780","new":"0x1c6bf5262e462","reason":"balance increase due to refund for unused gas at the end of execution"},{"addr":"0x0000000000000000000000000000000000000000","prev":"0x0","new":"0x5b9e","reason":"balance increase due to payment of transaction tip"}],"from":"%s","gas":"0x13880","gasUsed":"0x5b9e","to":"0x00000000000000000000000000000000deadbeef","input":"0x","logs":[{"address":"0x00000000000000000000000000000000deadbeef","topics":[],"data":"0x000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","position":"0x0"}],"value":"0x0","type":"CALL"}`, origin.Hex(), origin.Hex(), origin.Hex(), origin.Hex(), originHex),
},
{
// Leads to OOM on the prestate tracer
Expand Down
28 changes: 20 additions & 8 deletions eth/tracers/internal/tracetest/testdata/call_tracer/blob_tx.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,30 +56,42 @@
},
"input": "0x03f8b1820539806485174876e800825208940c2c51a0990aee1d73c1228de1586883415575088080c083020000f842a00100c9fbdf97f747e85847b4f3fff408f89c26842f77c882858bf2c89923849aa00138e3896f3c27f2389147507f8bcec52028b0efca6ee842ed83c9158873943880a0dbac3f97a532c9b00e6239b29036245a5bfbb96940b9d848634661abee98b945a03eec8525f261c2e79798f7b45a5d6ccaefa24576d53ba5023e919b86841c0675",
"result": {
"beforeEVMTransfers":
[
"beforeEVMTransfers": [
{
"purpose": "feePayment",
"purpose": "purchase of gas for execution of a transaction",
"from": "0x0c2c51a0990AeE1d73C1228de158688341557508",
"to": null,
"value": "0x2de364958"
}
],
"afterEVMTransfers":
[
"afterEVMTransfers": [
{
"purpose": "gasRefund",
"purpose": "refund for unused gas at the end of execution",
"from": null,
"to": "0x0c2c51a0990AeE1d73C1228de158688341557508",
"value": "0x0"
},
{
"purpose": "tip",
"purpose": "payment of transaction tip",
"from": null,
"to": "0x0000000000000000000000000000000000000000",
"value": "0x200b20"
}
],
"balanceChanges": [
{
"addr": "0x0c2c51a0990AeE1d73C1228de158688341557508",
"prev": "0xde0b6b3a7640000",
"new": "0xde0b6b0c92db6a8",
"reason": "balance decrease due to purchase of gas for execution of a transaction"
},
{
"addr": "0x0000000000000000000000000000000000000000",
"prev": "0x272e0528",
"new": "0x274e1048",
"reason": "balance increase due to payment of transaction tip"
}
],
"from": "0x0c2c51a0990aee1d73c1228de158688341557508",
"gas": "0x5208",
"gasUsed": "0x5208",
Expand All @@ -88,4 +100,4 @@
"value": "0x0",
"type": "CALL"
}
}
}
22 changes: 18 additions & 4 deletions eth/tracers/internal/tracetest/testdata/call_tracer/create.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,26 +48,40 @@
"result": {
"beforeEVMTransfers": [
{
"purpose": "feePayment",
"purpose": "purchase of gas for execution of a transaction",
"from": "0x13e4ACeFE6a6700604929946E70E6443E4E73447",
"to": null,
"value": "0x2a0383e2a65c00"
}
],
"afterEVMTransfers": [
{
"purpose": "gasRefund",
"purpose": "refund for unused gas at the end of execution",
"from": null,
"to": "0x13e4ACeFE6a6700604929946E70E6443E4E73447",
"value": "0x0"
},
{
"purpose": "tip",
"purpose": "payment of transaction tip",
"from": null,
"to": "0xD049bfd667cB46Aa3Ef5Df0dA3e57DB3Be39E511",
"value": "0x2a0383e2a65c00"
}
],
"balanceChanges": [
{
"addr": "0x13e4ACeFE6a6700604929946E70E6443E4E73447",
"prev": "0xcf3e0938579f000",
"new": "0xcc9dd0fa2d39400",
"reason": "balance decrease due to purchase of gas for execution of a transaction"
},
{
"addr": "0xD049bfd667cB46Aa3Ef5Df0dA3e57DB3Be39E511",
"prev": "0x0",
"new": "0x2a0383e2a65c00",
"reason": "balance increase due to payment of transaction tip"
}
],
"from": "0x13e4acefe6a6700604929946e70e6443e4e73447",
"gas": "0x897be",
"gasUsed": "0x897be",
Expand All @@ -77,4 +91,4 @@
"type": "CREATE",
"value": "0x0"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -111,27 +111,47 @@
"result": {
"beforeEVMTransfers": [
{
"purpose": "feePayment",
"purpose": "purchase of gas for execution of a transaction",
"from": "0x70C9217D814985faEF62B124420F8dFbdDD96433",
"to": null,
"value": "0x11c37937e08000"
}
],
"afterEVMTransfers": [
{
"purpose": "gasRefund",
"purpose": "refund for unused gas at the end of execution",
"from": null,
"to": "0x70C9217D814985faEF62B124420F8dFbdDD96433",
"value": "0xac27a3b12e800"
},
{
"purpose": "tip",
"purpose": "payment of transaction tip",
"from": null,
"to": "0x1977C248e1014Cc103929Dd7f154199C916E39Ec",
"value": "0x700fefccd9800"
}
],
"calls": [
"balanceChanges": [
{
"addr": "0x70C9217D814985faEF62B124420F8dFbdDD96433",
"prev": "0x4ef436dcbda6cd4a",
"new": "0x4ee2736385c64d4a",
"reason": "balance decrease due to purchase of gas for execution of a transaction"
},
{
"addr": "0x70C9217D814985faEF62B124420F8dFbdDD96433",
"prev": "0x4ee2736385c64d4a",
"new": "0x4eed35ddc0d9354a",
"reason": "balance increase due to refund for unused gas at the end of execution"
},
{
"addr": "0x1977C248e1014Cc103929Dd7f154199C916E39Ec",
"prev": "0x0",
"new": "0x700fefccd9800",
"reason": "balance increase due to payment of transaction tip"
}
],
"calls": [
{
"from": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b",
"gas": "0x31217",
Expand Down Expand Up @@ -428,4 +448,4 @@
"type": "CALL",
"value": "0x0"
}
}
}
Loading
Loading