Skip to content
Open
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,16 @@ 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
* (evm) [#728](https://github.com/crypto-org-chain/ethermint/pull/728) feat: support preinstalls
* (evm) [#722](https://github.com/crypto-org-chain/ethermint/pull/722) feat: support EIP-2935
* (rpc) [#764](https://github.com/crypto-org-chain/ethermint/pull/764) rpc: apply state overrides to eth_estimateGas
* (api) [#768](https://github.com/crypto-org-chain/ethermint/pull/768) feat: support create access list


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

Expand Down
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
18 changes: 18 additions & 0 deletions rpc/backend/backend_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package backend

import (
"bufio"
sdkmath "cosmossdk.io/math"
"math/big"
"os"
"path/filepath"
Expand Down Expand Up @@ -194,3 +195,20 @@ func (suite *BackendTestSuite) signAndEncodeEthTx(msgEthereumTx *evmtypes.MsgEth

return txBz
}

func (suite *BackendTestSuite) SetupMockCLient() {
c := suite.backend.clientCtx.Client.(*mocks.Client)
_, err := RegisterBlockResults(c, 1)
suite.Require().NoError(err)
height := rpctypes.NewBlockNumber(big.NewInt(1)).Int64()
_, err = RegisterHeader(c, &height, nil)
suite.Require().NoError(err)
RegisterHeaderByHashAny(c)
RegisterABCIQueryAny(c, 1)

queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterParamsAny(queryClient)
RegisterBaseFee(queryClient, sdkmath.NewInt(1))
validator := sdk.AccAddress(tests.GenerateAddress().Bytes())
RegisterValidatorAccount(queryClient, validator)
}
3 changes: 3 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 {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this check here within the nonce check?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line below requires non null

nonce, _ := b.getAccountNonce(*args.From, true, 0, b.logger)

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
116 changes: 83 additions & 33 deletions rpc/backend/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,57 +35,67 @@ var _ tmrpcclient.Client = &mocks.Client{}
func RegisterTxSearch(client *mocks.Client, query string, txBz []byte) {
resulTxs := []*tmrpctypes.ResultTx{{Tx: txBz}}
client.On("TxSearch", rpc.ContextWithHeight(1), query, false, (*int)(nil), (*int)(nil), "").
Return(&tmrpctypes.ResultTxSearch{Txs: resulTxs, TotalCount: 1}, nil)
Return(&tmrpctypes.ResultTxSearch{Txs: resulTxs, TotalCount: 1}, nil).
Maybe()
}

func RegisterTxSearchEmpty(client *mocks.Client, query string) {
client.On("TxSearch", rpc.ContextWithHeight(1), query, false, (*int)(nil), (*int)(nil), "").
Return(&tmrpctypes.ResultTxSearch{}, nil)
Return(&tmrpctypes.ResultTxSearch{}, nil).
Maybe()
}

func RegisterTxSearchError(client *mocks.Client, query string) {
client.On("TxSearch", rpc.ContextWithHeight(1), query, false, (*int)(nil), (*int)(nil), "").
Return(nil, errortypes.ErrInvalidRequest)
Return(nil, errortypes.ErrInvalidRequest).
Maybe()
}

// Broadcast Tx
func RegisterBroadcastTx(client *mocks.Client, tx types.Tx) {
client.On("BroadcastTxSync", context.Background(), tx).
Return(&tmrpctypes.ResultBroadcastTx{}, nil)
Return(&tmrpctypes.ResultBroadcastTx{}, nil).
Maybe()
}

func RegisterBroadcastTxError(client *mocks.Client, tx types.Tx) {
client.On("BroadcastTxSync", context.Background(), tx).
Return(nil, errortypes.ErrInvalidRequest)
Return(nil, errortypes.ErrInvalidRequest).
Maybe()
}

// Unconfirmed Transactions
func RegisterUnconfirmedTxs(client *mocks.Client, limit *int, txs []types.Tx) {
client.On("UnconfirmedTxs", rpc.ContextWithHeight(1), limit).
Return(&tmrpctypes.ResultUnconfirmedTxs{Txs: txs}, nil)
Return(&tmrpctypes.ResultUnconfirmedTxs{Txs: txs}, nil).
Maybe()
}

func RegisterUnconfirmedTxsEmpty(client *mocks.Client, limit *int) {
client.On("UnconfirmedTxs", rpc.ContextWithHeight(1), limit).
Return(&tmrpctypes.ResultUnconfirmedTxs{
Txs: make([]types.Tx, 2),
}, nil)
}, nil).
Maybe()
}

func RegisterUnconfirmedTxsError(client *mocks.Client, limit *int) {
client.On("UnconfirmedTxs", rpc.ContextWithHeight(1), limit).
Return(nil, errortypes.ErrInvalidRequest)
Return(nil, errortypes.ErrInvalidRequest).
Maybe()
}

// Status
func RegisterStatus(client *mocks.Client) {
client.On("Status", rpc.ContextWithHeight(1)).
Return(&tmrpctypes.ResultStatus{}, nil)
Return(&tmrpctypes.ResultStatus{}, nil).
Maybe()
}

func RegisterStatusError(client *mocks.Client) {
client.On("Status", rpc.ContextWithHeight(1)).
Return(nil, errortypes.ErrInvalidRequest)
Return(nil, errortypes.ErrInvalidRequest).
Maybe()
}

// Block
Expand All @@ -97,7 +107,8 @@ func RegisterBlockMultipleTxs(
block := types.MakeBlock(height, txs, nil, nil)
block.ChainID = ChainID
resBlock := &tmrpctypes.ResultBlock{Block: block}
client.On("Block", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).Return(resBlock, nil)
client.On("Block", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).Return(resBlock, nil).
Maybe()
return resBlock, nil
}

Expand All @@ -111,22 +122,25 @@ func RegisterBlock(
emptyBlock := types.MakeBlock(height, []types.Tx{}, nil, nil)
emptyBlock.ChainID = ChainID
resBlock := &tmrpctypes.ResultBlock{Block: emptyBlock}
client.On("Block", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).Return(resBlock, nil)
client.On("Block", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).Return(resBlock, nil).
Maybe()
return resBlock, nil
}

// with tx
block := types.MakeBlock(height, []types.Tx{tx}, nil, nil)
block.ChainID = ChainID
resBlock := &tmrpctypes.ResultBlock{Block: block}
client.On("Block", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).Return(resBlock, nil)
client.On("Block", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).Return(resBlock, nil).
Maybe()
return resBlock, nil
}

// Block returns error
func RegisterBlockError(client *mocks.Client, height int64) {
client.On("Block", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).
Return(nil, errortypes.ErrInvalidRequest)
Return(nil, errortypes.ErrInvalidRequest).
Maybe()
}

// Block not found
Expand All @@ -135,7 +149,8 @@ func RegisterBlockNotFound(
height int64,
) (*tmrpctypes.ResultBlock, error) {
client.On("Block", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).
Return(&tmrpctypes.ResultBlock{Block: nil}, nil)
Return(&tmrpctypes.ResultBlock{Block: nil}, nil).
Maybe()

return &tmrpctypes.ResultBlock{Block: nil}, nil
}
Expand All @@ -145,7 +160,8 @@ func RegisterBlockPanic(client *mocks.Client, height int64) {
client.On("Block", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).
Return(func(context.Context, *int64) *tmrpctypes.ResultBlock {
panic("Block call panic")
}, nil)
}, nil).
Maybe()
}

func TestRegisterBlock(t *testing.T) {
Expand All @@ -166,12 +182,14 @@ func TestRegisterBlock(t *testing.T) {
func RegisterConsensusParams(client *mocks.Client, height int64) {
consensusParams := types.DefaultConsensusParams()
client.On("ConsensusParams", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).
Return(&tmrpctypes.ResultConsensusParams{ConsensusParams: *consensusParams}, nil)
Return(&tmrpctypes.ResultConsensusParams{ConsensusParams: *consensusParams}, nil).
Maybe()
}

func RegisterConsensusParamsError(client *mocks.Client, height int64) {
client.On("ConsensusParams", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).
Return(nil, errortypes.ErrInvalidRequest)
Return(nil, errortypes.ErrInvalidRequest).
Maybe()
}

func TestRegisterConsensusParams(t *testing.T) {
Expand Down Expand Up @@ -209,7 +227,8 @@ func RegisterBlockResultsWithEventLog(client *mocks.Client, height int64) (*tmrp
}

client.On("BlockResults", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).
Return(res, nil)
Return(res, nil).
Maybe()
return res, nil
}

Expand All @@ -223,13 +242,15 @@ func RegisterBlockResults(
}

client.On("BlockResults", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).
Return(res, nil)
Return(res, nil).
Maybe()
return res, nil
}

func RegisterBlockResultsError(client *mocks.Client, height int64) {
client.On("BlockResults", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).
Return(nil, errortypes.ErrInvalidRequest)
Return(nil, errortypes.ErrInvalidRequest).
Maybe()
}

func TestRegisterBlockResults(t *testing.T) {
Expand All @@ -256,18 +277,21 @@ func RegisterBlockByHash(
resBlock := &tmrpctypes.ResultBlock{Block: block}

client.On("BlockByHash", rpc.ContextWithHeight(1), []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}).
Return(resBlock, nil)
Return(resBlock, nil).
Maybe()
return resBlock, nil
}

func RegisterBlockByHashError(client *mocks.Client, hash common.Hash, tx []byte) {
client.On("BlockByHash", rpc.ContextWithHeight(1), []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}).
Return(nil, errortypes.ErrInvalidRequest)
Return(nil, errortypes.ErrInvalidRequest).
Maybe()
}

func RegisterBlockByHashNotFound(client *mocks.Client, hash common.Hash, tx []byte) {
client.On("BlockByHash", rpc.ContextWithHeight(1), []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}).
Return(nil, nil)
Return(nil, nil).
Maybe()
}

