From 60a27092957ed10cf0043034b619b889cb79be70 Mon Sep 17 00:00:00 2001 From: Rachel Franks Date: Sun, 23 Jan 2022 00:32:11 -0600 Subject: [PATCH 1/8] Add Type field to ArbitrumInternalTx --- core/types/arb_types.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/types/arb_types.go b/core/types/arb_types.go index 16accb8bd4db..fc5d632e8e65 100644 --- a/core/types/arb_types.go +++ b/core/types/arb_types.go @@ -310,6 +310,7 @@ func (d *ArbitrumDepositTx) setSignatureValues(chainID, v, r, s *big.Int) { type ArbitrumInternalTx struct { ChainId *big.Int + Type uint8 Data []byte BlockNumber uint64 TxIndex uint64 @@ -322,6 +323,7 @@ func (t *ArbitrumInternalTx) txType() byte { func (t *ArbitrumInternalTx) copy() TxData { return &ArbitrumInternalTx{ new(big.Int).Set(t.ChainId), + t.Type, common.CopyBytes(t.Data), t.BlockNumber, t.TxIndex, From ba0f0f7d2b1f0cb99bf885f38d3c9747e7163dff Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Mon, 31 Jan 2022 10:37:14 -0600 Subject: [PATCH 2/8] Fix selfdestruct balance tracking by expecting balance burn --- core/state/statedb.go | 7 +++++++ core/vm/instructions.go | 10 ++++++++-- core/vm/interface.go | 1 + 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/core/state/statedb.go b/core/state/statedb.go index a6c0cb1bd519..51531b4c6aad 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -409,6 +409,13 @@ func (s *StateDB) SetBalance(addr common.Address, amount *big.Int) { } } +func (s *StateDB) ExpectBalanceBurn(amount *big.Int) { + if amount.Sign() < 0 { + panic(fmt.Sprintf("ExpectBalanceBurn called with negative amount %v", amount)) + } + s.totalBalanceDelta.Add(s.totalBalanceDelta, amount) +} + func (s *StateDB) SetNonce(addr common.Address, nonce uint64) { stateObject := s.GetOrNewStateObject(addr) if stateObject != nil { diff --git a/core/vm/instructions.go b/core/vm/instructions.go index 5da8d0ab50c5..769e0913eeca 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -17,12 +17,13 @@ package vm import ( + "math/big" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/params" "github.com/holiman/uint256" "golang.org/x/crypto/sha3" - "math/big" ) func opAdd(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { @@ -798,7 +799,12 @@ func opStop(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byt func opSuicide(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { beneficiary := scope.Stack.pop() balance := interpreter.evm.StateDB.GetBalance(scope.Contract.Address()) - interpreter.evm.StateDB.AddBalance(beneficiary.Bytes20(), balance) + if beneficiary.Bytes20() == scope.Contract.Address() { + // Arbitrum: calling selfdestruct(this) burns the balance + interpreter.evm.StateDB.ExpectBalanceBurn(balance) + } else { + interpreter.evm.StateDB.AddBalance(beneficiary.Bytes20(), balance) + } interpreter.evm.StateDB.Suicide(scope.Contract.Address()) if interpreter.cfg.Debug { interpreter.cfg.Tracer.CaptureEnter(SELFDESTRUCT, scope.Contract.Address(), beneficiary.Bytes20(), []byte{}, 0, balance) diff --git a/core/vm/interface.go b/core/vm/interface.go index ad9b05d666a8..1bd001e0cac7 100644 --- a/core/vm/interface.go +++ b/core/vm/interface.go @@ -30,6 +30,7 @@ type StateDB interface { SubBalance(common.Address, *big.Int) AddBalance(common.Address, *big.Int) GetBalance(common.Address) *big.Int + ExpectBalanceBurn(*big.Int) GetNonce(common.Address) uint64 SetNonce(common.Address, uint64) From 6cdef3a4b6dc4282b7b304a5155a45ab2d80e1b6 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 1 Feb 2022 10:40:05 -0600 Subject: [PATCH 3/8] Always call AddBalance --- core/vm/instructions.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/core/vm/instructions.go b/core/vm/instructions.go index 769e0913eeca..637c7d3c682c 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -799,13 +799,12 @@ func opStop(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byt func opSuicide(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { beneficiary := scope.Stack.pop() balance := interpreter.evm.StateDB.GetBalance(scope.Contract.Address()) + interpreter.evm.StateDB.AddBalance(beneficiary.Bytes20(), balance) + interpreter.evm.StateDB.Suicide(scope.Contract.Address()) if beneficiary.Bytes20() == scope.Contract.Address() { // Arbitrum: calling selfdestruct(this) burns the balance interpreter.evm.StateDB.ExpectBalanceBurn(balance) - } else { - interpreter.evm.StateDB.AddBalance(beneficiary.Bytes20(), balance) } - interpreter.evm.StateDB.Suicide(scope.Contract.Address()) if interpreter.cfg.Debug { interpreter.cfg.Tracer.CaptureEnter(SELFDESTRUCT, scope.Contract.Address(), beneficiary.Bytes20(), []byte{}, 0, balance) interpreter.cfg.Tracer.CaptureExit([]byte{}, 0, nil) From 25a3b9cc889af8ea6da10c36883bfcae0ddcf4c2 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Mon, 14 Feb 2022 13:20:02 -0600 Subject: [PATCH 4/8] Rename totalBalanceDelta to unexpectedBalanceDelta --- core/state/statedb.go | 55 ++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/core/state/statedb.go b/core/state/statedb.go index 51531b4c6aad..26b4633a9ff3 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -39,7 +39,7 @@ type revision struct { id int journalIndex int // Arbitrum: track the total balance change across all accounts - totalBalanceDelta *big.Int + unexpectedBalanceDelta *big.Int } var ( @@ -65,7 +65,7 @@ func (n *proofList) Delete(key []byte) error { // * Accounts type StateDB struct { // Arbitrum: track the total balance change across all accounts - totalBalanceDelta *big.Int + unexpectedBalanceDelta *big.Int db Database prefetcher *triePrefetcher @@ -136,7 +136,8 @@ func New(root common.Hash, db Database, snaps *snapshot.Tree) (*StateDB, error) return nil, err } sdb := &StateDB{ - totalBalanceDelta: new(big.Int), + unexpectedBalanceDelta: new(big.Int), + db: db, trie: tr, originalRoot: root, @@ -384,7 +385,7 @@ func (s *StateDB) HasSuicided(addr common.Address) bool { func (s *StateDB) AddBalance(addr common.Address, amount *big.Int) { stateObject := s.GetOrNewStateObject(addr) if stateObject != nil { - s.totalBalanceDelta.Add(s.totalBalanceDelta, amount) + s.unexpectedBalanceDelta.Add(s.unexpectedBalanceDelta, amount) stateObject.AddBalance(amount) } } @@ -393,7 +394,7 @@ func (s *StateDB) AddBalance(addr common.Address, amount *big.Int) { func (s *StateDB) SubBalance(addr common.Address, amount *big.Int) { stateObject := s.GetOrNewStateObject(addr) if stateObject != nil { - s.totalBalanceDelta.Sub(s.totalBalanceDelta, amount) + s.unexpectedBalanceDelta.Sub(s.unexpectedBalanceDelta, amount) stateObject.SubBalance(amount) } } @@ -402,8 +403,8 @@ func (s *StateDB) SetBalance(addr common.Address, amount *big.Int) { stateObject := s.GetOrNewStateObject(addr) if stateObject != nil { prevBalance := stateObject.Balance() - s.totalBalanceDelta.Add(s.totalBalanceDelta, amount) - s.totalBalanceDelta.Sub(s.totalBalanceDelta, prevBalance) + s.unexpectedBalanceDelta.Add(s.unexpectedBalanceDelta, amount) + s.unexpectedBalanceDelta.Sub(s.unexpectedBalanceDelta, prevBalance) stateObject.SetBalance(amount) } @@ -413,7 +414,7 @@ func (s *StateDB) ExpectBalanceBurn(amount *big.Int) { if amount.Sign() < 0 { panic(fmt.Sprintf("ExpectBalanceBurn called with negative amount %v", amount)) } - s.totalBalanceDelta.Add(s.totalBalanceDelta, amount) + s.unexpectedBalanceDelta.Add(s.unexpectedBalanceDelta, amount) } func (s *StateDB) SetNonce(addr common.Address, nonce uint64) { @@ -462,7 +463,7 @@ func (s *StateDB) Suicide(addr common.Address) bool { prevbalance: new(big.Int).Set(stateObject.Balance()), }) stateObject.markSuicided() - s.totalBalanceDelta.Sub(s.totalBalanceDelta, stateObject.data.Balance) + s.unexpectedBalanceDelta.Sub(s.unexpectedBalanceDelta, stateObject.data.Balance) stateObject.data.Balance = new(big.Int) return true @@ -667,18 +668,18 @@ func (db *StateDB) ForEachStorage(addr common.Address, cb func(key, value common func (s *StateDB) Copy() *StateDB { // Copy all the basic fields, initialize the memory ones state := &StateDB{ - totalBalanceDelta: new(big.Int).Set(s.totalBalanceDelta), - db: s.db, - trie: s.db.CopyTrie(s.trie), - stateObjects: make(map[common.Address]*stateObject, len(s.journal.dirties)), - stateObjectsPending: make(map[common.Address]struct{}, len(s.stateObjectsPending)), - stateObjectsDirty: make(map[common.Address]struct{}, len(s.journal.dirties)), - refund: s.refund, - logs: make(map[common.Hash][]*types.Log, len(s.logs)), - logSize: s.logSize, - preimages: make(map[common.Hash][]byte, len(s.preimages)), - journal: newJournal(), - hasher: crypto.NewKeccakState(), + unexpectedBalanceDelta: new(big.Int).Set(s.unexpectedBalanceDelta), + db: s.db, + trie: s.db.CopyTrie(s.trie), + stateObjects: make(map[common.Address]*stateObject, len(s.journal.dirties)), + stateObjectsPending: make(map[common.Address]struct{}, len(s.stateObjectsPending)), + stateObjectsDirty: make(map[common.Address]struct{}, len(s.journal.dirties)), + refund: s.refund, + logs: make(map[common.Hash][]*types.Log, len(s.logs)), + logSize: s.logSize, + preimages: make(map[common.Hash][]byte, len(s.preimages)), + journal: newJournal(), + hasher: crypto.NewKeccakState(), } // Copy the dirty states, logs, and preimages for addr := range s.journal.dirties { @@ -767,7 +768,7 @@ func (s *StateDB) Copy() *StateDB { func (s *StateDB) Snapshot() int { id := s.nextRevisionId s.nextRevisionId++ - s.validRevisions = append(s.validRevisions, revision{id, s.journal.length(), new(big.Int).Set(s.totalBalanceDelta)}) + s.validRevisions = append(s.validRevisions, revision{id, s.journal.length(), new(big.Int).Set(s.unexpectedBalanceDelta)}) return id } @@ -782,7 +783,7 @@ func (s *StateDB) RevertToSnapshot(revid int) { } revision := s.validRevisions[idx] snapshot := revision.journalIndex - s.totalBalanceDelta = new(big.Int).Set(revision.totalBalanceDelta) + s.unexpectedBalanceDelta = new(big.Int).Set(revision.unexpectedBalanceDelta) // Replay the journal to undo changes and remove invalidated snapshots s.journal.revert(s, snapshot) @@ -794,9 +795,9 @@ func (s *StateDB) GetRefund() uint64 { return s.refund } -// GetTotalBalanceDelta returns the total change in balances since the last commit to the database -func (s *StateDB) GetTotalBalanceDelta() *big.Int { - return new(big.Int).Set(s.totalBalanceDelta) +// GetUnexpectedBalanceDelta returns the total unexpected change in balances since the last commit to the database. +func (s *StateDB) GetUnexpectedBalanceDelta() *big.Int { + return new(big.Int).Set(s.unexpectedBalanceDelta) } // Finalise finalises the state by removing the s destructed objects and clears @@ -1011,7 +1012,7 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) { s.snap, s.snapDestructs, s.snapAccounts, s.snapStorage = nil, nil, nil, nil } if err == nil { - s.totalBalanceDelta.Set(new(big.Int)) + s.unexpectedBalanceDelta.Set(new(big.Int)) } return root, err } From ce0ee4c66a2ceacbff3a7b501d678ef8b2d19556 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Mon, 14 Feb 2022 17:31:39 -0600 Subject: [PATCH 5/8] Add newline to minimize diff --- core/state/statedb.go | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/core/state/statedb.go b/core/state/statedb.go index 26b4633a9ff3..e1e13a2a72cc 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -669,17 +669,18 @@ func (s *StateDB) Copy() *StateDB { // Copy all the basic fields, initialize the memory ones state := &StateDB{ unexpectedBalanceDelta: new(big.Int).Set(s.unexpectedBalanceDelta), - db: s.db, - trie: s.db.CopyTrie(s.trie), - stateObjects: make(map[common.Address]*stateObject, len(s.journal.dirties)), - stateObjectsPending: make(map[common.Address]struct{}, len(s.stateObjectsPending)), - stateObjectsDirty: make(map[common.Address]struct{}, len(s.journal.dirties)), - refund: s.refund, - logs: make(map[common.Hash][]*types.Log, len(s.logs)), - logSize: s.logSize, - preimages: make(map[common.Hash][]byte, len(s.preimages)), - journal: newJournal(), - hasher: crypto.NewKeccakState(), + + db: s.db, + trie: s.db.CopyTrie(s.trie), + stateObjects: make(map[common.Address]*stateObject, len(s.journal.dirties)), + stateObjectsPending: make(map[common.Address]struct{}, len(s.stateObjectsPending)), + stateObjectsDirty: make(map[common.Address]struct{}, len(s.journal.dirties)), + refund: s.refund, + logs: make(map[common.Hash][]*types.Log, len(s.logs)), + logSize: s.logSize, + preimages: make(map[common.Hash][]byte, len(s.preimages)), + journal: newJournal(), + hasher: crypto.NewKeccakState(), } // Copy the dirty states, logs, and preimages for addr := range s.journal.dirties { From 86de72bf992632b28aa32dd286e61ce909025e20 Mon Sep 17 00:00:00 2001 From: Rachel Franks Date: Thu, 17 Feb 2022 21:42:29 -0600 Subject: [PATCH 6/8] remove UnderlyingTx --- core/state_transition.go | 5 +++-- core/types/arb_types.go | 13 ------------- core/types/transaction.go | 18 ++---------------- core/vm/evm_arbitrum.go | 6 ++++-- 4 files changed, 9 insertions(+), 33 deletions(-) diff --git a/core/state_transition.go b/core/state_transition.go index efd8e9995bc6..0432665b6f40 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -294,7 +294,8 @@ func (st *StateTransition) transitionDbImpl() (*ExecutionResult, error) { // 5. there is no overflow when calculating intrinsic gas // 6. caller has enough balance to cover asset transfer for **topmost** call - // There are no tips in L2 + // In L2, ArbOS decides what to do with the tip. Most users shouldn't set one. + txGasPrice := st.gasPrice if st.evm.ChainConfig().IsArbitrum() && st.gasPrice.Cmp(st.evm.Context.BaseFee) > 0 { st.gasPrice = st.evm.Context.BaseFee } @@ -320,7 +321,7 @@ func (st *StateTransition) transitionDbImpl() (*ExecutionResult, error) { } st.gas -= gas - err = st.evm.ProcessingHook.GasChargingHook(&st.gas) + err = st.evm.ProcessingHook.GasChargingHook(&st.gas, txGasPrice) if err != nil { return nil, err } diff --git a/core/types/arb_types.go b/core/types/arb_types.go index fc5d632e8e65..d730aef0c430 100644 --- a/core/types/arb_types.go +++ b/core/types/arb_types.go @@ -349,16 +349,3 @@ func (d *ArbitrumInternalTx) rawSignatureValues() (v, r, s *big.Int) { func (d *ArbitrumInternalTx) setSignatureValues(chainID, v, r, s *big.Int) { } - -type ArbitrumWrappedTx struct { - l1Calldata uint64 - TxData -} - -func (tx *ArbitrumWrappedTx) copy() TxData { - cpy := &ArbitrumWrappedTx{ - l1Calldata: tx.l1Calldata, - TxData: tx.TxData.copy(), - } - return cpy -} diff --git a/core/types/transaction.go b/core/types/transaction.go index d812296bb612..711cd55d8397 100644 --- a/core/types/transaction.go +++ b/core/types/transaction.go @@ -48,7 +48,6 @@ const ( ArbitrumDepositTxType = 100 ArbitrumUnsignedTxType = 101 ArbitrumContractTxType = 102 - ArbitrumWrappedTxType = 103 ArbitrumRetryTxType = 104 ArbitrumSubmitRetryableTxType = 105 ArbitrumInternalTxType = 106 @@ -99,7 +98,7 @@ type TxData interface { // EncodeRLP implements rlp.Encoder func (tx *Transaction) EncodeRLP(w io.Writer) error { - if tx.realType() == LegacyTxType { + if tx.Type() == LegacyTxType { return rlp.Encode(w, tx.inner) } // It's an EIP-2718 typed TX envelope. @@ -114,7 +113,7 @@ func (tx *Transaction) EncodeRLP(w io.Writer) error { // encodeTyped writes the canonical encoding of a typed transaction to w. func (tx *Transaction) encodeTyped(w *bytes.Buffer) error { - w.WriteByte(tx.realType()) + w.WriteByte(tx.Type()) return rlp.Encode(w, tx.inner) } @@ -205,10 +204,6 @@ func (tx *Transaction) decodeTyped(b []byte, arbParsing bool) (TxData, error) { var inner ArbitrumContractTx err := rlp.DecodeBytes(b[1:], &inner) return &inner, err - case ArbitrumWrappedTxType: - var inner ArbitrumWrappedTx - err := rlp.DecodeBytes(b[1:], &inner) - return &inner, err case ArbitrumRetryTxType: var inner ArbitrumRetryTx err := rlp.DecodeBytes(b[1:], &inner) @@ -296,15 +291,6 @@ func (tx *Transaction) Type() uint8 { return tx.inner.txType() } -func (tx *Transaction) realType() uint8 { - _, isArbWrapped := tx.inner.(*ArbitrumWrappedTx) - if isArbWrapped { - return ArbitrumWrappedTxType - } else { - return tx.Type() - } -} - func (tx *Transaction) GetInner() TxData { return tx.inner.copy() } diff --git a/core/vm/evm_arbitrum.go b/core/vm/evm_arbitrum.go index 11a7a6890cc3..1da53813ac00 100644 --- a/core/vm/evm_arbitrum.go +++ b/core/vm/evm_arbitrum.go @@ -17,6 +17,8 @@ package vm import ( + "math/big" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" ) @@ -28,7 +30,7 @@ func (evm *EVM) Depth() int { type TxProcessingHook interface { StartTxHook() (bool, uint64, error, []byte) // return 4-tuple rather than *struct to avoid an import cycle - GasChargingHook(gasRemaining *uint64) error + GasChargingHook(gasRemaining *uint64, txGasPrice *big.Int) error PushCaller(addr common.Address) PopCaller() ForceRefundGas() uint64 @@ -45,7 +47,7 @@ func (p DefaultTxProcessor) StartTxHook() (bool, uint64, error, []byte) { return false, 0, nil, nil } -func (p DefaultTxProcessor) GasChargingHook(gasRemaining *uint64) error { +func (p DefaultTxProcessor) GasChargingHook(gasRemaining *uint64, txGasPrice *big.Int) error { return nil } From b0f9c1b40f48c3c6a121df6a3e7523c02674a418 Mon Sep 17 00:00:00 2001 From: Rachel Franks Date: Mon, 21 Feb 2022 17:07:16 -0600 Subject: [PATCH 7/8] remove gasprice overwrite --- core/state_transition.go | 8 +------- core/vm/evm_arbitrum.go | 6 ++---- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/core/state_transition.go b/core/state_transition.go index 0432665b6f40..929b4b3a19c2 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -294,12 +294,6 @@ func (st *StateTransition) transitionDbImpl() (*ExecutionResult, error) { // 5. there is no overflow when calculating intrinsic gas // 6. caller has enough balance to cover asset transfer for **topmost** call - // In L2, ArbOS decides what to do with the tip. Most users shouldn't set one. - txGasPrice := st.gasPrice - if st.evm.ChainConfig().IsArbitrum() && st.gasPrice.Cmp(st.evm.Context.BaseFee) > 0 { - st.gasPrice = st.evm.Context.BaseFee - } - // Check clauses 1-3, buy gas if everything is correct if err := st.preCheck(); err != nil { return nil, err @@ -321,7 +315,7 @@ func (st *StateTransition) transitionDbImpl() (*ExecutionResult, error) { } st.gas -= gas - err = st.evm.ProcessingHook.GasChargingHook(&st.gas, txGasPrice) + err = st.evm.ProcessingHook.GasChargingHook(&st.gas) if err != nil { return nil, err } diff --git a/core/vm/evm_arbitrum.go b/core/vm/evm_arbitrum.go index 1da53813ac00..11a7a6890cc3 100644 --- a/core/vm/evm_arbitrum.go +++ b/core/vm/evm_arbitrum.go @@ -17,8 +17,6 @@ package vm import ( - "math/big" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" ) @@ -30,7 +28,7 @@ func (evm *EVM) Depth() int { type TxProcessingHook interface { StartTxHook() (bool, uint64, error, []byte) // return 4-tuple rather than *struct to avoid an import cycle - GasChargingHook(gasRemaining *uint64, txGasPrice *big.Int) error + GasChargingHook(gasRemaining *uint64) error PushCaller(addr common.Address) PopCaller() ForceRefundGas() uint64 @@ -47,7 +45,7 @@ func (p DefaultTxProcessor) StartTxHook() (bool, uint64, error, []byte) { return false, 0, nil, nil } -func (p DefaultTxProcessor) GasChargingHook(gasRemaining *uint64, txGasPrice *big.Int) error { +func (p DefaultTxProcessor) GasChargingHook(gasRemaining *uint64) error { return nil } From 555c97f09df86bc0ca3bfdfc1c96c1f8f91fde4f Mon Sep 17 00:00:00 2001 From: Rachel Franks Date: Mon, 21 Feb 2022 22:05:19 -0600 Subject: [PATCH 8/8] let GasChargingHook() decide the tip recipient --- core/state_transition.go | 7 +++++-- core/vm/evm_arbitrum.go | 6 +++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/core/state_transition.go b/core/state_transition.go index 929b4b3a19c2..47903e657b65 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -315,7 +315,7 @@ func (st *StateTransition) transitionDbImpl() (*ExecutionResult, error) { } st.gas -= gas - err = st.evm.ProcessingHook.GasChargingHook(&st.gas) + tipRecipient, err := st.evm.ProcessingHook.GasChargingHook(&st.gas) if err != nil { return nil, err } @@ -352,7 +352,10 @@ func (st *StateTransition) transitionDbImpl() (*ExecutionResult, error) { if london { effectiveTip = cmath.BigMin(st.gasTipCap, new(big.Int).Sub(st.gasFeeCap, st.evm.Context.BaseFee)) } - st.state.AddBalance(st.evm.Context.Coinbase, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), effectiveTip)) + if tipRecipient == nil { + tipRecipient = &st.evm.Context.Coinbase + } + st.state.AddBalance(*tipRecipient, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), effectiveTip)) return &ExecutionResult{ UsedGas: st.gasUsed(), diff --git a/core/vm/evm_arbitrum.go b/core/vm/evm_arbitrum.go index 11a7a6890cc3..d5943bd20667 100644 --- a/core/vm/evm_arbitrum.go +++ b/core/vm/evm_arbitrum.go @@ -28,7 +28,7 @@ func (evm *EVM) Depth() int { type TxProcessingHook interface { StartTxHook() (bool, uint64, error, []byte) // return 4-tuple rather than *struct to avoid an import cycle - GasChargingHook(gasRemaining *uint64) error + GasChargingHook(gasRemaining *uint64) (*common.Address, error) PushCaller(addr common.Address) PopCaller() ForceRefundGas() uint64 @@ -45,8 +45,8 @@ func (p DefaultTxProcessor) StartTxHook() (bool, uint64, error, []byte) { return false, 0, nil, nil } -func (p DefaultTxProcessor) GasChargingHook(gasRemaining *uint64) error { - return nil +func (p DefaultTxProcessor) GasChargingHook(gasRemaining *uint64) (*common.Address, error) { + return nil, nil } func (p DefaultTxProcessor) PushCaller(addr common.Address) {