From 69478f7df5bcdf2b62d337ba967156372580f83b Mon Sep 17 00:00:00 2001 From: Rachel Bousfield Date: Sat, 5 Aug 2023 13:31:05 -0600 Subject: [PATCH 1/2] PushCaller => PushContract with stylus info --- core/vm/evm_arbitrum.go | 8 ++++---- core/vm/interpreter.go | 9 ++++++--- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/core/vm/evm_arbitrum.go b/core/vm/evm_arbitrum.go index a4a7bd84e6d5..7fc6646de839 100644 --- a/core/vm/evm_arbitrum.go +++ b/core/vm/evm_arbitrum.go @@ -40,8 +40,8 @@ func (evm *EVM) DecrementDepth() { type TxProcessingHook interface { StartTxHook() (bool, uint64, error, []byte) // return 4-tuple rather than *struct to avoid an import cycle GasChargingHook(gasRemaining *uint64) (common.Address, error) - PushCaller(addr common.Address) - PopCaller() + PushContract(contract *Contract, stylus bool) + PopContract(stylus bool) ForceRefundGas() uint64 NonrefundableGas() uint64 DropTip() bool @@ -67,9 +67,9 @@ func (p DefaultTxProcessor) GasChargingHook(gasRemaining *uint64) (common.Addres return p.evm.Context.Coinbase, nil } -func (p DefaultTxProcessor) PushCaller(addr common.Address) {} +func (p DefaultTxProcessor) PushContract(contract *Contract, stylus bool) {} -func (p DefaultTxProcessor) PopCaller() {} +func (p DefaultTxProcessor) PopContract(stylus bool) {} func (p DefaultTxProcessor) ForceRefundGas() uint64 { return 0 } diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go index 58fb64353352..a1ac1f4ed3e2 100644 --- a/core/vm/interpreter.go +++ b/core/vm/interpreter.go @@ -105,11 +105,14 @@ func NewEVMInterpreter(evm *EVM) *EVMInterpreter { // considered a revert-and-consume-all-gas operation except for // ErrExecutionReverted which means revert-and-keep-gas-left. func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (ret []byte, err error) { + // Arbitrum: detect Stylus program + stylus := in.evm.chainRules.IsArbitrum && state.IsStylusProgram(contract.Code) + // Increment the call depth which is restricted to 1024 in.evm.depth++ - in.evm.ProcessingHook.PushCaller(contract.Caller()) + in.evm.ProcessingHook.PushContract(contract, stylus) defer func() { in.evm.depth-- }() - defer func() { in.evm.ProcessingHook.PopCaller() }() + defer func() { in.evm.ProcessingHook.PopContract(stylus) }() // Make sure the readOnly is only set if we aren't in readOnly yet. // This also makes sure that the readOnly flag isn't removed for child calls. @@ -168,7 +171,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( } // Arbitrum: handle Stylus programs - if in.evm.chainRules.IsArbitrum && state.IsStylusProgram(contract.Code) { + if stylus { ret, err = in.evm.ProcessingHook.ExecuteWASM(callContext, input, in) return } From 10b47292983b7ed11a6068729b1e38ab2bbe3d2e Mon Sep 17 00:00:00 2001 From: Rachel Bousfield Date: Sat, 5 Aug 2023 16:41:52 -0600 Subject: [PATCH 2/2] track delegatecall and callcode in Contract's --- core/vm/contract.go | 3 +++ core/vm/contract_arbitrum.go | 4 ++++ core/vm/evm.go | 8 ++++++++ core/vm/evm_arbitrum.go | 8 ++++---- core/vm/interpreter.go | 9 +++------ 5 files changed, 22 insertions(+), 10 deletions(-) diff --git a/core/vm/contract.go b/core/vm/contract.go index bb0902969ec7..4bec38f824ef 100644 --- a/core/vm/contract.go +++ b/core/vm/contract.go @@ -50,6 +50,9 @@ type Contract struct { caller ContractRef self ContractRef + // Arbitrum + delegateOrCallcode bool + jumpdests map[common.Hash]bitvec // Aggregated result of JUMPDEST analysis. analysis bitvec // Locally cached result of JUMPDEST analysis diff --git a/core/vm/contract_arbitrum.go b/core/vm/contract_arbitrum.go index 96e60fea114b..fb7bfbb88cab 100644 --- a/core/vm/contract_arbitrum.go +++ b/core/vm/contract_arbitrum.go @@ -24,3 +24,7 @@ func (c *Contract) BurnGas(amount uint64) error { c.Gas -= amount return nil } + +func (c *Contract) IsDelegateOrCallcode() bool { + return c.delegateOrCallcode +} diff --git a/core/vm/evm.go b/core/vm/evm.go index 5f8d82ec275b..df588f164dc9 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -315,6 +315,10 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, // The contract is a scoped environment for this execution context only. contract := NewContract(caller, AccountRef(caller.Address()), value, gas) contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), evm.StateDB.GetCode(addrCopy)) + + // Arbitrum: note the callcode + contract.delegateOrCallcode = true + ret, err = evm.interpreter.Run(contract, input, false) gas = contract.Gas } @@ -368,6 +372,10 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by // Initialise a new contract and make initialise the delegate values contract := NewContract(caller, AccountRef(caller.Address()), nil, gas).AsDelegate() contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), evm.StateDB.GetCode(addrCopy)) + + // Arbitrum: note the delegate call + contract.delegateOrCallcode = true + ret, err = evm.interpreter.Run(contract, input, false) gas = contract.Gas } diff --git a/core/vm/evm_arbitrum.go b/core/vm/evm_arbitrum.go index 7fc6646de839..a77f2a7aa549 100644 --- a/core/vm/evm_arbitrum.go +++ b/core/vm/evm_arbitrum.go @@ -40,8 +40,8 @@ func (evm *EVM) DecrementDepth() { type TxProcessingHook interface { StartTxHook() (bool, uint64, error, []byte) // return 4-tuple rather than *struct to avoid an import cycle GasChargingHook(gasRemaining *uint64) (common.Address, error) - PushContract(contract *Contract, stylus bool) - PopContract(stylus bool) + PushContract(contract *Contract) + PopContract() ForceRefundGas() uint64 NonrefundableGas() uint64 DropTip() bool @@ -67,9 +67,9 @@ func (p DefaultTxProcessor) GasChargingHook(gasRemaining *uint64) (common.Addres return p.evm.Context.Coinbase, nil } -func (p DefaultTxProcessor) PushContract(contract *Contract, stylus bool) {} +func (p DefaultTxProcessor) PushContract(contract *Contract) {} -func (p DefaultTxProcessor) PopContract(stylus bool) {} +func (p DefaultTxProcessor) PopContract() {} func (p DefaultTxProcessor) ForceRefundGas() uint64 { return 0 } diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go index a1ac1f4ed3e2..49a6237c7207 100644 --- a/core/vm/interpreter.go +++ b/core/vm/interpreter.go @@ -105,14 +105,11 @@ func NewEVMInterpreter(evm *EVM) *EVMInterpreter { // considered a revert-and-consume-all-gas operation except for // ErrExecutionReverted which means revert-and-keep-gas-left. func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (ret []byte, err error) { - // Arbitrum: detect Stylus program - stylus := in.evm.chainRules.IsArbitrum && state.IsStylusProgram(contract.Code) - // Increment the call depth which is restricted to 1024 in.evm.depth++ - in.evm.ProcessingHook.PushContract(contract, stylus) + in.evm.ProcessingHook.PushContract(contract) defer func() { in.evm.depth-- }() - defer func() { in.evm.ProcessingHook.PopContract(stylus) }() + defer func() { in.evm.ProcessingHook.PopContract() }() // Make sure the readOnly is only set if we aren't in readOnly yet. // This also makes sure that the readOnly flag isn't removed for child calls. @@ -171,7 +168,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( } // Arbitrum: handle Stylus programs - if stylus { + if in.evm.chainRules.IsArbitrum && state.IsStylusProgram(contract.Code) { ret, err = in.evm.ProcessingHook.ExecuteWASM(callContext, input, in) return }