Skip to content

Commit 3a15227

Browse files
committed
core, internal: support various eth_call invocations post 1559 (ethereum#23027)
1 parent e61c673 commit 3a15227

File tree

9 files changed

+73
-61
lines changed

9 files changed

+73
-61
lines changed

core/state_transition.go

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -223,23 +223,26 @@ func (st *StateTransition) preCheck() error {
223223
}
224224
// Make sure that transaction gasFeeCap is greater than the baseFee (post london)
225225
if st.evm.ChainConfig().IsEIP1559(st.evm.Context.BlockNumber) {
226-
if l := st.gasFeeCap.BitLen(); l > 256 {
227-
return fmt.Errorf("%w: address %v, maxFeePerGas bit length: %d", ErrFeeCapVeryHigh,
228-
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-
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-
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-
msg.From().Hex(), st.gasFeeCap, st.evm.Context.BaseFee)
226+
// Skip the checks if gas fields are zero and baseFee was explicitly disabled (eth_call)
227+
if !st.evm.Config.NoBaseFee || st.gasFeeCap.BitLen() > 0 || st.gasTipCap.BitLen() > 0 {
228+
if l := st.gasFeeCap.BitLen(); l > 256 {
229+
return fmt.Errorf("%w: address %v, maxFeePerGas bit length: %d", ErrFeeCapVeryHigh,
230+
msg.From().Hex(), l)
231+
}
232+
if l := st.gasTipCap.BitLen(); l > 256 {
233+
return fmt.Errorf("%w: address %v, maxPriorityFeePerGas bit length: %d", ErrTipVeryHigh,
234+
msg.From().Hex(), l)
235+
}
236+
if st.gasFeeCap.Cmp(st.gasTipCap) < 0 {
237+
return fmt.Errorf("%w: address %v, maxPriorityFeePerGas: %s, maxFeePerGas: %s", ErrTipAboveFeeCap,
238+
msg.From().Hex(), st.gasTipCap, st.gasFeeCap)
239+
}
240+
// This will panic if baseFee is nil, but basefee presence is verified
241+
// as part of header validation.
242+
if st.gasFeeCap.Cmp(st.evm.Context.BaseFee) < 0 {
243+
return fmt.Errorf("%w: address %v, maxFeePerGas: %s baseFee: %s", ErrFeeCapTooLow,
244+
msg.From().Hex(), st.gasFeeCap, st.evm.Context.BaseFee)
245+
}
243246
}
244247
}
245248
return st.buyGas()

core/vm/evm.go

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ type EVM struct {
138138
chainRules params.Rules
139139
// virtual machine configuration options used to initialise the
140140
// evm.
141-
vmConfig Config
141+
Config Config
142142
// global (to this context) ethereum virtual machine
143143
// used throughout the execution of the tx.
144144
interpreters []Interpreter
@@ -154,21 +154,21 @@ type EVM struct {
154154

155155
// NewEVM returns a new EVM. The returned EVM is not thread safe and should
156156
// only ever be used *once*.
157-
func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, tradingStateDB *tradingstate.TradingStateDB, chainConfig *params.ChainConfig, vmConfig Config) *EVM {
157+
func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, tradingStateDB *tradingstate.TradingStateDB, chainConfig *params.ChainConfig, config Config) *EVM {
158158
evm := &EVM{
159159
Context: blockCtx,
160160
TxContext: txCtx,
161161
StateDB: statedb,
162162
tradingStateDB: tradingStateDB,
163-
vmConfig: vmConfig,
163+
Config: config,
164164
chainConfig: chainConfig,
165165
chainRules: chainConfig.Rules(blockCtx.BlockNumber),
166166
interpreters: make([]Interpreter, 0, 1),
167167
}
168168

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

174174
return evm
@@ -216,13 +216,13 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
216216
if !evm.StateDB.Exist(addr) {
217217
if !isPrecompile && evm.chainRules.IsEIP158 && value.Sign() == 0 {
218218
// Calling a non existing account, don't do anything, but ping the tracer
219-
if evm.vmConfig.Debug {
219+
if evm.Config.Debug {
220220
if evm.depth == 0 {
221-
evm.vmConfig.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value)
222-
evm.vmConfig.Tracer.CaptureEnd(ret, 0, 0, nil)
221+
evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value)
222+
evm.Config.Tracer.CaptureEnd(ret, 0, 0, nil)
223223
} else {
224-
evm.vmConfig.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value)
225-
evm.vmConfig.Tracer.CaptureExit(ret, 0, nil)
224+
evm.Config.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value)
225+
evm.Config.Tracer.CaptureExit(ret, 0, nil)
226226
}
227227
}
228228
return nil, gas, nil
@@ -232,18 +232,18 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
232232
evm.Context.Transfer(evm.StateDB, caller.Address(), addr, value)
233233

234234
// Capture the tracer start/end events in debug mode
235-
if evm.vmConfig.Debug {
235+
if evm.Config.Debug {
236236
if evm.depth == 0 {
237-
evm.vmConfig.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value)
237+
evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value)
238238

239239
defer func(startGas uint64, startTime time.Time) { // Lazy evaluation of the parameters
240-
evm.vmConfig.Tracer.CaptureEnd(ret, startGas-gas, time.Since(startTime), err)
240+
evm.Config.Tracer.CaptureEnd(ret, startGas-gas, time.Since(startTime), err)
241241
}(gas, time.Now())
242242
} else {
243243
// Handle tracer events for entering and exiting a call frame
244-
evm.vmConfig.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value)
244+
evm.Config.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value)
245245
defer func(startGas uint64) {
246-
evm.vmConfig.Tracer.CaptureExit(ret, startGas-gas, err)
246+
evm.Config.Tracer.CaptureExit(ret, startGas-gas, err)
247247
}(gas)
248248
}
249249
}
@@ -303,10 +303,10 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte,
303303
var snapshot = evm.StateDB.Snapshot()
304304