// HeaderByHash
Expand All @@ -280,36 +304,47 @@ func RegisterHeaderByHash(
resHeader := &tmrpctypes.ResultHeader{Header: &block.Header}

client.On("HeaderByHash", rpc.ContextWithHeight(1), bytes.HexBytes(hash.Bytes())).
Return(resHeader, nil)
Return(resHeader, nil).
Maybe()
return resHeader, nil
}

func RegisterHeaderByHashError(client *mocks.Client, hash common.Hash, tx []byte) {
client.On("HeaderByHash", rpc.ContextWithHeight(1), bytes.HexBytes(hash.Bytes())).
Return(nil, errortypes.ErrInvalidRequest)
Return(nil, errortypes.ErrInvalidRequest).
Maybe()
}

func RegisterHeaderByHashNotFound(client *mocks.Client, hash common.Hash, tx []byte) {
client.On("HeaderByHash", rpc.ContextWithHeight(1), bytes.HexBytes(hash.Bytes())).
Return(&tmrpctypes.ResultHeader{Header: nil}, nil)
Return(&tmrpctypes.ResultHeader{Header: nil}, nil).
Maybe()
}

func RegisterHeaderByHashAny(client *mocks.Client) {
client.On("HeaderByHash", mock.Anything, mock.Anything).
Return(&tmrpctypes.ResultHeader{Header: &types.Header{Height: 1}}, nil).Maybe()
}

