Skip to content

Commit eff998e

Browse files
authored
Merge pull request #23027 from karalabe/1559-call
core, internal: support various eth_call invocations post 1559
2 parents a2ea537 + f68a68a commit eff998e

File tree

9 files changed

+62
-51
lines changed

9 files changed

+62
-51
lines changed

core/state_transition.go

+21-19
Original file line numberDiff line numberDiff line change
@@ -221,23 +221,26 @@ func (st *StateTransition) preCheck() error {
221221
}
222222
// Make sure that transaction gasFeeCap is greater than the baseFee (post london)
223223
if st.evm.ChainConfig().IsLondon(st.evm.Context.BlockNumber) {
224-
if l := st.gasFeeCap.BitLen(); l > 256 {
225-
return fmt.Errorf("%w: address %v, maxFeePerGas bit length: %d", ErrFeeCapVeryHigh,
226-
st.msg.From().Hex(), l)
227-
}
228-
if l := st.gasTipCap.BitLen(); l > 256 {
229-
return fmt.Errorf("%w: address %v, maxPriorityFeePerGas bit length: %d", ErrTipVeryHigh,
230-
st.msg.From().Hex(), l)
231-
}
232-
if st.gasFeeCap.Cmp(st.gasTipCap) < 0 {
233-
return fmt.Errorf("%w: address %v, maxPriorityFeePerGas: %s, maxFeePerGas: %s", ErrTipAboveFeeCap,
234-
st.msg.From().Hex(), st.gasTipCap, st.gasFeeCap)
235-
}
236-
// This will panic if baseFee is nil, but basefee presence is verified
237-
// as part of header validation.
238-
if st.gasFeeCap.Cmp(st.evm.Context.BaseFee) < 0 {
239-
return fmt.Errorf("%w: address %v, maxFeePerGas: %s baseFee: %s", ErrFeeCapTooLow,
240-
st.msg.From().Hex(), st.gasFeeCap, st.evm.Context.BaseFee)
224+
// Skip the checks if gas fields are zero and baseFee was explicitly disabled (eth_call)
225+
if !st.evm.Config.NoBaseFee || st.gasFeeCap.BitLen() > 0 || st.gasTipCap.BitLen() > 0 {
226+
if l := st.gasFeeCap.BitLen(); l > 256 {
227+
return fmt.Errorf("%w: address %v, maxFeePerGas bit length: %d", ErrFeeCapVeryHigh,
228+
st.msg.From().Hex(), l)
229+
}
230+
if l := st.gasTipCap.BitLen(); l > 256 {
231+
return fmt.Errorf("%w: address %v, maxPriorityFeePerGas bit length: %d", ErrTipVeryHigh,
232+
st.msg.From().Hex(), l)
233+
}
234+
if st.gasFeeCap.Cmp(st.gasTipCap) < 0 {
235+
return fmt.Errorf("%w: address %v, maxPriorityFeePerGas: %s, maxFeePerGas: %s", ErrTipAboveFeeCap,
236+
st.msg.From().Hex(), st.gasTipCap, st.gasFeeCap)
237+
}
238+
// This will panic if baseFee is nil, but basefee presence is verified
239+
// as part of header validation.
240+
if st.gasFeeCap.Cmp(st.evm.Context.BaseFee) < 0 {
241+
return fmt.Errorf("%w: address %v, maxFeePerGas: %s baseFee: %s", ErrFeeCapTooLow,
242+
st.msg.From().Hex(), st.gasFeeCap, st.evm.Context.BaseFee)
243+
}
241244
}
242245
}
243246
return st.buyGas()
@@ -275,7 +278,6 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
275278
sender := vm.AccountRef(msg.From())
276279
homestead := st.evm.ChainConfig().IsHomestead(st.evm.Context.BlockNumber)
277280
istanbul := st.evm.ChainConfig().IsIstanbul(st.evm.Context.BlockNumber)
278-
eip3529 := st.evm.ChainConfig().IsLondon(st.evm.Context.BlockNumber)
279281
contractCreation := msg.To() == nil
280282

281283
// Check clauses 4-5, subtract intrinsic gas if everything is correct
@@ -308,7 +310,7 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
308310
st.state.SetNonce(msg.From(), st.state.GetNonce(sender.Address())+1)
309311
ret, st.gas, vmerr = st.evm.Call(sender, st.to(), st.data, st.gas, st.value)
310312
}
311-
if !eip3529 {
313+
if !st.evm.ChainConfig().IsLondon(st.evm.Context.BlockNumber) {
312314
// Before EIP-3529: refunds were capped to gasUsed / 2
313315
st.refundGas(params.RefundQuotient)
314316
} else {

core/vm/evm.go

+19-19
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ type EVM struct {
128128
chainRules params.Rules
129129
// virtual machine configuration options used to initialise the
130130
// evm.
131-
vmConfig Config
131+
Config Config
132132
// global (to this context) ethereum virtual machine
133133
// used throughout the execution of the tx.
134134
interpreters []Interpreter
@@ -144,12 +144,12 @@ type EVM struct {
144144

145145
// NewEVM returns a new EVM. The returned EVM is not thread safe and should
146146
// only ever be used *once*.
147-
func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig *params.ChainConfig, vmConfig Config) *EVM {
147+
func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig *params.ChainConfig, config Config) *EVM {
148148
evm := &EVM{
149149
Context: blockCtx,
150150
TxContext: txCtx,
151151
StateDB: statedb,
152-
vmConfig: vmConfig,
152+
Config: config,
153153
chainConfig: chainConfig,
154154
chainRules: chainConfig.Rules(blockCtx.BlockNumber),
155155
interpreters: make([]Interpreter, 0, 1),
@@ -173,7 +173,7 @@ func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig
173173

174174
// vmConfig.EVMInterpreter will be used by EVM-C, it won't be checked here
175175
// as we always want to have the built-in EVM as the failover option.
176-
evm.interpreters = append(evm.interpreters, NewEVMInterpreter(evm, vmConfig))
176+
evm.interpreters = append(evm.interpreters, NewEVMInterpreter(evm, config))
177177
evm.interpreter = evm.interpreters[0]
178178

179179
return evm
@@ -207,7 +207,7 @@ func (evm *EVM) Interpreter() Interpreter {
207207
// the necessary steps to create accounts and reverses the state in case of an
208208
// execution error or failed value transfer.
209209
func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) {
210-
if evm.vmConfig.NoRecursion && evm.depth > 0 {
210+
if evm.Config.NoRecursion && evm.depth > 0 {
211211
return nil, gas, nil
212212
}
213213
// 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
224224
if !evm.StateDB.Exist(addr) {
225225
if !isPrecompile && evm.chainRules.IsEIP158 && value.Sign() == 0 {
226226
// Calling a non existing account, don't do anything, but ping the tracer
227-
if evm.vmConfig.Debug && evm.depth == 0 {
228-
evm.vmConfig.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value)
229-
evm.vmConfig.Tracer.CaptureEnd(ret, 0, 0, nil)
227+
if evm.Config.Debug && evm.depth == 0 {
228+
evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value)
229+
evm.Config.Tracer.CaptureEnd(ret, 0, 0, nil)
230230
}
231231
return nil, gas, nil
232232
}
@@ -235,10 +235,10 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
235235
evm.Context.Transfer(evm.StateDB, caller.Address(), addr, value)
236236

237237
// Capture the tracer start/end events in debug mode
238-
if evm.vmConfig.Debug && evm.depth == 0 {
239-
evm.vmConfig.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value)
238+
if evm.Config.Debug && evm.depth == 0 {
239+
evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value)
240240
defer func(startGas uint64, startTime time.Time) { // Lazy evaluation of the parameters
241-
evm.vmConfig.Tracer.CaptureEnd(ret, startGas-gas, time.Since(startTime), err)
241+
evm.Config.Tracer.CaptureEnd(ret, startGas-gas, time.Since(startTime), err)
242242
}(gas, time.Now())
243243
}
244244

@@ -283,7 +283,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
283283
// CallCode differs from Call in the sense that it executes the given address'
284284
// code with the caller as context.
285285
func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) {
286-
if evm.vmConfig.NoRecursion && evm.depth > 0 {
286+
if evm.Config.NoRecursion && evm.depth > 0 {
287287
return nil, gas, nil
288288
}
289289
// 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,
326326
// DelegateCall differs from CallCode in the sense that it executes the given address'
327327
// code with the caller as context and the caller is set to the caller of the caller.
328328
func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) {
329-
if evm.vmConfig.NoRecursion && evm.depth > 0 {
329+
if evm.Config.NoRecursion && evm.depth > 0 {
330330
return nil, gas, nil
331331
}
332332
// 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
360360
// Opcodes that attempt to perform such modifications will result in exceptions
361361
// instead of performing the modifications.
362362
func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) {
363-
if evm.vmConfig.NoRecursion && evm.depth > 0 {
363+
if evm.Config.NoRecursion && evm.depth > 0 {
364364
return nil, gas, nil
365365
}
366366
// 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,
453453
contract := NewContract(caller, AccountRef(address), value, gas)
454454
contract.SetCodeOptionalHash(&address, codeAndHash)
455455

456-
if evm.vmConfig.NoRecursion && evm.depth > 0 {
456+
if evm.Config.NoRecursion && evm.depth > 0 {
457457
return nil, address, gas, nil
458458
}
459459

460-
if evm.vmConfig.Debug && evm.depth == 0 {
461-
evm.vmConfig.Tracer.CaptureStart(evm, caller.Address(), address, true, codeAndHash.code, gas, value)
460+
if evm.Config.Debug && evm.depth == 0 {
461+
evm.Config.Tracer.CaptureStart(evm, caller.Address(), address, true, codeAndHash.code, gas, value)
462462
}
463463
start := time.Now()
464464

@@ -497,8 +497,8 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
497497
}
498498
}
499499

500-
if evm.vmConfig.Debug && evm.depth == 0 {
501-
evm.vmConfig.Tracer.CaptureEnd(ret, gas-contract.Gas, time.Since(start), err)
500+
if evm.Config.Debug && evm.depth == 0 {
501+
evm.Config.Tracer.CaptureEnd(ret, gas-contract.Gas, time.Since(start), err)
502502
}
503503
return ret, address, contract.Gas, err
504504
}

core/vm/instructions.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ func opSha3(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byt
244244
interpreter.hasher.Read(interpreter.hasherBuf[:])
245245

246246
evm := interpreter.evm
247-
if evm.vmConfig.EnablePreimageRecording {
247+
if evm.Config.EnablePreimageRecording {
248248
evm.StateDB.AddPreimage(interpreter.hasherBuf, data)
249249
}
250250

core/vm/instructions_test.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ func TestAddMod(t *testing.T) {
194194
var (
195195
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
196196
stack = newstack()
197-
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
197+
evmInterpreter = NewEVMInterpreter(env, env.Config)
198198
pc = uint64(0)
199199
)
200200
tests := []struct {
@@ -283,7 +283,7 @@ func opBenchmark(bench *testing.B, op executionFunc, args ...string) {
283283
var (
284284
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
285285
stack = newstack()
286-
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
286+
evmInterpreter = NewEVMInterpreter(env, env.Config)
287287
)
288288

289289
env.interpreter = evmInterpreter
@@ -518,7 +518,7 @@ func TestOpMstore(t *testing.T) {
518518
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
519519
stack = newstack()
520520
mem = NewMemory()
521-
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
521+
evmInterpreter = NewEVMInterpreter(env, env.Config)
522522
)
523523

524524
env.interpreter = evmInterpreter
@@ -542,7 +542,7 @@ func BenchmarkOpMstore(bench *testing.B) {
542542
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
543543
stack = newstack()
544544
mem = NewMemory()
545-
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
545+
evmInterpreter = NewEVMInterpreter(env, env.Config)
546546
)
547547

548548
env.interpreter = evmInterpreter
@@ -563,7 +563,7 @@ func BenchmarkOpSHA3(bench *testing.B) {
563563
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
564564
stack = newstack()
565565
mem = NewMemory()
566-
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
566+
evmInterpreter = NewEVMInterpreter(env, env.Config)
567567
)
568568
env.interpreter = evmInterpreter
569569
mem.Resize(32)

core/vm/interpreter.go

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ type Config struct {
3030
Debug bool // Enables debugging
3131
Tracer Tracer // Opcode logger
3232
NoRecursion bool // Disables call, callcode, delegate call and create
33+
NoBaseFee bool // Forces the EIP-1559 baseFee to 0 (needed for 0 price calls)
3334
EnablePreimageRecording bool // Enables recording of SHA3/keccak preimages
3435

3536
JumpTable [256]*operation // EVM instruction table, automatically populated if unset

internal/ethapi/api.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -849,7 +849,7 @@ func DoCall(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash
849849
if err != nil {
850850
return nil, err
851851
}
852-
evm, vmError, err := b.GetEVM(ctx, msg, state, header, nil)
852+
evm, vmError, err := b.GetEVM(ctx, msg, state, header, &vm.Config{NoBaseFee: true})
853853
if err != nil {
854854
return nil, err
855855
}

internal/ethapi/transaction_args.go

+10-2
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,9 @@ func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend) error {
158158
return nil
159159
}
160160

161-
// ToMessage converts TransactionArgs to the Message type used by the core evm
161+
// ToMessage converts th transaction arguments to the Message type used by the
162+
// core evm. This method is used in calls and traces that do not require a real
163+
// live transaction.
162164
func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (types.Message, error) {
163165
// Reject invalid combinations of pre- and post-1559 fee styles
164166
if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) {
@@ -194,9 +196,11 @@ func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (t
194196
} else {
195197
// A basefee is provided, necessitating 1559-type execution
196198
if args.GasPrice != nil {
199+
// User specified the legacy gas field, convert to 1559 gas typing
197200
gasPrice = args.GasPrice.ToInt()
198201
gasFeeCap, gasTipCap = gasPrice, gasPrice
199202
} else {
203+
// User specified 1559 gas feilds (or none), use those
200204
gasFeeCap = new(big.Int)
201205
if args.MaxFeePerGas != nil {
202206
gasFeeCap = args.MaxFeePerGas.ToInt()
@@ -205,7 +209,11 @@ func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (t
205209
if args.MaxPriorityFeePerGas != nil {
206210
gasTipCap = args.MaxPriorityFeePerGas.ToInt()
207211
}
208-
gasPrice = math.BigMin(new(big.Int).Add(gasTipCap, baseFee), gasFeeCap)
212+
// Backfill the legacy gasPrice for EVM execution, unless we're all zeroes
213+
gasPrice = new(big.Int)
214+
if gasFeeCap.BitLen() > 0 || gasTipCap.BitLen() > 0 {
215+
gasPrice = math.BigMin(new(big.Int).Add(gasTipCap, baseFee), gasFeeCap)
216+
}
209217
}
210218
}
211219
value := new(big.Int)

internal/jsre/deps/bindata.go

+3-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/jsre/deps/web3.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)