305305
// Invoke tracer hooks that signal entering/exiting a call frame
306-
if evm.vmConfig.Debug {
307-
evm.vmConfig.Tracer.CaptureEnter(CALLCODE, caller.Address(), addr, input, gas, value)
306+
if evm.Config.Debug {
307+
evm.Config.Tracer.CaptureEnter(CALLCODE, caller.Address(), addr, input, gas, value)
308308
defer func(startGas uint64) {
309-
evm.vmConfig.Tracer.CaptureExit(ret, startGas-gas, err)
309+
evm.Config.Tracer.CaptureExit(ret, startGas-gas, err)
310310
}(gas)
311311
}
312312

@@ -344,10 +344,10 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
344344
var snapshot = evm.StateDB.Snapshot()
345345

346346
// Invoke tracer hooks that signal entering/exiting a call frame
347-
if evm.vmConfig.Debug {
348-
evm.vmConfig.Tracer.CaptureEnter(DELEGATECALL, caller.Address(), addr, input, gas, nil)
347+
if evm.Config.Debug {
348+
evm.Config.Tracer.CaptureEnter(DELEGATECALL, caller.Address(), addr, input, gas, nil)
349349
defer func(startGas uint64) {
350-
evm.vmConfig.Tracer.CaptureExit(ret, startGas-gas, err)
350+
evm.Config.Tracer.CaptureExit(ret, startGas-gas, err)
351351
}(gas)
352352
}
353353

@@ -394,10 +394,10 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte
394394
evm.StateDB.AddBalance(addr, big0)
395395

396396
// Invoke tracer hooks that signal entering/exiting a call frame
397-
if evm.vmConfig.Debug {
398-
evm.vmConfig.Tracer.CaptureEnter(STATICCALL, caller.Address(), addr, input, gas, nil)
397+
if evm.Config.Debug {
398+
evm.Config.Tracer.CaptureEnter(STATICCALL, caller.Address(), addr, input, gas, nil)
399399
defer func(startGas uint64) {
400-
evm.vmConfig.Tracer.CaptureExit(ret, startGas-gas, err)
400+
evm.Config.Tracer.CaptureExit(ret, startGas-gas, err)
401401
}(gas)
402402
}
403403

@@ -478,11 +478,11 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
478478
contract := NewContract(caller, AccountRef(address), value, gas)
479479
contract.SetCodeOptionalHash(&address, codeAndHash)
480480

481-
if evm.vmConfig.Debug {
481+
if evm.Config.Debug {
482482
if evm.depth == 0 {
483-
evm.vmConfig.Tracer.CaptureStart(evm, caller.Address(), address, true, codeAndHash.code, gas, value)
483+
evm.Config.Tracer.CaptureStart(evm, caller.Address(), address, true, codeAndHash.code, gas, value)
484484
} else {
485-
evm.vmConfig.Tracer.CaptureEnter(typ, caller.Address(), address, codeAndHash.code, gas, value)
485+
evm.Config.Tracer.CaptureEnter(typ, caller.Address(), address, codeAndHash.code, gas, value)
486486
}
487487
}
488488
start := time.Now()
@@ -522,11 +522,11 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
522522
}
523523
}
524524

525-
if evm.vmConfig.Debug {
525+
if evm.Config.Debug {
526526
if evm.depth == 0 {
527-
evm.vmConfig.Tracer.CaptureEnd(ret, gas-contract.Gas, time.Since(start), err)
527+
evm.Config.Tracer.CaptureEnd(ret, gas-contract.Gas, time.Since(start), err)
528528
} else {
529-
evm.vmConfig.Tracer.CaptureExit(ret, gas-contract.Gas, err)
529+
evm.Config.Tracer.CaptureExit(ret, gas-contract.Gas, err)
530530
}
531531
}
532532
return ret, address, contract.Gas, err

core/vm/instructions.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ func opKeccak256(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) (
246246
interpreter.hasher.Read(interpreter.hasherBuf[:])
247247

248248
evm := interpreter.evm
249-
if evm.vmConfig.EnablePreimageRecording {
249+
if evm.Config.EnablePreimageRecording {
250250
evm.StateDB.AddPreimage(interpreter.hasherBuf, data)
251251
}
252252

core/vm/instructions_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ func TestAddMod(t *testing.T) {
196196
var (
197197
env = NewEVM(BlockContext{}, TxContext{}, nil, nil, params.TestChainConfig, Config{})
198198
stack = newstack()
199-
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
199+
evmInterpreter = NewEVMInterpreter(env, env.Config)
200200
pc = uint64(0)
201201
)
202202
tests := []struct {
@@ -291,7 +291,7 @@ func opBenchmark(bench *testing.B, op executionFunc, args ...string) {
291291
var (
292292
env = NewEVM(BlockContext{}, TxContext{}, nil, nil, params.TestChainConfig, Config{})
293293
stack = newstack()
294-
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
294+
evmInterpreter = NewEVMInterpreter(env, env.Config)
295295
)
296296

297297
env.interpreter = evmInterpreter
@@ -526,7 +526,7 @@ func TestOpMstore(t *testing.T) {
526526
env = NewEVM(BlockContext{}, TxContext{}, nil, nil, params.TestChainConfig, Config{})
527527
stack = newstack()
528528
mem = NewMemory()
529-
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
529+
evmInterpreter = NewEVMInterpreter(env, env.Config)
530530
)
531531

532532
env.interpreter = evmInterpreter
@@ -552,7 +552,7 @@ func BenchmarkOpMstore(bench *testing.B) {
552552
env = NewEVM(BlockContext{}, TxContext{}, nil, nil, params.TestChainConfig, Config{})
553553
stack = newstack()
554554
mem = NewMemory()
555-
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
555+
evmInterpreter = NewEVMInterpreter(env, env.Config)
556556
)
557557

558558
env.interpreter = evmInterpreter
@@ -574,7 +574,7 @@ func BenchmarkOpKeccak256(bench *testing.B) {
574574
env = NewEVM(BlockContext{}, TxContext{}, nil, nil, params.TestChainConfig, Config{})
575575
stack = newstack()
576576
mem = NewMemory()
577-
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
577+
evmInterpreter = NewEVMInterpreter(env, env.Config)
578578
)
579579
env.interpreter = evmInterpreter
580580
mem.Resize(32)
@@ -679,7 +679,7 @@ func TestRandom(t *testing.T) {
679679
env = NewEVM(BlockContext{Random: &tt.random}, TxContext{}, nil, nil, params.TestChainConfig, Config{})
680680
stack = newstack()
681681
pc = uint64(0)
682-
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
682+
evmInterpreter = NewEVMInterpreter(env, env.Config)
683683
)
684684
opRandom(&pc, evmInterpreter, &ScopeContext{nil, stack, nil})
685685
if len(stack.data) != 1 {

core/vm/interpreter.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
type Config struct {
2929
Debug bool // Enables debugging
3030
Tracer EVMLogger // Opcode logger
31+
NoBaseFee bool // Forces the EIP-1559 baseFee to 0 (needed for 0 price calls)
3132
EnablePreimageRecording bool // Enables recording of SHA3/keccak preimages
3233

3334
JumpTable *JumpTable // EVM instruction table, automatically populated if unset

internal/ethapi/api.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1257,7 +1257,7 @@ func (s *PublicBlockChainAPI) getCandidatesFromSmartContract() ([]utils.Masterno
12571257
return candidatesWithStakeInfo, nil
12581258
}
12591259

1260-
func DoCall(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride, vmCfg vm.Config, timeout time.Duration, globalGasCap uint64) ([]byte, uint64, bool, error, error) {
1260+
func DoCall(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride, timeout time.Duration, globalGasCap uint64) ([]byte, uint64, bool, error, error) {
12611261
defer func(start time.Time) { log.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now())
12621262

12631263
statedb, header, err := b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
@@ -1306,7 +1306,7 @@ func DoCall(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash
13061306
}
13071307

13081308
// Get a new instance of the EVM.
1309-
evm, vmError, err := b.GetEVM(ctx, msg, statedb, XDCxState, header, &vmCfg)
1309+
evm, vmError, err := b.GetEVM(ctx, msg, statedb, XDCxState, header, &vm.Config{NoBaseFee: true})
13101310
if err != nil {
13111311
return nil, 0, false, err, nil
13121312
}
@@ -1376,7 +1376,7 @@ func (s *PublicBlockChainAPI) Call(ctx context.Context, args TransactionArgs, bl
13761376
if args.To != nil && *args.To == common.MasternodeVotingSMCBinary {
13771377
timeout = 0
13781378
}
1379-
result, _, failed, err, vmErr := DoCall(ctx, s.b, args, *blockNrOrHash, overrides, vm.Config{}, timeout, s.b.RPCGasCap())
1379+
result, _, failed, err, vmErr := DoCall(ctx, s.b, args, *blockNrOrHash, overrides, timeout, s.b.RPCGasCap())
13801380
if err != nil {
13811381
return nil, err
13821382
}
@@ -1432,7 +1432,7 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr
14321432
executable := func(gas uint64) (bool, []byte, error, error) {
14331433
args.Gas = (*hexutil.Uint64)(&gas)
14341434

1435-
res, _, failed, err, vmErr := DoCall(ctx, b, args, blockNrOrHash, nil, vm.Config{}, 0, gasCap)
1435+
res, _, failed, err, vmErr := DoCall(ctx, b, args, blockNrOrHash, nil, 0, gasCap)
14361436
if err != nil {
14371437
if errors.Is(err, vm.ErrOutOfGas) || errors.Is(err, core.ErrIntrinsicGas) {
14381438
return false, nil, nil, nil // Special case, raise gas limit

internal/ethapi/transaction_args.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,9 @@ func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend) error {
159159
return nil
160160
}
161161

162-
// ToMessage converts TransactionArgs to the Message type used by the core evm
162+
// ToMessage converts th transaction arguments to the Message type used by the
163+
// core evm. This method is used in calls and traces that do not require a real
164+
// live transaction.
163165
func (args *TransactionArgs) ToMessage(b Backend, number *big.Int, globalGasCap uint64, baseFee *big.Int) (types.Message, error) {
164166
// Reject invalid combinations of pre- and post-1559 fee styles
165167
if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) {
@@ -207,9 +209,11 @@ func (args *TransactionArgs) ToMessage(b Backend, number *big.Int, globalGasCap
207209
} else {
208210
// A basefee is provided, necessitating 1559-type execution
209211
if args.GasPrice != nil {
212+
// User specified the legacy gas field, convert to 1559 gas typing
210213
gasPrice = args.GasPrice.ToInt()
211214
gasFeeCap, gasTipCap = gasPrice, gasPrice
212215
} else {
216+
// User specified 1559 gas feilds (or none), use those
213217
gasFeeCap = new(big.Int)
214218
if args.MaxFeePerGas != nil {
215219
gasFeeCap = args.MaxFeePerGas.ToInt()
@@ -218,7 +222,11 @@ func (args *TransactionArgs) ToMessage(b Backend, number *big.Int, globalGasCap
218222
if args.MaxPriorityFeePerGas != nil {
219223
gasTipCap = args.MaxPriorityFeePerGas.ToInt()
220224
}
221-
gasPrice = math.BigMin(new(big.Int).Add(gasTipCap, baseFee), gasFeeCap)
225+
// Backfill the legacy gasPrice for EVM execution, unless we're all zeroes
226+
gasPrice = new(big.Int)
227+
if gasFeeCap.BitLen() > 0 || gasTipCap.BitLen() > 0 {
228+
gasPrice = math.BigMin(new(big.Int).Add(gasTipCap, baseFee), gasFeeCap)
229+
}
222230
}
223231
}
224232
value := new(big.Int)

internal/jsre/deps/bindata.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/jsre/deps/web3.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)