// Header
func RegisterHeader(client *mocks.Client, height *int64, tx []byte) (*tmrpctypes.ResultHeader, error) {
block := types.MakeBlock(*height, []types.Tx{tx}, nil, nil)
resHeader := &tmrpctypes.ResultHeader{Header: &block.Header}
client.On("Header", rpc.ContextWithHeight(*height), height).Return(resHeader, nil)
client.On("Header", rpc.ContextWithHeight(*height), height).Return(resHeader, nil).
Maybe()
return resHeader, nil
}

func RegisterHeaderError(client *mocks.Client, height *int64) {
client.On("Header", rpc.ContextWithHeight(*height), height).Return(nil, errortypes.ErrInvalidRequest)
client.On("Header", rpc.ContextWithHeight(*height), height).Return(nil, errortypes.ErrInvalidRequest).
Maybe()
}

// Header not found
func RegisterHeaderNotFound(client *mocks.Client, height int64) {
client.On("Header", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).
Return(&tmrpctypes.ResultHeader{Header: nil}, nil)
Return(&tmrpctypes.ResultHeader{Header: nil}, nil).
Maybe()
}

func RegisterABCIQueryWithOptions(client *mocks.Client, height int64, path string, data bytes.HexBytes, opts tmrpcclient.ABCIQueryOptions) {
Expand All @@ -319,12 +354,26 @@ func RegisterABCIQueryWithOptions(client *mocks.Client, height int64, path strin
Value: []byte{2}, // TODO replace with data.Bytes(),
Height: height,
},
}, nil)
}, nil).
Maybe()
}

func RegisterABCIQueryWithOptionsError(clients *mocks.Client, path string, data bytes.HexBytes, opts tmrpcclient.ABCIQueryOptions) {
clients.On("ABCIQueryWithOptions", context.Background(), path, data, opts).
Return(nil, errortypes.ErrInvalidRequest)
Return(nil, errortypes.ErrInvalidRequest).
Maybe()
}

func RegisterABCIQueryAny(client *mocks.Client, height int64) {
client.On("ABCIQueryWithOptions", context.Background(), mock.Anything, mock.Anything, mock.Anything).
Return(&tmrpctypes.ResultABCIQuery{
Response: abci.ResponseQuery{
Value: []byte{2}, // TODO replace with data.Bytes(),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

todo not done?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah not sure, just copying from above

Height: height,
},
}, nil).
Maybe()

}

func RegisterABCIQueryAccount(clients *mocks.Client, data bytes.HexBytes, opts tmrpcclient.ABCIQueryOptions, acc client.Account) {
Expand All @@ -338,5 +387,6 @@ func RegisterABCIQueryAccount(clients *mocks.Client, data bytes.HexBytes, opts t
Value: respBz,
Height: 1,
},
}, nil)
}, nil).
Maybe()
}
Loading
Loading