mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-02-26 15:47:21 +00:00
core/tracing: reshape the comments in core/tracing
This commit is contained in:
parent
b33cf06ce7
commit
af34c01b90
2 changed files with 151 additions and 70 deletions
|
|
@ -127,7 +127,6 @@ type (
|
|||
CloseHook = func()
|
||||
|
||||
// BlockStartHook is called before executing `block`.
|
||||
// `td` is the total difficulty prior to `block`.
|
||||
BlockStartHook = func(event BlockEvent)
|
||||
|
||||
// BlockEndHook is called after executing a block.
|
||||
|
|
@ -141,24 +140,25 @@ type (
|
|||
// GenesisBlockHook is called when the genesis block is being processed.
|
||||
GenesisBlockHook = func(genesis *types.Block, alloc types.GenesisAlloc)
|
||||
|
||||
// OnSystemCallStartHook is called when a system call is about to be executed. Today,
|
||||
// this hook is invoked when the EIP-4788 system call is about to be executed to set the
|
||||
// beacon block root.
|
||||
// OnSystemCallStartHook is called when a system call is about to be executed.
|
||||
// Today, this hook is invoked when the EIP-4788 system call is about to be
|
||||
// executed to set the beacon block root.
|
||||
//
|
||||
// After this hook, the EVM call tracing will happened as usual so you will receive a `OnEnter/OnExit`
|
||||
// as well as state hooks between this hook and the `OnSystemCallEndHook`.
|
||||
// After this hook, the EVM call tracing will happened as usual so you will
|
||||
// receive a `OnEnter/OnExit` as well as state hooks between this hook and
|
||||
// the `OnSystemCallEndHook`.
|
||||
//
|
||||
// Note that system call happens outside normal transaction execution, so the `OnTxStart/OnTxEnd` hooks
|
||||
// will not be invoked.
|
||||
// Note that system call happens outside normal transaction execution, so
|
||||
// the `OnTxStart/OnTxEnd` hooks will not be invoked.
|
||||
OnSystemCallStartHook = func()
|
||||
|
||||
// OnSystemCallStartHookV2 is called when a system call is about to be executed. Refer
|
||||
// to `OnSystemCallStartHook` for more information.
|
||||
// OnSystemCallStartHookV2 is called when a system call is about to be executed.
|
||||
// Refer to `OnSystemCallStartHook` for more information.
|
||||
OnSystemCallStartHookV2 = func(vm *VMContext)
|
||||
|
||||
// OnSystemCallEndHook is called when a system call has finished executing. Today,
|
||||
// this hook is invoked when the EIP-4788 system call is about to be executed to set the
|
||||
// beacon block root.
|
||||
// OnSystemCallEndHook is called when a system call has finished executing.
|
||||
// Today, this hook is invoked when the EIP-4788 system call is about to be
|
||||
// executed to set the beacon block root.
|
||||
OnSystemCallEndHook = func()
|
||||
|
||||
/*
|
||||
|
|
@ -207,6 +207,7 @@ type Hooks struct {
|
|||
OnOpcode OpcodeHook
|
||||
OnFault FaultHook
|
||||
OnGasChange GasChangeHook
|
||||
|
||||
// Chain events
|
||||
OnBlockchainInit BlockchainInitHook
|
||||
OnClose CloseHook
|
||||
|
|
@ -233,6 +234,7 @@ type Hooks struct {
|
|||
//State read events
|
||||
OnColdStorageRead ColdStorageReadHook
|
||||
OnColdAccountRead ColdAccountReadHook
|
||||
|
||||
// Block hash read
|
||||
OnBlockHashRead BlockHashReadHook
|
||||
}
|
||||
|
|
@ -249,57 +251,74 @@ const (
|
|||
// Issuance
|
||||
// BalanceIncreaseRewardMineUncle is a reward for mining an uncle block.
|
||||
BalanceIncreaseRewardMineUncle BalanceChangeReason = 1
|
||||
|
||||
// BalanceIncreaseRewardMineBlock is a reward for mining a block.
|
||||
BalanceIncreaseRewardMineBlock BalanceChangeReason = 2
|
||||
|
||||
// BalanceIncreaseWithdrawal is ether withdrawn from the beacon chain.
|
||||
BalanceIncreaseWithdrawal BalanceChangeReason = 3
|
||||
|
||||
// BalanceIncreaseGenesisBalance is ether allocated at the genesis block.
|
||||
BalanceIncreaseGenesisBalance BalanceChangeReason = 4
|
||||
|
||||
// Transaction fees
|
||||
// BalanceIncreaseRewardTransactionFee is the transaction tip increasing block builder's balance.
|
||||
// BalanceIncreaseRewardTransactionFee is the transaction tip increasing
|
||||
// block builder's balance.
|
||||
BalanceIncreaseRewardTransactionFee BalanceChangeReason = 5
|
||||
|
||||
// BalanceDecreaseGasBuy is spent to purchase gas for execution a transaction.
|
||||
// Part of this gas will be burnt as per EIP-1559 rules.
|
||||
BalanceDecreaseGasBuy BalanceChangeReason = 6
|
||||
|
||||
// BalanceIncreaseGasReturn is ether returned for unused gas at the end of execution.
|
||||
BalanceIncreaseGasReturn BalanceChangeReason = 7
|
||||
|
||||
// DAO fork
|
||||
// BalanceIncreaseDaoContract is ether sent to the DAO refund contract.
|
||||
BalanceIncreaseDaoContract BalanceChangeReason = 8
|
||||
// BalanceDecreaseDaoAccount is ether taken from a DAO account to be moved to the refund contract.
|
||||
|
||||
// BalanceDecreaseDaoAccount is ether taken from a DAO account to be moved
|
||||
// to the refund contract.
|
||||
BalanceDecreaseDaoAccount BalanceChangeReason = 9
|
||||
|
||||
// BalanceChangeTransfer is ether transferred via a call.
|
||||
// it is a decrease for the sender and an increase for the recipient.
|
||||
BalanceChangeTransfer BalanceChangeReason = 10
|
||||
|
||||
// BalanceChangeTouchAccount is a transfer of zero value. It is only there to
|
||||
// touch-create an account.
|
||||
BalanceChangeTouchAccount BalanceChangeReason = 11
|
||||
|
||||
// BalanceIncreaseSelfdestruct is added to the recipient as indicated by a selfdestructing account.
|
||||
// BalanceIncreaseSelfdestruct is added to the recipient as indicated by a
|
||||
// selfdestructing account.
|
||||
BalanceIncreaseSelfdestruct BalanceChangeReason = 12
|
||||
|
||||
// BalanceDecreaseSelfdestruct is deducted from a contract due to self-destruct.
|
||||
BalanceDecreaseSelfdestruct BalanceChangeReason = 13
|
||||
|
||||
// BalanceDecreaseSelfdestructBurn is ether that is sent to an already self-destructed
|
||||
// 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
|
||||
|
||||
// BalanceChangeRevert is emitted when the balance is reverted back to a previous value due to call failure.
|
||||
// It is only emitted when the tracer has opted in to use the journaling wrapper (WrapWithJournal).
|
||||
// BalanceChangeRevert is emitted when the balance is reverted back to a
|
||||
// previous value due to call failure.
|
||||
//
|
||||
// It is only emitted when the tracer has opted in to use the journaling
|
||||
// wrapper (WrapWithJournal).
|
||||
BalanceChangeRevert BalanceChangeReason = 15
|
||||
)
|
||||
|
||||
// GasChangeReason is used to indicate the reason for a gas change, useful
|
||||
// for tracing and reporting.
|
||||
//
|
||||
// There is essentially two types of gas changes, those that can be emitted once per transaction
|
||||
// and those that can be emitted on a call basis, so possibly multiple times per transaction.
|
||||
// There is essentially two types of gas changes, those that can be emitted
|
||||
// once per transaction and those that can be emitted on a call basis, so possibly
|
||||
// multiple times per transaction.
|
||||
//
|
||||
// They can be recognized easily by their name, those that start with `GasChangeTx` are emitted
|
||||
// once per transaction, while those that start with `GasChangeCall` are emitted on a call basis.
|
||||
// They can be recognized easily by their name, those that start with `GasChangeTx`
|
||||
// are emitted once per transaction, while those that start with `GasChangeCall`
|
||||
// are emitted on a call basis.
|
||||
type GasChangeReason byte
|
||||
|
||||
//go:generate go run golang.org/x/tools/cmd/stringer -type=GasChangeReason -trimprefix=GasChange -output gen_gas_change_reason_stringer.go
|
||||
|
|
@ -307,61 +326,100 @@ type GasChangeReason byte
|
|||
const (
|
||||
GasChangeUnspecified GasChangeReason = 0
|
||||
|
||||
// GasChangeTxInitialBalance is the initial balance for the call which will be equal to the gasLimit of the call. There is only
|
||||
// one such gas change per transaction.
|
||||
// GasChangeTxInitialBalance is the initial balance for the call which will
|
||||
// be equal to the gasLimit of the call. There is only one such gas change
|
||||
// per transaction.
|
||||
GasChangeTxInitialBalance GasChangeReason = 1
|
||||
// GasChangeTxIntrinsicGas is the amount of gas that will be charged for the intrinsic cost of the transaction, there is
|
||||
// always exactly one of those per transaction.
|
||||
|
||||
// GasChangeTxIntrinsicGas is the amount of gas that will be charged for the
|
||||
// intrinsic cost of the transaction, there is always exactly one of those
|
||||
// per transaction.
|
||||
GasChangeTxIntrinsicGas GasChangeReason = 2
|
||||
// GasChangeTxRefunds is the sum of all refunds which happened during the tx execution (e.g. storage slot being cleared)
|
||||
// this generates an increase in gas. There is at most one of such gas change per transaction.
|
||||
|
||||
// GasChangeTxRefunds is the sum of all refunds which happened during the tx
|
||||
// execution (e.g. storage slot being cleared). this generates an increase in
|
||||
// gas. There is at most one of such gas change per transaction.
|
||||
GasChangeTxRefunds GasChangeReason = 3
|
||||
// GasChangeTxLeftOverReturned is the amount of gas left over at the end of transaction's execution that will be returned
|
||||
// to the chain. This change will always be a negative change as we "drain" left over gas towards 0. If there was no gas
|
||||
// left at the end of execution, no such even will be emitted. The returned gas's value in Wei is returned to caller.
|
||||
// There is at most one of such gas change per transaction.
|
||||
|
||||
// GasChangeTxLeftOverReturned is the amount of gas left over at the end of
|
||||
// transaction's execution that will be returned to the chain. This change
|
||||
// will always be a negative change as we "drain" left over gas towards 0.
|
||||
// If there was no gas left at the end of execution, no such even will be
|
||||
// emitted. The returned gas's value in Wei is returned to caller. There is
|
||||
// at most one of such gas change per transaction.
|
||||
GasChangeTxLeftOverReturned GasChangeReason = 4
|
||||
|
||||
// GasChangeCallInitialBalance is the initial balance for the call which will be equal to the gasLimit of the call. There is only
|
||||
// one such gas change per call.
|
||||
// GasChangeCallInitialBalance is the initial balance for the call which
|
||||
// will be equal to the gasLimit of the call. There is only one such gas
|
||||
// change per call.
|
||||
GasChangeCallInitialBalance GasChangeReason = 5
|
||||
// GasChangeCallLeftOverReturned is the amount of gas left over that will be returned to the caller, this change will always
|
||||
// be a negative change as we "drain" left over gas towards 0. If there was no gas left at the end of execution, no such even
|
||||
// will be emitted.
|
||||
|
||||
// GasChangeCallLeftOverReturned is the amount of gas left over that will
|
||||
// be returned to the caller, this change will always be a negative change
|
||||
// as we "drain" left over gas towards 0. If there was no gas left at the
|
||||
// end of execution, no such even will be emitted.
|
||||
GasChangeCallLeftOverReturned GasChangeReason = 6
|
||||
// GasChangeCallLeftOverRefunded is the amount of gas that will be refunded to the call after the child call execution it
|
||||
// executed completed. This value is always positive as we are giving gas back to the you, the left over gas of the child.
|
||||
// If there was no gas left to be refunded, no such even will be emitted.
|
||||
|
||||
// GasChangeCallLeftOverRefunded is the amount of gas that will be refunded
|
||||
// to the call after the child call execution it executed completed. This
|
||||
// value is always positive as we are giving gas back to the you, the left over
|
||||
// gas of the child. If there was no gas left to be refunded, no such event
|
||||
// will be emitted.
|
||||
GasChangeCallLeftOverRefunded GasChangeReason = 7
|
||||
// GasChangeCallContractCreation is the amount of gas that will be burned for a CREATE.
|
||||
|
||||
// GasChangeCallContractCreation is the amount of gas that will be burned
|
||||
// for a CREATE.
|
||||
GasChangeCallContractCreation GasChangeReason = 8
|
||||
// GasChangeCallContractCreation2 is the amount of gas that will be burned for a CREATE2.
|
||||
|
||||
// GasChangeCallContractCreation2 is the amount of gas that will be burned
|
||||
// for a CREATE2.
|
||||
GasChangeCallContractCreation2 GasChangeReason = 9
|
||||
// GasChangeCallCodeStorage is the amount of gas that will be charged for code storage.
|
||||
|
||||
// GasChangeCallCodeStorage is the amount of gas that will be charged for
|
||||
// code storage.
|
||||
GasChangeCallCodeStorage GasChangeReason = 10
|
||||
// GasChangeCallOpCode is the amount of gas that will be charged for an opcode executed by the EVM, exact opcode that was
|
||||
// performed can be check by `OnOpcode` handling.
|
||||
|
||||
// GasChangeCallOpCode is the amount of gas that will be charged for an opcode
|
||||
// executed by the EVM, exact opcode that was performed can be check by
|
||||
// `OnOpcode` handling.
|
||||
GasChangeCallOpCode GasChangeReason = 11
|
||||
// GasChangeCallPrecompiledContract is the amount of gas that will be charged for a precompiled contract execution.
|
||||
|
||||
// GasChangeCallPrecompiledContract is the amount of gas that will be charged
|
||||
// for a precompiled contract execution.
|
||||
GasChangeCallPrecompiledContract GasChangeReason = 12
|
||||
// GasChangeCallStorageColdAccess is the amount of gas that will be charged for a cold storage access as controlled by EIP2929 rules.
|
||||
|
||||
// GasChangeCallStorageColdAccess is the amount of gas that will be charged
|
||||
// for a cold storage access as controlled by EIP2929 rules.
|
||||
GasChangeCallStorageColdAccess GasChangeReason = 13
|
||||
// GasChangeCallFailedExecution is the burning of the remaining gas when the execution failed without a revert.
|
||||
|
||||
// GasChangeCallFailedExecution is the burning of the remaining gas when the
|
||||
// execution failed without a revert.
|
||||
GasChangeCallFailedExecution GasChangeReason = 14
|
||||
// GasChangeWitnessContractInit flags the event of adding to the witness during the contract creation initialization step.
|
||||
|
||||
// GasChangeWitnessContractInit flags the event of adding to the witness
|
||||
// during the contract creation initialization step.
|
||||
GasChangeWitnessContractInit GasChangeReason = 15
|
||||
// GasChangeWitnessContractCreation flags the event of adding to the witness during the contract creation finalization step.
|
||||
|
||||
// GasChangeWitnessContractCreation flags the event of adding to the witness
|
||||
// during the contract creation finalization step.
|
||||
GasChangeWitnessContractCreation GasChangeReason = 16
|
||||
// GasChangeWitnessCodeChunk flags the event of adding one or more contract code chunks to the witness.
|
||||
|
||||
// GasChangeWitnessCodeChunk flags the event of adding one or more contract
|
||||
// code chunks to the witness.
|
||||
GasChangeWitnessCodeChunk GasChangeReason = 17
|
||||
// GasChangeWitnessContractCollisionCheck flags the event of adding to the witness when checking for contract address collision.
|
||||
|
||||
// GasChangeWitnessContractCollisionCheck flags the event of adding to the
|
||||
// witness when checking for contract address collision.
|
||||
GasChangeWitnessContractCollisionCheck GasChangeReason = 18
|
||||
// GasChangeTxDataFloor is the amount of extra gas the transaction has to pay to reach the minimum gas requirement for the
|
||||
// transaction data. This change will always be a negative change.
|
||||
|
||||
// GasChangeTxDataFloor is the amount of extra gas the transaction has to
|
||||
// pay to reach the minimum gas requirement for the transaction data.
|
||||
// This change will always be a negative change.
|
||||
GasChangeTxDataFloor GasChangeReason = 19
|
||||
|
||||
// GasChangeIgnored is a special value that can be used to indicate that the gas change should be ignored as
|
||||
// it will be "manually" tracked by a direct emit of the gas change event.
|
||||
// GasChangeIgnored is a special value that can be used to indicate that
|
||||
// the gas change should be ignored as it will be "manually" tracked by
|
||||
// a direct emit of the gas change event.
|
||||
GasChangeIgnored GasChangeReason = 0xFF
|
||||
)
|
||||
|
||||
|
|
@ -385,11 +443,12 @@ const (
|
|||
// NonceChangeNewContract is the nonce change of a newly created contract.
|
||||
NonceChangeNewContract NonceChangeReason = 4
|
||||
|
||||
// NonceChangeTransaction is the nonce change due to a EIP-7702 authorization.
|
||||
// NonceChangeAuthorization is the nonce change due to a EIP-7702 authorization.
|
||||
NonceChangeAuthorization NonceChangeReason = 5
|
||||
|
||||
// NonceChangeRevert is emitted when the nonce is reverted back to a previous value due to call failure.
|
||||
// It is only emitted when the tracer has opted in to use the journaling wrapper (WrapWithJournal).
|
||||
// NonceChangeRevert is emitted when the nonce is reverted back to a previous
|
||||
// value due to call failure. It is only emitted when the tracer has opted in
|
||||
// to use the journaling wrapper (WrapWithJournal).
|
||||
NonceChangeRevert NonceChangeReason = 6
|
||||
|
||||
// NonceChangeSelfdestruct is emitted when the nonce is reset to zero due to a self-destruct
|
||||
|
|
@ -404,22 +463,26 @@ type CodeChangeReason byte
|
|||
const (
|
||||
CodeChangeUnspecified CodeChangeReason = 0
|
||||
|
||||
// CodeChangeContractCreation is when a new contract is deployed via CREATE/CREATE2 operations.
|
||||
// CodeChangeContractCreation is when a new contract is deployed via
|
||||
// CREATE/CREATE2 operations.
|
||||
CodeChangeContractCreation CodeChangeReason = 1
|
||||
|
||||
// CodeChangeGenesis is when contract code is set during blockchain genesis or initial setup.
|
||||
// CodeChangeGenesis is when contract code is set during blockchain genesis
|
||||
// or initial setup.
|
||||
CodeChangeGenesis CodeChangeReason = 2
|
||||
|
||||
// CodeChangeAuthorization is when code is set via EIP-7702 Set Code Authorization.
|
||||
CodeChangeAuthorization CodeChangeReason = 3
|
||||
|
||||
// CodeChangeAuthorizationClear is when EIP-7702 delegation is cleared by setting to zero address.
|
||||
// CodeChangeAuthorizationClear is when EIP-7702 delegation is cleared by
|
||||
// setting to zero address.
|
||||
CodeChangeAuthorizationClear CodeChangeReason = 4
|
||||
|
||||
// CodeChangeSelfDestruct is when contract code is cleared due to self-destruct.
|
||||
CodeChangeSelfDestruct CodeChangeReason = 5
|
||||
|
||||
// CodeChangeRevert is emitted when the code is reverted back to a previous value due to call failure.
|
||||
// It is only emitted when the tracer has opted in to use the journaling wrapper (WrapWithJournal).
|
||||
// CodeChangeRevert is emitted when the code is reverted back to a previous
|
||||
// value due to call failure. It is only emitted when the tracer has opted
|
||||
// in to use the journaling wrapper (WrapWithJournal).
|
||||
CodeChangeRevert CodeChangeReason = 6
|
||||
)
|
||||
|
|
|
|||
|
|
@ -42,7 +42,9 @@ func WrapWithJournal(hooks *Hooks) (*Hooks, error) {
|
|||
return nil, errors.New("wrapping nil tracer")
|
||||
}
|
||||
// No state change to journal, return the wrapped hooks as is
|
||||
if hooks.OnBalanceChange == nil && hooks.OnNonceChange == nil && hooks.OnNonceChangeV2 == nil && hooks.OnCodeChange == nil && hooks.OnCodeChangeV2 == nil && hooks.OnStorageChange == nil {
|
||||
if hooks.OnBalanceChange == nil && hooks.OnNonceChange == nil && hooks.OnNonceChangeV2 == nil &&
|
||||
hooks.OnCodeChange == nil && hooks.OnCodeChangeV2 == nil && hooks.OnStorageChange == nil {
|
||||
// TODO(sina) hooks.OnLog should also be handled here
|
||||
return hooks, nil
|
||||
}
|
||||
if hooks.OnNonceChange != nil && hooks.OnNonceChangeV2 != nil {
|
||||
|
|
@ -56,11 +58,14 @@ func WrapWithJournal(hooks *Hooks) (*Hooks, error) {
|
|||
wrapped := *hooks
|
||||
|
||||
// Create journal
|
||||
j := &journal{hooks: hooks}
|
||||
j := &journal{
|
||||
hooks: hooks,
|
||||
}
|
||||
// Scope hooks need to be re-implemented.
|
||||
wrapped.OnTxEnd = j.OnTxEnd
|
||||
wrapped.OnEnter = j.OnEnter
|
||||
wrapped.OnExit = j.OnExit
|
||||
|
||||
// Wrap state change hooks.
|
||||
if hooks.OnBalanceChange != nil {
|
||||
wrapped.OnBalanceChange = j.OnBalanceChange
|
||||
|
|
@ -69,6 +74,7 @@ func WrapWithJournal(hooks *Hooks) (*Hooks, error) {
|
|||
// Regardless of which hook version is used in the tracer,
|
||||
// the journal will want to capture the nonce change reason.
|
||||
wrapped.OnNonceChangeV2 = j.OnNonceChangeV2
|
||||
|
||||
// A precaution to ensure EVM doesn't call both hooks.
|
||||
wrapped.OnNonceChange = nil
|
||||
}
|
||||
|
|
@ -81,7 +87,6 @@ func WrapWithJournal(hooks *Hooks) (*Hooks, error) {
|
|||
if hooks.OnStorageChange != nil {
|
||||
wrapped.OnStorageChange = j.OnStorageChange
|
||||
}
|
||||
|
||||
return &wrapped, nil
|
||||
}
|
||||
|
||||
|
|
@ -160,7 +165,11 @@ func (j *journal) OnColdAccountLoad(address common.Address) {
|
|||
}
|
||||
|
||||
func (j *journal) OnBalanceChange(addr common.Address, prev, new *big.Int, reason BalanceChangeReason) {
|
||||
j.entries = append(j.entries, balanceChange{addr: addr, prev: prev, new: new})
|
||||
j.entries = append(j.entries, balanceChange{
|
||||
addr: addr,
|
||||
prev: prev,
|
||||
new: new,
|
||||
})
|
||||
if j.hooks.OnBalanceChange != nil {
|
||||
j.hooks.OnBalanceChange(addr, prev, new, reason)
|
||||
}
|
||||
|
|
@ -170,7 +179,11 @@ func (j *journal) OnNonceChangeV2(addr common.Address, prev, new uint64, reason
|
|||
// When a contract is created, the nonce of the creator is incremented.
|
||||
// This change is not reverted when the creation fails.
|
||||
if reason != NonceChangeContractCreator {
|
||||
j.entries = append(j.entries, nonceChange{addr: addr, prev: prev, new: new})
|
||||
j.entries = append(j.entries, nonceChange{
|
||||
addr: addr,
|
||||
prev: prev,
|
||||
new: new,
|
||||
})
|
||||
}
|
||||
if j.hooks.OnNonceChangeV2 != nil {
|
||||
j.hooks.OnNonceChangeV2(addr, prev, new, reason)
|
||||
|
|
@ -206,7 +219,12 @@ func (j *journal) OnCodeChangeV2(addr common.Address, prevCodeHash common.Hash,
|
|||
}
|
||||
|
||||
func (j *journal) OnStorageChange(addr common.Address, slot common.Hash, prev, new common.Hash) {
|
||||
j.entries = append(j.entries, storageChange{addr: addr, slot: slot, prev: prev, new: new})
|
||||
j.entries = append(j.entries, storageChange{
|
||||
addr: addr,
|
||||
slot: slot,
|
||||
prev: prev,
|
||||
new: new,
|
||||
})
|
||||
if j.hooks.OnStorageChange != nil {
|
||||
j.hooks.OnStorageChange(addr, slot, prev, new)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue