core, internal: support various eth_call invocations post 1559
This commit is contained in:
		@@ -221,6 +221,8 @@ func (st *StateTransition) preCheck() error {
 | 
			
		||||
	}
 | 
			
		||||
	// Make sure that transaction gasFeeCap is greater than the baseFee (post london)
 | 
			
		||||
	if st.evm.ChainConfig().IsLondon(st.evm.Context.BlockNumber) {
 | 
			
		||||
		// Skip the checks if gas fields are zero and baseFee was explicitly disabled (eth_call)
 | 
			
		||||
		if !st.evm.Config.NoBaseFee || st.gasFeeCap.BitLen() > 0 || st.gasTipCap.BitLen() > 0 {
 | 
			
		||||
			if l := st.gasFeeCap.BitLen(); l > 256 {
 | 
			
		||||
				return fmt.Errorf("%w: address %v, maxFeePerGas bit length: %d", ErrFeeCapVeryHigh,
 | 
			
		||||
					st.msg.From().Hex(), l)
 | 
			
		||||
@@ -240,6 +242,7 @@ func (st *StateTransition) preCheck() error {
 | 
			
		||||
					st.msg.From().Hex(), st.gasFeeCap, st.evm.Context.BaseFee)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return st.buyGas()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -275,7 +278,6 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
 | 
			
		||||
	sender := vm.AccountRef(msg.From())
 | 
			
		||||
	homestead := st.evm.ChainConfig().IsHomestead(st.evm.Context.BlockNumber)
 | 
			
		||||
	istanbul := st.evm.ChainConfig().IsIstanbul(st.evm.Context.BlockNumber)
 | 
			
		||||
	eip3529 := st.evm.ChainConfig().IsLondon(st.evm.Context.BlockNumber)
 | 
			
		||||
	contractCreation := msg.To() == nil
 | 
			
		||||
 | 
			
		||||
	// Check clauses 4-5, subtract intrinsic gas if everything is correct
 | 
			
		||||
@@ -308,7 +310,7 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
 | 
			
		||||
		st.state.SetNonce(msg.From(), st.state.GetNonce(sender.Address())+1)
 | 
			
		||||
		ret, st.gas, vmerr = st.evm.Call(sender, st.to(), st.data, st.gas, st.value)
 | 
			
		||||
	}
 | 
			
		||||
	if !eip3529 {
 | 
			
		||||
	if !st.evm.ChainConfig().IsLondon(st.evm.Context.BlockNumber) {
 | 
			
		||||
		// Before EIP-3529: refunds were capped to gasUsed / 2
 | 
			
		||||
		st.refundGas(params.RefundQuotient)
 | 
			
		||||
	} else {
 | 
			
		||||
 
 | 
			
		||||
@@ -128,7 +128,7 @@ type EVM struct {
 | 
			
		||||
	chainRules params.Rules
 | 
			
		||||
	// virtual machine configuration options used to initialise the
 | 
			
		||||
	// evm.
 | 
			
		||||
	vmConfig Config
 | 
			
		||||
	Config Config
 | 
			
		||||
	// global (to this context) ethereum virtual machine
 | 
			
		||||
	// used throughout the execution of the tx.
 | 
			
		||||
	interpreters []Interpreter
 | 
			
		||||
@@ -144,12 +144,12 @@ type EVM struct {
 | 
			
		||||
 | 
			
		||||
// NewEVM returns a new EVM. The returned EVM is not thread safe and should
 | 
			
		||||
// only ever be used *once*.
 | 
			
		||||
func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig *params.ChainConfig, vmConfig Config) *EVM {
 | 
			
		||||
func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig *params.ChainConfig, config Config) *EVM {
 | 
			
		||||
	evm := &EVM{
 | 
			
		||||
		Context:      blockCtx,
 | 
			
		||||
		TxContext:    txCtx,
 | 
			
		||||
		StateDB:      statedb,
 | 
			
		||||
		vmConfig:     vmConfig,
 | 
			
		||||
		Config:       config,
 | 
			
		||||
		chainConfig:  chainConfig,
 | 
			
		||||
		chainRules:   chainConfig.Rules(blockCtx.BlockNumber),
 | 
			
		||||
		interpreters: make([]Interpreter, 0, 1),
 | 
			
		||||
@@ -173,7 +173,7 @@ func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig
 | 
			
		||||
 | 
			
		||||
	// vmConfig.EVMInterpreter will be used by EVM-C, it won't be checked here
 | 
			
		||||
	// as we always want to have the built-in EVM as the failover option.
 | 
			
		||||
	evm.interpreters = append(evm.interpreters, NewEVMInterpreter(evm, vmConfig))
 | 
			
		||||
	evm.interpreters = append(evm.interpreters, NewEVMInterpreter(evm, config))
 | 
			
		||||
	evm.interpreter = evm.interpreters[0]
 | 
			
		||||
 | 
			
		||||
	return evm
 | 
			
		||||
@@ -207,7 +207,7 @@ func (evm *EVM) Interpreter() Interpreter {
 | 
			
		||||
// the necessary steps to create accounts and reverses the state in case of an
 | 
			
		||||
// execution error or failed value transfer.
 | 
			
		||||
func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) {
 | 
			
		||||
	if evm.vmConfig.NoRecursion && evm.depth > 0 {
 | 
			
		||||
	if evm.Config.NoRecursion && evm.depth > 0 {
 | 
			
		||||
		return nil, gas, nil
 | 
			
		||||
	}
 | 
			
		||||
	// Fail if we're trying to execute above the call depth limit
 | 
			
		||||
@@ -224,9 +224,9 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
 | 
			
		||||
	if !evm.StateDB.Exist(addr) {
 | 
			
		||||
		if !isPrecompile && evm.chainRules.IsEIP158 && value.Sign() == 0 {
 | 
			
		||||
			// Calling a non existing account, don't do anything, but ping the tracer
 | 
			
		||||
			if evm.vmConfig.Debug && evm.depth == 0 {
 | 
			
		||||
				evm.vmConfig.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value)
 | 
			
		||||
				evm.vmConfig.Tracer.CaptureEnd(ret, 0, 0, nil)
 | 
			
		||||
			if evm.Config.Debug && evm.depth == 0 {
 | 
			
		||||
				evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value)
 | 
			
		||||
				evm.Config.Tracer.CaptureEnd(ret, 0, 0, nil)
 | 
			
		||||
			}
 | 
			
		||||
			return nil, gas, nil
 | 
			
		||||
		}
 | 
			
		||||
@@ -235,10 +235,10 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
 | 
			
		||||
	evm.Context.Transfer(evm.StateDB, caller.Address(), addr, value)
 | 
			
		||||
 | 
			
		||||
	// Capture the tracer start/end events in debug mode
 | 
			
		||||
	if evm.vmConfig.Debug && evm.depth == 0 {
 | 
			
		||||
		evm.vmConfig.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value)
 | 
			
		||||
	if evm.Config.Debug && evm.depth == 0 {
 | 
			
		||||
		evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value)
 | 
			
		||||
		defer func(startGas uint64, startTime time.Time) { // Lazy evaluation of the parameters
 | 
			
		||||
			evm.vmConfig.Tracer.CaptureEnd(ret, startGas-gas, time.Since(startTime), err)
 | 
			
		||||
			evm.Config.Tracer.CaptureEnd(ret, startGas-gas, time.Since(startTime), err)
 | 
			
		||||
		}(gas, time.Now())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -283,7 +283,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
 | 
			
		||||
// CallCode differs from Call in the sense that it executes the given address'
 | 
			
		||||
// code with the caller as context.
 | 
			
		||||
func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) {
 | 
			
		||||
	if evm.vmConfig.NoRecursion && evm.depth > 0 {
 | 
			
		||||
	if evm.Config.NoRecursion && evm.depth > 0 {
 | 
			
		||||
		return nil, gas, nil
 | 
			
		||||
	}
 | 
			
		||||
	// Fail if we're trying to execute above the call depth limit
 | 
			
		||||
@@ -326,7 +326,7 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte,
 | 
			
		||||
// DelegateCall differs from CallCode in the sense that it executes the given address'
 | 
			
		||||
// code with the caller as context and the caller is set to the caller of the caller.
 | 
			
		||||
func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) {
 | 
			
		||||
	if evm.vmConfig.NoRecursion && evm.depth > 0 {
 | 
			
		||||
	if evm.Config.NoRecursion && evm.depth > 0 {
 | 
			
		||||
		return nil, gas, nil
 | 
			
		||||
	}
 | 
			
		||||
	// Fail if we're trying to execute above the call depth limit
 | 
			
		||||
@@ -360,7 +360,7 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
 | 
			
		||||
// Opcodes that attempt to perform such modifications will result in exceptions
 | 
			
		||||
// instead of performing the modifications.
 | 
			
		||||
func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) {
 | 
			
		||||
	if evm.vmConfig.NoRecursion && evm.depth > 0 {
 | 
			
		||||
	if evm.Config.NoRecursion && evm.depth > 0 {
 | 
			
		||||
		return nil, gas, nil
 | 
			
		||||
	}
 | 
			
		||||
	// Fail if we're trying to execute above the call depth limit
 | 
			
		||||
@@ -453,12 +453,12 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
 | 
			
		||||
	contract := NewContract(caller, AccountRef(address), value, gas)
 | 
			
		||||
	contract.SetCodeOptionalHash(&address, codeAndHash)
 | 
			
		||||
 | 
			
		||||
	if evm.vmConfig.NoRecursion && evm.depth > 0 {
 | 
			
		||||
	if evm.Config.NoRecursion && evm.depth > 0 {
 | 
			
		||||
		return nil, address, gas, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if evm.vmConfig.Debug && evm.depth == 0 {
 | 
			
		||||
		evm.vmConfig.Tracer.CaptureStart(evm, caller.Address(), address, true, codeAndHash.code, gas, value)
 | 
			
		||||
	if evm.Config.Debug && evm.depth == 0 {
 | 
			
		||||
		evm.Config.Tracer.CaptureStart(evm, caller.Address(), address, true, codeAndHash.code, gas, value)
 | 
			
		||||
	}
 | 
			
		||||
	start := time.Now()
 | 
			
		||||
 | 
			
		||||
@@ -497,8 +497,8 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if evm.vmConfig.Debug && evm.depth == 0 {
 | 
			
		||||
		evm.vmConfig.Tracer.CaptureEnd(ret, gas-contract.Gas, time.Since(start), err)
 | 
			
		||||
	if evm.Config.Debug && evm.depth == 0 {
 | 
			
		||||
		evm.Config.Tracer.CaptureEnd(ret, gas-contract.Gas, time.Since(start), err)
 | 
			
		||||
	}
 | 
			
		||||
	return ret, address, contract.Gas, err
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -244,7 +244,7 @@ func opSha3(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byt
 | 
			
		||||
	interpreter.hasher.Read(interpreter.hasherBuf[:])
 | 
			
		||||
 | 
			
		||||
	evm := interpreter.evm
 | 
			
		||||
	if evm.vmConfig.EnablePreimageRecording {
 | 
			
		||||
	if evm.Config.EnablePreimageRecording {
 | 
			
		||||
		evm.StateDB.AddPreimage(interpreter.hasherBuf, data)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -194,7 +194,7 @@ func TestAddMod(t *testing.T) {
 | 
			
		||||
	var (
 | 
			
		||||
		env            = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
 | 
			
		||||
		stack          = newstack()
 | 
			
		||||
		evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
 | 
			
		||||
		evmInterpreter = NewEVMInterpreter(env, env.Config)
 | 
			
		||||
		pc             = uint64(0)
 | 
			
		||||
	)
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
@@ -283,7 +283,7 @@ func opBenchmark(bench *testing.B, op executionFunc, args ...string) {
 | 
			
		||||
	var (
 | 
			
		||||
		env            = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
 | 
			
		||||
		stack          = newstack()
 | 
			
		||||
		evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
 | 
			
		||||
		evmInterpreter = NewEVMInterpreter(env, env.Config)
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	env.interpreter = evmInterpreter
 | 
			
		||||
@@ -518,7 +518,7 @@ func TestOpMstore(t *testing.T) {
 | 
			
		||||
		env            = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
 | 
			
		||||
		stack          = newstack()
 | 
			
		||||
		mem            = NewMemory()
 | 
			
		||||
		evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
 | 
			
		||||
		evmInterpreter = NewEVMInterpreter(env, env.Config)
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	env.interpreter = evmInterpreter
 | 
			
		||||
@@ -542,7 +542,7 @@ func BenchmarkOpMstore(bench *testing.B) {
 | 
			
		||||
		env            = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
 | 
			
		||||
		stack          = newstack()
 | 
			
		||||
		mem            = NewMemory()
 | 
			
		||||
		evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
 | 
			
		||||
		evmInterpreter = NewEVMInterpreter(env, env.Config)
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	env.interpreter = evmInterpreter
 | 
			
		||||
@@ -563,7 +563,7 @@ func BenchmarkOpSHA3(bench *testing.B) {
 | 
			
		||||
		env            = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
 | 
			
		||||
		stack          = newstack()
 | 
			
		||||
		mem            = NewMemory()
 | 
			
		||||
		evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
 | 
			
		||||
		evmInterpreter = NewEVMInterpreter(env, env.Config)
 | 
			
		||||
	)
 | 
			
		||||
	env.interpreter = evmInterpreter
 | 
			
		||||
	mem.Resize(32)
 | 
			
		||||
 
 | 
			
		||||
@@ -30,6 +30,7 @@ type Config struct {
 | 
			
		||||
	Debug                   bool   // Enables debugging
 | 
			
		||||
	Tracer                  Tracer // Opcode logger
 | 
			
		||||
	NoRecursion             bool   // Disables call, callcode, delegate call and create
 | 
			
		||||
	NoBaseFee               bool   // Forces the EIP-1559 baseFee to 0 (needed for 0 price calls)
 | 
			
		||||
	EnablePreimageRecording bool   // Enables recording of SHA3/keccak preimages
 | 
			
		||||
 | 
			
		||||
	JumpTable [256]*operation // EVM instruction table, automatically populated if unset
 | 
			
		||||
 
 | 
			
		||||
@@ -849,7 +849,7 @@ func DoCall(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	evm, vmError, err := b.GetEVM(ctx, msg, state, header, nil)
 | 
			
		||||
	evm, vmError, err := b.GetEVM(ctx, msg, state, header, &vm.Config{NoBaseFee: true})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -158,7 +158,9 @@ func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToMessage converts TransactionArgs to the Message type used by the core evm
 | 
			
		||||
// ToMessage converts th transaction arguments to the Message type used by the
 | 
			
		||||
// core evm. This method is used in calls and traces that do not require a real
 | 
			
		||||
// live transaction.
 | 
			
		||||
func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (types.Message, error) {
 | 
			
		||||
	// Reject invalid combinations of pre- and post-1559 fee styles
 | 
			
		||||
	if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) {
 | 
			
		||||
@@ -194,9 +196,11 @@ func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (t
 | 
			
		||||
	} else {
 | 
			
		||||
		// A basefee is provided, necessitating 1559-type execution
 | 
			
		||||
		if args.GasPrice != nil {
 | 
			
		||||
			// User specified the legacy gas field, convert to 1559 gas typing
 | 
			
		||||
			gasPrice = args.GasPrice.ToInt()
 | 
			
		||||
			gasFeeCap, gasTipCap = gasPrice, gasPrice
 | 
			
		||||
		} else {
 | 
			
		||||
			// User specified 1559 gas feilds (or none), use those
 | 
			
		||||
			gasFeeCap = new(big.Int)
 | 
			
		||||
			if args.MaxFeePerGas != nil {
 | 
			
		||||
				gasFeeCap = args.MaxFeePerGas.ToInt()
 | 
			
		||||
@@ -205,9 +209,13 @@ func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (t
 | 
			
		||||
			if args.MaxPriorityFeePerGas != nil {
 | 
			
		||||
				gasTipCap = args.MaxPriorityFeePerGas.ToInt()
 | 
			
		||||
			}
 | 
			
		||||
			// Backfill the legacy gasPrice for EVM execution, unless we're all zeroes
 | 
			
		||||
			gasPrice = new(big.Int)
 | 
			
		||||
			if gasFeeCap.BitLen() > 0 || gasTipCap.BitLen() > 0 {
 | 
			
		||||
				gasPrice = math.BigMin(new(big.Int).Add(gasTipCap, baseFee), gasFeeCap)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	value := new(big.Int)
 | 
			
		||||
	if args.Value != nil {
 | 
			
		||||
		value = args.Value.ToInt()
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@@ -3734,7 +3734,7 @@ var inputCallFormatter = function (options){
 | 
			
		||||
        options.to = inputAddressFormatter(options.to);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ['gasPrice', 'gas', 'value', 'nonce'].filter(function (key) {
 | 
			
		||||
    ['maxFeePerGas', 'maxPriorityFeePerGas', 'gasPrice', 'gas', 'value', 'nonce'].filter(function (key) {
 | 
			
		||||
        return options[key] !== undefined;
 | 
			
		||||
    }).forEach(function(key){
 | 
			
		||||
        options[key] = utils.fromDecimal(options[key]);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user