Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ Ref: https://keepachangelog.com/en/1.0.0/

## Unreleased

### Features

* (evm) [#725](https://github.com/crypto-org-chain/ethermint/pull/725) feat(RPC): add authorizationList from eth_getTransactionByHash response for EIP-7702 transactions
* (evm) [#740](https://github.com/crypto-org-chain/ethermint/pull/740) fix: missing tx context during vm initialisation
* (evm) [#742](https://github.com/crypto-org-chain/ethermint/pull/742) fix: prevent nil pointer dereference in tracer hooks
Expand All @@ -45,6 +47,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (rpc) [#764](https://github.com/crypto-org-chain/ethermint/pull/764) rpc: apply state overrides to eth_estimateGas
* (ante) [#775](https://github.com/crypto-org-chain/ethermint/pull/775) fix: race condition in antecache
* (ante) [#789](https://github.com/crypto-org-chain/ethermint/pull/789) fix: add check on evm transaction tip
* (api) [#768](https://github.com/crypto-org-chain/ethermint/pull/768) feat: support create access list

## [v0.22.0] - 2025-08-12

Expand Down
11 changes: 11 additions & 0 deletions proto/ethermint/evm/v1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ service Query {
rpc BaseFee(QueryBaseFeeRequest) returns (QueryBaseFeeResponse) {
option (google.api.http).get = "/ethermint/evm/v1/base_fee";
}

// CreateAccessList implement `eth_createAccessList` rpc call
rpc CreateAccessList(EthCallRequest) returns (CreateAccessListResponse) {
option (google.api.http).get = "/ethermint/evm/v1/create_access_list";
}
}

// QueryAccountRequest is the request type for the Query/Account RPC method.
Expand Down Expand Up @@ -338,3 +343,9 @@ message QueryBaseFeeResponse {
// base_fee is the EIP1559 base fee
string base_fee = 1 [(gogoproto.customtype) = "cosmossdk.io/math.Int"];
}

// CreateAccessListResponse defines CreateAccessList response
message CreateAccessListResponse {
// data is the response serialized in bytes
bytes data = 1;
}
5 changes: 5 additions & 0 deletions rpc/backend/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,11 @@ type EVMBackend interface {
GetTransactionReceipt(hash common.Hash, resBlock *tmrpctypes.ResultBlock) (map[string]interface{}, error)
GetTransactionByBlockHashAndIndex(hash common.Hash, idx hexutil.Uint) (*rpctypes.RPCTransaction, error)
GetTransactionByBlockNumberAndIndex(blockNum rpctypes.BlockNumber, idx hexutil.Uint) (*rpctypes.RPCTransaction, error)
CreateAccessList(
args evmtypes.TransactionArgs,
blockNrOrHash rpctypes.BlockNumberOrHash,
overrides *json.RawMessage,
) (*rpctypes.AccessListResult, error)

// Send Transaction
Resend(args evmtypes.TransactionArgs, gasPrice *hexutil.Big, gasLimit *hexutil.Uint64) (common.Hash, error)
Expand Down
66 changes: 66 additions & 0 deletions rpc/backend/call_tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,9 @@ func (b *Backend) SetTxDefaults(args evmtypes.TransactionArgs) (evmtypes.Transac
args.Value = new(hexutil.Big)
}
if args.Nonce == nil {
if args.From == nil {
return args, errors.New("missing from in argument")
}
// get the nonce from the account retriever
// ignore error in case tge account doesn't exist yet
nonce, _ := b.getAccountNonce(*args.From, true, 0, b.logger)
Expand Down Expand Up @@ -461,3 +464,66 @@ func (b *Backend) GasPrice() (*hexutil.Big, error) {

return (*hexutil.Big)(result), nil
}

// CreateAccessListCall performs a simulated call operation through the evmtypes. It returns the
// estimated gas used on the operation or an error if fails.
func (b *Backend) CreateAccessListCall(
args evmtypes.TransactionArgs,
blockNr rpctypes.BlockNumber,
overrides *json.RawMessage,
) (*evmtypes.AccessListResult, error) {
bz, err := json.Marshal(&args)
if err != nil {
return nil, err
}
header, err := b.TendermintHeaderByNumber(blockNr)
if err != nil {
// the error message imitates geth behavior
return nil, errors.New("header not found")
}
var bzOverrides []byte
if overrides != nil {
bzOverrides = *overrides
}

req := evmtypes.EthCallRequest{
Args: bz,
GasCap: b.RPCGasCap(),
ProposerAddress: sdk.ConsAddress(header.Header.ProposerAddress),
ChainId: b.chainID.Int64(),
Overrides: bzOverrides,
}

// From ContextWithHeight: if the provided height is 0,
// it will return an empty context and the gRPC query will use
// the latest block height for querying.
ctx := rpctypes.ContextWithHeight(blockNr.Int64())
timeout := b.RPCEVMTimeout()

// Setup context so it may be canceled the call has completed
// or, in case of unmetered gas, setup a context with a timeout.
var cancel context.CancelFunc
if timeout > 0 {
ctx, cancel = context.WithTimeout(ctx, timeout)
} else {
ctx, cancel = context.WithCancel(ctx)
}

// Make sure the context is canceled when the call has completed
// this makes sure resources are cleaned up.
defer cancel()

res, err := b.queryClient.CreateAccessList(ctx, &req)
if err != nil {
b.logger.Error("error access list call", "err", err)
return nil, err
}
if res == nil {
return nil, errors.New("result is nul")
}
var accessListResult evmtypes.AccessListResult
if err := json.Unmarshal(res.GetData(), &accessListResult); err != nil {
return nil, err
}
return &accessListResult, nil
}
Loading
Loading