diff --git a/internal/ethapi/api_test.go b/internal/ethapi/api_test.go index 34afce0e1c..12edaf6dc8 100644 --- a/internal/ethapi/api_test.go +++ b/internal/ethapi/api_test.go @@ -1693,6 +1693,38 @@ func TestSimulateV1(t *testing.T) { want: nil, expectErr: &invalidTxError{Message: fmt.Sprintf("err: nonce too high: address %s, tx: 2 state: 0 (supplied gas 4712388)", accounts[2].addr), Code: errCodeNonceTooHigh}, }, + // Successful validation + { + name: "validation-checks-success", + tag: latest, + blocks: []simBlock{{ + BlockOverrides: &BlockOverrides{ + BaseFeePerGas: (*hexutil.Big)(big.NewInt(1)), + }, + StateOverrides: &StateOverride{ + randomAccounts[0].addr: OverrideAccount{Balance: newRPCBalance(big.NewInt(10000000))}, + }, + Calls: []TransactionArgs{{ + From: &randomAccounts[0].addr, + To: &randomAccounts[1].addr, + Value: (*hexutil.Big)(big.NewInt(1000)), + MaxFeePerGas: (*hexutil.Big)(big.NewInt(2)), + }}, + }}, + validation: &validation, + want: []blockRes{{ + Number: "0xb", + GasLimit: "0x47e7c4", + GasUsed: "0x5208", + FeeRecipient: coinbase, + Calls: []callRes{{ + ReturnValue: "0x", + GasUsed: "0x5208", + Logs: []log{}, + Status: "0x1", + }}, + }}, + }, // Clear storage. { name: "clear-storage", diff --git a/internal/ethapi/simulate.go b/internal/ethapi/simulate.go index 7b06162fd3..0850badc3e 100644 --- a/internal/ethapi/simulate.go +++ b/internal/ethapi/simulate.go @@ -176,8 +176,25 @@ func (sim *simulator) execute(ctx context.Context, blocks []simBlock) ([]simBloc } func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header, parent *types.Header, headers []*types.Header, gp *core.GasPool, precompiles vm.PrecompiledContracts, timeout time.Duration) (*simBlockResult, error) { - // Set this here for evm.GetHashFn to work. + // Set header fields that depend only on parent block. + config := sim.b.ChainConfig() + // Parent hash is needed for evm.GetHashFn to work. header.ParentHash = parent.Hash() + if config.IsLondon(header.Number) { + // Base fee could have been overridden. + if header.BaseFee == nil { + header.BaseFee = eip1559.CalcBaseFee(config, parent) + } + } + if config.IsCancun(header.Number, header.Time) { + var excess uint64 + if config.IsCancun(parent.Number, parent.Time) { + excess = eip4844.CalcExcessBlobGas(*parent.ExcessBlobGas, *parent.BlobGasUsed) + } else { + excess = eip4844.CalcExcessBlobGas(0, 0) + } + header.ExcessBlobGas = &excess + } blockContext := core.NewEVMBlockContext(header, sim.newSimulatedChainContext(ctx, headers), nil) if block.BlockOverrides.BlobBaseFee != nil { blockContext.BlobBaseFee = block.BlockOverrides.BlobBaseFee.ToInt() @@ -192,7 +209,6 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header, callResults = make([]simCallResult, len(block.Calls)) receipts = make([]*types.Receipt, len(block.Calls)) tracer = newTracer(sim.traceTransfers, blockContext.BlockNumber.Uint64(), common.Hash{}, common.Hash{}, 0) - config = sim.b.ChainConfig() vmConfig = &vm.Config{ NoBaseFee: !sim.validate, // Block hash will be repaired after execution. @@ -263,19 +279,8 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header, header.ReceiptHash = types.DeriveSha(types.Receipts(receipts), trie.NewStackTrie(nil)) header.Bloom = types.CreateBloom(types.Receipts(receipts)) } - if config.IsLondon(header.Number) { - // BaseFee depends on parent's gasUsed, hence can't be pre-computed. - header.BaseFee = eip1559.CalcBaseFee(config, parent) - } if config.IsCancun(header.Number, header.Time) { header.BlobGasUsed = &blobGasUsed - var excess uint64 - if config.IsCancun(parent.Number, parent.Time) { - excess = eip4844.CalcExcessBlobGas(*parent.ExcessBlobGas, *parent.BlobGasUsed) - } else { - excess = eip4844.CalcExcessBlobGas(0, 0) - } - header.ExcessBlobGas = &excess } result := simBlockResultFromHeader(header, callResults) result.repairLogs()