Skip to content

Commit 6143c35

Browse files
georgehaos1na
andauthored
internal/ethapi: CreateAccessList with stateOverrides (#31497)
Add support for state overrides in eth_createAccessList. This will make the method consistent with other execution methods. --------- Co-authored-by: Sina Mahmoodi <[email protected]>
1 parent a82303f commit 6143c35

File tree

2 files changed

+86
-3
lines changed

2 files changed

+86
-3
lines changed

internal/ethapi/api.go

+13-3
Original file line numberDiff line numberDiff line change
@@ -1117,12 +1117,13 @@ type accessListResult struct {
11171117

11181118
// CreateAccessList creates an EIP-2930 type AccessList for the given transaction.
11191119
// Reexec and BlockNrOrHash can be specified to create the accessList on top of a certain state.
1120-
func (api *BlockChainAPI) CreateAccessList(ctx context.Context, args TransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash) (*accessListResult, error) {
1120+
// StateOverrides can be used to create the accessList while taking into account state changes from previous transactions.
1121+
func (api *BlockChainAPI) CreateAccessList(ctx context.Context, args TransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash, stateOverrides *override.StateOverride) (*accessListResult, error) {
11211122
bNrOrHash := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
11221123
if blockNrOrHash != nil {
11231124
bNrOrHash = *blockNrOrHash
11241125
}
1125-
acl, gasUsed, vmerr, err := AccessList(ctx, api.b, bNrOrHash, args)
1126+
acl, gasUsed, vmerr, err := AccessList(ctx, api.b, bNrOrHash, args, stateOverrides)
11261127
if err != nil {
11271128
return nil, err
11281129
}
@@ -1136,13 +1137,22 @@ func (api *BlockChainAPI) CreateAccessList(ctx context.Context, args Transaction
11361137
// AccessList creates an access list for the given transaction.
11371138
// If the accesslist creation fails an error is returned.
11381139
// If the transaction itself fails, an vmErr is returned.
1139-
func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrHash, args TransactionArgs) (acl types.AccessList, gasUsed uint64, vmErr error, err error) {
1140+
func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrHash, args TransactionArgs, stateOverrides *override.StateOverride) (acl types.AccessList, gasUsed uint64, vmErr error, err error) {
11401141
// Retrieve the execution context
11411142
db, header, err := b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
11421143
if db == nil || err != nil {
11431144
return nil, 0, nil, err
11441145
}
11451146

1147+
// Apply state overrides immediately after StateAndHeaderByNumberOrHash.
1148+
// If not applied here, there could be cases where user-specified overrides (e.g., nonce)
1149+
// may conflict with default values from the database, leading to inconsistencies.
1150+
if stateOverrides != nil {
1151+
if err := stateOverrides.Apply(db, nil); err != nil {
1152+
return nil, 0, nil, err
1153+
}
1154+
}
1155+
11461156
// Ensure any missing fields are filled, extract the recipient and input data
11471157
if err = args.setFeeDefaults(ctx, b, header); err != nil {
11481158
return nil, 0, nil, err

internal/ethapi/api_test.go

+73
Original file line numberDiff line numberDiff line change
@@ -3529,3 +3529,76 @@ func testRPCResponseWithFile(t *testing.T, testid int, result interface{}, rpc s
35293529
func addressToHash(a common.Address) common.Hash {
35303530
return common.BytesToHash(a.Bytes())
35313531
}
3532+
3533+
func TestCreateAccessListWithStateOverrides(t *testing.T) {
3534+
// Initialize test backend
3535+
genesis := &core.Genesis{
3536+
Config: params.TestChainConfig,
3537+
Alloc: types.GenesisAlloc{
3538+
common.HexToAddress("0x71562b71999873db5b286df957af199ec94617f7"): {Balance: big.NewInt(1000000000000000000)},
3539+
},
3540+
}
3541+
backend := newTestBackend(t, 1, genesis, ethash.NewFaker(), nil)
3542+
3543+
// Create a new BlockChainAPI instance
3544+
api := NewBlockChainAPI(backend)
3545+
3546+
// Create test contract code - a simple storage contract
3547+
//
3548+
// SPDX-License-Identifier: MIT
3549+
// pragma solidity ^0.8.0;
3550+
//
3551+
// contract SimpleStorage {
3552+
// uint256 private value;
3553+
//
3554+
// function retrieve() public view returns (uint256) {
3555+
// return value;
3556+
// }
3557+
// }
3558+
var (
3559+
contractCode = hexutil.Bytes(common.Hex2Bytes("6080604052348015600f57600080fd5b506004361060285760003560e01c80632e64cec114602d575b600080fd5b60336047565b604051603e91906067565b60405180910390f35b60008054905090565b6000819050919050565b6061816050565b82525050565b6000602082019050607a6000830184605a565b9291505056"))
3560+
// Create state overrides with more complete state
3561+
contractAddr = common.HexToAddress("0x1234567890123456789012345678901234567890")
3562+
nonce = hexutil.Uint64(1)
3563+
overrides = &override.StateOverride{
3564+
contractAddr: override.OverrideAccount{
3565+
Code: &contractCode,
3566+
Balance: (*hexutil.Big)(big.NewInt(1000000000000000000)),
3567+
Nonce: &nonce,
3568+
State: map[common.Hash]common.Hash{
3569+
common.Hash{}: common.HexToHash("0x000000000000000000000000000000000000000000000000000000000000002a"),
3570+
},
3571+
},
3572+
}
3573+
)
3574+
3575+
// Create transaction arguments with gas and value
3576+
var (
3577+
from = common.HexToAddress("0x71562b71999873db5b286df957af199ec94617f7")
3578+
data = hexutil.Bytes(common.Hex2Bytes("2e64cec1")) // retrieve()
3579+
gas = hexutil.Uint64(100000)
3580+
args = TransactionArgs{
3581+
From: &from,
3582+
To: &contractAddr,
3583+
Data: &data,
3584+
Gas: &gas,
3585+
Value: new(hexutil.Big),
3586+
}
3587+
)
3588+
// Call CreateAccessList
3589+
result, err := api.CreateAccessList(context.Background(), args, nil, overrides)
3590+
if err != nil {
3591+
t.Fatalf("Failed to create access list: %v", err)
3592+
}
3593+
if err != nil || result == nil {
3594+
t.Fatalf("Failed to create access list: %v", err)
3595+
}
3596+
require.NotNil(t, result.Accesslist)
3597+
3598+
// Verify access list contains the contract address and storage slot
3599+
expected := &types.AccessList{{
3600+
Address: contractAddr,
3601+
StorageKeys: []common.Hash{{}},
3602+
}}
3603+
require.Equal(t, expected, result.Accesslist)
3604+
}

0 commit comments

Comments
 (0)