diff --git a/core/vm/contracts.libevm.go b/core/vm/contracts.libevm.go index 32eb811076b..e615ed545a6 100644 --- a/core/vm/contracts.libevm.go +++ b/core/vm/contracts.libevm.go @@ -94,6 +94,7 @@ func (p statefulPrecompile) Run([]byte) ([]byte, error) { // A PrecompileEnvironment provides information about the context in which a // precompiled contract is being run. type PrecompileEnvironment interface { + ChainConfig() *params.ChainConfig Rules() params.Rules ReadOnly() bool // StateDB will be non-nil i.f.f !ReadOnly(). @@ -121,7 +122,8 @@ type PrecompileEnvironment interface { var _ PrecompileEnvironment = (*evmCallArgs)(nil) -func (args *evmCallArgs) Rules() params.Rules { return args.evm.chainRules } +func (args *evmCallArgs) ChainConfig() *params.ChainConfig { return args.evm.chainConfig } +func (args *evmCallArgs) Rules() params.Rules { return args.evm.chainRules } func (args *evmCallArgs) ReadOnly() bool { if args.readWrite == inheritReadOnly { diff --git a/core/vm/contracts.libevm_test.go b/core/vm/contracts.libevm_test.go index 7950aa91933..b709da7445f 100644 --- a/core/vm/contracts.libevm_test.go +++ b/core/vm/contracts.libevm_test.go @@ -84,6 +84,7 @@ func TestPrecompileOverride(t *testing.T) { } type statefulPrecompileOutput struct { + ChainID *big.Int Caller, Self common.Address StateValue common.Hash ReadOnly bool @@ -127,6 +128,7 @@ func TestNewStatefulPrecompile(t *testing.T) { addrs := env.Addresses() out := &statefulPrecompileOutput{ + ChainID: env.ChainConfig().ChainID, Caller: addrs.Caller, Self: addrs.Self, StateValue: env.ReadOnlyState().GetState(precompile, slot), @@ -153,10 +155,17 @@ func TestNewStatefulPrecompile(t *testing.T) { caller := rng.Address() input := rng.Bytes(8) value := rng.Hash() - - state, evm := ethtest.NewZeroEVM(t, ethtest.WithBlockContext( - core.NewEVMBlockContext(header, nil, rng.AddressPtr()), - )) + chainID := rng.BigUint64() + + state, evm := ethtest.NewZeroEVM( + t, + ethtest.WithBlockContext( + core.NewEVMBlockContext(header, nil, rng.AddressPtr()), + ), + ethtest.WithChainConfig( + ¶ms.ChainConfig{ChainID: chainID}, + ), + ) state.SetState(precompile, slot, value) tests := []struct { @@ -199,6 +208,7 @@ func TestNewStatefulPrecompile(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { wantReturnData := statefulPrecompileOutput{ + ChainID: chainID, Caller: caller, Self: precompile, StateValue: value, diff --git a/libevm/ethtest/evm.go b/libevm/ethtest/evm.go index bf79e64aff1..7bf1a23480c 100644 --- a/libevm/ethtest/evm.go +++ b/libevm/ethtest/evm.go @@ -25,7 +25,7 @@ func NewZeroEVM(tb testing.TB, opts ...EVMOption) (*state.StateDB, *vm.EVM) { sdb, err := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) require.NoError(tb, err, "state.New()") - vm := vm.NewEVM( + args := &evmConstructorArgs{ vm.BlockContext{ CanTransfer: core.CanTransfer, Transfer: core.Transfer, @@ -34,28 +34,49 @@ func NewZeroEVM(tb testing.TB, opts ...EVMOption) (*state.StateDB, *vm.EVM) { sdb, ¶ms.ChainConfig{}, vm.Config{}, - ) + } for _, o := range opts { - o.apply(vm) + o.apply(args) } - return sdb, vm + return sdb, vm.NewEVM( + args.blockContext, + args.txContext, + args.stateDB, + args.chainConfig, + args.config, + ) +} + +type evmConstructorArgs struct { + blockContext vm.BlockContext + txContext vm.TxContext + stateDB vm.StateDB + chainConfig *params.ChainConfig + config vm.Config } // An EVMOption configures the EVM returned by [NewZeroEVM]. type EVMOption interface { - apply(*vm.EVM) + apply(*evmConstructorArgs) } -type funcOption func(*vm.EVM) +type funcOption func(*evmConstructorArgs) var _ EVMOption = funcOption(nil) -func (f funcOption) apply(vm *vm.EVM) { f(vm) } +func (f funcOption) apply(args *evmConstructorArgs) { f(args) } // WithBlockContext overrides the default context. func WithBlockContext(c vm.BlockContext) EVMOption { - return funcOption(func(vm *vm.EVM) { - vm.Context = c + return funcOption(func(args *evmConstructorArgs) { + args.blockContext = c + }) +} + +// WithBlockContext overrides the default context. +func WithChainConfig(c *params.ChainConfig) EVMOption { + return funcOption(func(args *evmConstructorArgs) { + args.chainConfig = c }) }