diff --git a/rpc/contracts/direct_backend.go b/rpc/contracts/direct_backend.go index d58b567d7fa..0d0d0186fd7 100644 --- a/rpc/contracts/direct_backend.go +++ b/rpc/contracts/direct_backend.go @@ -48,7 +48,8 @@ func NewDirectBackend(api jsonrpc.EthAPI) DirectBackend { } func (b DirectBackend) CodeAt(ctx context.Context, account common.Address, blockNum *uint256.Int) ([]byte, error) { - return b.api.GetCode(ctx, account, BlockNumArg(blockNum)) + blockNrOrHash := BlockNumArg(blockNum) + return b.api.GetCode(ctx, account, &blockNrOrHash) } func (b DirectBackend) CallContract(ctx context.Context, callMsg bind.CallMsg, blockNum *uint256.Int) ([]byte, error) { @@ -59,11 +60,13 @@ func (b DirectBackend) CallContract(ctx context.Context, callMsg bind.CallMsg, b } func (b DirectBackend) PendingCodeAt(ctx context.Context, account common.Address) ([]byte, error) { - return b.api.GetCode(ctx, account, PendingBlockNumArg()) + blockNrOrHash := PendingBlockNumArg() + return b.api.GetCode(ctx, account, &blockNrOrHash) } func (b DirectBackend) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) { - count, err := b.api.GetTransactionCount(ctx, account, PendingBlockNumArg()) + blockNrOrHash := PendingBlockNumArg() + count, err := b.api.GetTransactionCount(ctx, account, &blockNrOrHash) if err != nil { return 0, err } @@ -79,7 +82,8 @@ func (b DirectBackend) NonceAt(ctx context.Context, account common.Address, bloc blockRef = rpc.BlockNumber(blockNumber.Int64()).AsBlockReference() } - count, err := b.api.GetTransactionCount(ctx, account, rpc.BlockNumberOrHash(blockRef)) + blockNrOrHash := rpc.BlockNumberOrHash(blockRef) + count, err := b.api.GetTransactionCount(ctx, account, &blockNrOrHash) if err != nil { return 0, err } diff --git a/rpc/jsonrpc/corner_cases_support_test.go b/rpc/jsonrpc/corner_cases_support_test.go index 22a8670b129..1642fb42d3c 100644 --- a/rpc/jsonrpc/corner_cases_support_test.go +++ b/rpc/jsonrpc/corner_cases_support_test.go @@ -83,7 +83,7 @@ func TestNotFoundMustReturnError(t *testing.T) { api := newEthApiForTest(newBaseApiForTest(m), m.DB, nil, nil) ctx := context.Background() - a, err := api.GetBalance(ctx, common.Address{}, rpc.BlockNumberOrHashWithNumber(10_000)) + a, err := api.GetBalance(ctx, common.Address{}, bnhPtr(rpc.BlockNumberOrHashWithNumber(10_000))) assertions.Nil(a) assertions.EqualError(err, "block not found: 10000") } diff --git a/rpc/jsonrpc/eth_accounts.go b/rpc/jsonrpc/eth_accounts.go index 3c1facaa2d9..a08bd6d70c5 100644 --- a/rpc/jsonrpc/eth_accounts.go +++ b/rpc/jsonrpc/eth_accounts.go @@ -73,7 +73,8 @@ func (api *APIImpl) stateReaderAt(ctx context.Context, blockNrOrHash rpc.BlockNu } // GetBalance implements eth_getBalance. Returns the balance of an account for a given address. -func (api *APIImpl) GetBalance(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (*hexutil.Big, error) { +func (api *APIImpl) GetBalance(ctx context.Context, address common.Address, blockNrOrHashArg *rpc.BlockNumberOrHash) (*hexutil.Big, error) { + blockNrOrHash := orLatest(blockNrOrHashArg) tx, reader, err := api.stateReaderAt(ctx, blockNrOrHash) if err != nil { return nil, err @@ -93,7 +94,8 @@ func (api *APIImpl) GetBalance(ctx context.Context, address common.Address, bloc } // GetTransactionCount implements eth_getTransactionCount. Returns the number of transactions sent from an address (the nonce). -func (api *APIImpl) GetTransactionCount(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (*hexutil.Uint64, error) { +func (api *APIImpl) GetTransactionCount(ctx context.Context, address common.Address, blockNrOrHashArg *rpc.BlockNumberOrHash) (*hexutil.Uint64, error) { + blockNrOrHash := orLatest(blockNrOrHashArg) if blockNrOrHash.BlockNumber != nil && *blockNrOrHash.BlockNumber == rpc.PendingBlockNumber { reply, err := api.txPool.Nonce(ctx, &txpoolproto.NonceRequest{ Address: gointerfaces.ConvertAddressToH160(address), @@ -122,7 +124,8 @@ func (api *APIImpl) GetTransactionCount(ctx context.Context, address common.Addr } // GetCode implements eth_getCode. Returns the byte code at a given address (if it's a smart contract). -func (api *APIImpl) GetCode(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (hexutil.Bytes, error) { +func (api *APIImpl) GetCode(ctx context.Context, address common.Address, blockNrOrHashArg *rpc.BlockNumberOrHash) (hexutil.Bytes, error) { + blockNrOrHash := orLatest(blockNrOrHashArg) tx, reader, err := api.stateReaderAt(ctx, blockNrOrHash) if err != nil { return nil, err @@ -143,7 +146,8 @@ func (api *APIImpl) GetCode(ctx context.Context, address common.Address, blockNr // GetStorageValues implements eth_getStorageValues. Returns the values of multiple // storage slots for multiple accounts in a single request. -func (api *APIImpl) GetStorageValues(ctx context.Context, requests map[common.Address][]common.Hash, blockNrOrHash rpc.BlockNumberOrHash) (map[common.Address][]hexutil.Bytes, error) { +func (api *APIImpl) GetStorageValues(ctx context.Context, requests map[common.Address][]common.Hash, blockNrOrHashArg *rpc.BlockNumberOrHash) (map[common.Address][]hexutil.Bytes, error) { + blockNrOrHash := orLatest(blockNrOrHashArg) var totalSlots int for _, keys := range requests { @@ -204,7 +208,8 @@ func (api *APIImpl) GetStorageValues(ctx context.Context, requests map[common.Ad } // GetStorageAt implements eth_getStorageAt. Returns the value from a storage position at a given address. -func (api *APIImpl) GetStorageAt(ctx context.Context, address common.Address, index string, blockNrOrHash rpc.BlockNumberOrHash) (string, error) { +func (api *APIImpl) GetStorageAt(ctx context.Context, address common.Address, index string, blockNrOrHashArg *rpc.BlockNumberOrHash) (string, error) { + blockNrOrHash := orLatest(blockNrOrHashArg) var empty []byte // Validation for index i.e. storage slot is non-standard: it can be interpreted as QUANTITY (stricter) or as DATA (like Hive tests do). // Waiting for a spec, we choose the latter because it's more general, but we check that the length is not greater than 64 hex-digits. diff --git a/rpc/jsonrpc/eth_api.go b/rpc/jsonrpc/eth_api.go index 3b1131f0664..9a657b6c8a6 100644 --- a/rpc/jsonrpc/eth_api.go +++ b/rpc/jsonrpc/eth_api.go @@ -97,11 +97,11 @@ type EthAPI interface { // Account related (see ./eth_accounts.go) Accounts(ctx context.Context) ([]common.Address, error) - GetBalance(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (*hexutil.Big, error) - GetTransactionCount(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (*hexutil.Uint64, error) - GetStorageAt(ctx context.Context, address common.Address, index string, blockNrOrHash rpc.BlockNumberOrHash) (string, error) - GetStorageValues(ctx context.Context, requests map[common.Address][]common.Hash, blockNrOrHash rpc.BlockNumberOrHash) (map[common.Address][]hexutil.Bytes, error) - GetCode(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (hexutil.Bytes, error) + GetBalance(ctx context.Context, address common.Address, blockNrOrHash *rpc.BlockNumberOrHash) (*hexutil.Big, error) + GetTransactionCount(ctx context.Context, address common.Address, blockNrOrHash *rpc.BlockNumberOrHash) (*hexutil.Uint64, error) + GetStorageAt(ctx context.Context, address common.Address, index string, blockNrOrHash *rpc.BlockNumberOrHash) (string, error) + GetStorageValues(ctx context.Context, requests map[common.Address][]common.Hash, blockNrOrHash *rpc.BlockNumberOrHash) (map[common.Address][]hexutil.Bytes, error) + GetCode(ctx context.Context, address common.Address, blockNrOrHash *rpc.BlockNumberOrHash) (hexutil.Bytes, error) // System related (see ./eth_system.go) BlockNumber(ctx context.Context) (hexutil.Uint64, error) @@ -125,7 +125,7 @@ type EthAPI interface { SendTransaction(_ context.Context, txObject any) (common.Hash, error) Sign(ctx context.Context, _ common.Address, _ hexutil.Bytes) (hexutil.Bytes, error) SignTransaction(_ context.Context, txObject any) (common.Hash, error) - GetProof(ctx context.Context, address common.Address, storageKeys []hexutil.Bytes, blockNr rpc.BlockNumberOrHash) (*accounts.AccProofResult, error) + GetProof(ctx context.Context, address common.Address, storageKeys []hexutil.Bytes, blockNr *rpc.BlockNumberOrHash) (*accounts.AccProofResult, error) CreateAccessList(ctx context.Context, args ethapi.CallArgs, blockNrOrHash *rpc.BlockNumberOrHash, overrides *ethapi2.StateOverrides, optimizeGas *bool) (*accessListResult, error) // Mining related (see ./eth_mining.go) diff --git a/rpc/jsonrpc/eth_api_test.go b/rpc/jsonrpc/eth_api_test.go index f7bf4c41b1d..cdc7ef8fc9c 100644 --- a/rpc/jsonrpc/eth_api_test.go +++ b/rpc/jsonrpc/eth_api_test.go @@ -113,7 +113,7 @@ func TestGetStorageAt_ByBlockNumber_WithRequireCanonicalDefault(t *testing.T) { api := newEthApiForTest(newBaseApiForTest(m), m.DB, nil, nil) addr := common.HexToAddress("0x71562b71999873db5b286df957af199ec94617f7") - result, err := api.GetStorageAt(context.Background(), addr, "0x0", rpc.BlockNumberOrHashWithNumber(0)) + result, err := api.GetStorageAt(context.Background(), addr, "0x0", bnhPtr(rpc.BlockNumberOrHashWithNumber(0))) if err != nil { t.Errorf("calling GetStorageAt: %v", err) } @@ -127,7 +127,7 @@ func TestGetStorageAt_ByBlockHash_WithRequireCanonicalDefault(t *testing.T) { api := newEthApiForTest(newBaseApiForTest(m), m.DB, nil, nil) addr := common.HexToAddress("0x71562b71999873db5b286df957af199ec94617f7") - result, err := api.GetStorageAt(context.Background(), addr, "0x0", rpc.BlockNumberOrHashWithHash(m.Genesis.Hash(), false)) + result, err := api.GetStorageAt(context.Background(), addr, "0x0", bnhPtr(rpc.BlockNumberOrHashWithHash(m.Genesis.Hash(), false))) if err != nil { t.Errorf("calling GetStorageAt: %v", err) } @@ -141,7 +141,7 @@ func TestGetStorageAt_ByBlockHash_WithRequireCanonicalTrue(t *testing.T) { api := newEthApiForTest(newBaseApiForTest(m), m.DB, nil, nil) addr := common.HexToAddress("0x71562b71999873db5b286df957af199ec94617f7") - result, err := api.GetStorageAt(context.Background(), addr, "0x0", rpc.BlockNumberOrHashWithHash(m.Genesis.Hash(), true)) + result, err := api.GetStorageAt(context.Background(), addr, "0x0", bnhPtr(rpc.BlockNumberOrHashWithHash(m.Genesis.Hash(), true))) if err != nil { t.Errorf("calling GetStorageAt: %v", err) } @@ -164,7 +164,7 @@ func TestGetStorageAt_ByBlockHash_WithRequireCanonicalDefault_BlockNotFoundError } offChainBlock := offChain.Blocks[0] - if _, err := api.GetStorageAt(context.Background(), addr, "0x0", rpc.BlockNumberOrHashWithHash(offChainBlock.Hash(), false)); err != nil { + if _, err := api.GetStorageAt(context.Background(), addr, "0x0", bnhPtr(rpc.BlockNumberOrHashWithHash(offChainBlock.Hash(), false))); err != nil { if fmt.Sprintf("%v", err) != fmt.Sprintf("block not found: %s", offChainBlock.Hash().String()) { t.Errorf("wrong error: %v", err) } @@ -185,7 +185,7 @@ func TestGetStorageAt_ByBlockHash_WithRequireCanonicalTrue_BlockNotFoundError(t } offChainBlock := offChain.Blocks[0] - if _, err := api.GetStorageAt(context.Background(), addr, "0x0", rpc.BlockNumberOrHashWithHash(offChainBlock.Hash(), true)); err != nil { + if _, err := api.GetStorageAt(context.Background(), addr, "0x0", bnhPtr(rpc.BlockNumberOrHashWithHash(offChainBlock.Hash(), true))); err != nil { if fmt.Sprintf("%v", err) != fmt.Sprintf("block not found: %s", offChainBlock.Hash().String()) { t.Errorf("wrong error: %v", err) } @@ -202,7 +202,7 @@ func TestGetStorageAt_ByBlockHash_WithRequireCanonicalDefault_NonCanonicalBlock( orphanedBlock := orphanedChain[0].Blocks[0] - result, err := api.GetStorageAt(context.Background(), addr, "0x0", rpc.BlockNumberOrHashWithHash(orphanedBlock.Hash(), false)) + result, err := api.GetStorageAt(context.Background(), addr, "0x0", bnhPtr(rpc.BlockNumberOrHashWithHash(orphanedBlock.Hash(), false))) if err != nil { if fmt.Sprintf("%v", err) != fmt.Sprintf("hash %s is not currently canonical", orphanedBlock.Hash().String()[2:]) { t.Errorf("wrong error: %v", err) @@ -221,7 +221,7 @@ func TestGetStorageAt_ByBlockHash_WithRequireCanonicalTrue_NonCanonicalBlock(t * orphanedBlock := orphanedChain[0].Blocks[0] - if _, err := api.GetStorageAt(context.Background(), addr, "0x0", rpc.BlockNumberOrHashWithHash(orphanedBlock.Hash(), true)); err != nil { + if _, err := api.GetStorageAt(context.Background(), addr, "0x0", bnhPtr(rpc.BlockNumberOrHashWithHash(orphanedBlock.Hash(), true))); err != nil { if fmt.Sprintf("%v", err) != fmt.Sprintf("hash %s is not currently canonical", orphanedBlock.Hash().String()[2:]) { t.Errorf("wrong error: %v", err) } @@ -302,7 +302,7 @@ func TestGetStorageValues_HappyPath(t *testing.T) { result, err := api.GetStorageValues(context.Background(), map[common.Address][]common.Hash{ addr1: {slot0, slot1}, - }, latest) + }, &latest) if err != nil { t.Fatalf("unexpected error: %v", err) } @@ -329,7 +329,7 @@ func TestGetStorageValues_MultipleAddresses(t *testing.T) { addr2: {slot1, slot2}, addr3: {slot0, slot2}, } - result, err := api.GetStorageValues(context.Background(), request, latest) + result, err := api.GetStorageValues(context.Background(), request, &latest) if err != nil { t.Fatalf("unexpected error: %v", err) } @@ -356,7 +356,7 @@ func TestGetStorageValues_MissingSlotReturnsZero(t *testing.T) { result, err := api.GetStorageValues(context.Background(), map[common.Address][]common.Hash{ addr1: {common.HexToHash("0xff")}, - }, latest) + }, &latest) if err != nil { t.Fatalf("unexpected error: %v", err) } @@ -371,7 +371,7 @@ func TestGetStorageValues_EmptyRequestReturnsError(t *testing.T) { latest := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber) - _, err := api.GetStorageValues(context.Background(), map[common.Address][]common.Hash{}, latest) + _, err := api.GetStorageValues(context.Background(), map[common.Address][]common.Hash{}, &latest) if err == nil { t.Fatal("expected error for empty request") } @@ -394,7 +394,7 @@ func TestGetStorageValues_ExceedingSlotLimitReturnsError(t *testing.T) { _, err := api.GetStorageValues(context.Background(), map[common.Address][]common.Hash{ addr1: tooMany, - }, latest) + }, &latest) if err == nil { t.Fatal("expected error for exceeding slot limit") } @@ -411,7 +411,7 @@ func TestGetStorageValues_ByBlockHash_NonCanonicalBlock(t *testing.T) { _, err := api.GetStorageValues(context.Background(), map[common.Address][]common.Hash{ addr1: {common.Hash{}}, - }, blockNumberOrHash) + }, &blockNumberOrHash) if err != nil { if fmt.Sprintf("%v", err) != fmt.Sprintf("hash %s is not currently canonical", orphanedBlock.Hash().String()[2:]) { t.Errorf("wrong error: %v", err) @@ -432,7 +432,7 @@ func TestGetStorageValues_ByBlockHash_WithRequireCanonicalTrue_NonCanonicalBlock _, err := api.GetStorageValues(context.Background(), map[common.Address][]common.Hash{ addr1: {common.Hash{}}, - }, blockNumberOrHash) + }, &blockNumberOrHash) if err != nil { if fmt.Sprintf("%v", err) != fmt.Sprintf("hash %s is not currently canonical", orphanedBlock.Hash().String()[2:]) { t.Errorf("wrong error: %v", err) @@ -453,8 +453,62 @@ func TestGetStorageValues_PrunedBlockReturnsError(t *testing.T) { _, err := api.GetStorageValues(context.Background(), map[common.Address][]common.Hash{ addr1: {common.Hash{}}, - }, blockNumberOrHash) + }, &blockNumberOrHash) if err != nil { t.Logf("got expected prune error: %v", err) } } + +// bnhPtr returns a pointer to a BlockNumberOrHash, for the state methods whose +// block parameter is now optional (*rpc.BlockNumberOrHash). +func bnhPtr(b rpc.BlockNumberOrHash) *rpc.BlockNumberOrHash { return &b } + +// TestStateMethods_OmittedBlockDefaultsToLatest verifies that an omitted (nil) +// block selector is treated identically to an explicit "latest" selector for each +// state method (per execution-apis: the Block parameter is optional, default +// 'latest'). This exercises the orLatest(nil) path directly. +func TestStateMethods_OmittedBlockDefaultsToLatest(t *testing.T) { + a := assert.New(t) + m, _, _ := rpcdaemontest.CreateTestExecModule(t) + api := newEthApiForTest(newBaseApiForTest(m), m.DB, nil, nil) + ctx := context.Background() + addr := common.HexToAddress("0x71562b71999873db5b286df957af199ec94617f7") + latest := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber) + + balNil, err := api.GetBalance(ctx, addr, nil) + a.NoError(err) + balLatest, err := api.GetBalance(ctx, addr, &latest) + a.NoError(err) + a.Equal(balLatest, balNil) + + codeNil, err := api.GetCode(ctx, addr, nil) + a.NoError(err) + codeLatest, err := api.GetCode(ctx, addr, &latest) + a.NoError(err) + a.Equal(codeLatest, codeNil) + + nonceNil, err := api.GetTransactionCount(ctx, addr, nil) + a.NoError(err) + nonceLatest, err := api.GetTransactionCount(ctx, addr, &latest) + a.NoError(err) + a.Equal(nonceLatest, nonceNil) + + storageNil, err := api.GetStorageAt(ctx, addr, "0x0", nil) + a.NoError(err) + storageLatest, err := api.GetStorageAt(ctx, addr, "0x0", &latest) + a.NoError(err) + a.Equal(storageLatest, storageNil) + + proofNil, err := api.GetProof(ctx, addr, nil, nil) + a.NoError(err) + proofLatest, err := api.GetProof(ctx, addr, nil, &latest) + a.NoError(err) + a.Equal(proofLatest, proofNil) + + req := map[common.Address][]common.Hash{addr: {{}}} + svNil, err := api.GetStorageValues(ctx, req, nil) + a.NoError(err) + svLatest, err := api.GetStorageValues(ctx, req, &latest) + a.NoError(err) + a.Equal(svLatest, svNil) +} diff --git a/rpc/jsonrpc/eth_call.go b/rpc/jsonrpc/eth_call.go index b221f681752..3735633660a 100644 --- a/rpc/jsonrpc/eth_call.go +++ b/rpc/jsonrpc/eth_call.go @@ -56,6 +56,16 @@ import ( var latestNumOrHash = rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber) +// orLatest resolves an optional block selector, defaulting to the latest block +// when the caller omitted the parameter (nil). Used by the state-reading methods +// whose Block parameter is optional per execution-apis (default 'latest'). +func orLatest(blockNrOrHash *rpc.BlockNumberOrHash) rpc.BlockNumberOrHash { + if blockNrOrHash != nil { + return *blockNrOrHash + } + return latestNumOrHash +} + const ( // estimateGasErrorRatio is the amount of overestimation eth_estimateGas is // allowed to produce in order to speed up calculations. @@ -398,7 +408,8 @@ type StorageKeysInfo struct { } // GetProof implements eth_getProof partially; Proofs are available only with the `latest` block tag. -func (api *APIImpl) GetProof(ctx context.Context, address common.Address, storageKeys []hexutil.Bytes, blockNrOrHash rpc.BlockNumberOrHash) (*accounts.AccProofResult, error) { +func (api *APIImpl) GetProof(ctx context.Context, address common.Address, storageKeys []hexutil.Bytes, blockNrOrHashArg *rpc.BlockNumberOrHash) (*accounts.AccProofResult, error) { + blockNrOrHash := orLatest(blockNrOrHashArg) if len(storageKeys) > maxGetProofKeys { return nil, &rpc.CustomError{ Message: fmt.Sprintf("too many storage keys requested (max %d, got %d)", maxGetProofKeys, len(storageKeys)), diff --git a/rpc/jsonrpc/eth_call_test.go b/rpc/jsonrpc/eth_call_test.go index 9d625dd1ec2..463a2332cc1 100644 --- a/rpc/jsonrpc/eth_call_test.go +++ b/rpc/jsonrpc/eth_call_test.go @@ -357,7 +357,7 @@ func TestGetProof(t *testing.T) { context.Background(), tt.addr, tt.storageKeys, - rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(tt.blockNum)), + bnhPtr(rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(tt.blockNum))), ) if tt.expectedErr != "" { require.EqualError(t, err, tt.expectedErr) diff --git a/rpc/mcp/mcp.go b/rpc/mcp/mcp.go index fb5dbfe6096..b067a7dec7d 100644 --- a/rpc/mcp/mcp.go +++ b/rpc/mcp/mcp.go @@ -514,7 +514,7 @@ func (e *ErigonMCPServer) handleGetBlockTransactionCountByHash(ctx context.Conte func (e *ErigonMCPServer) handleGetBalance(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { addr := common.HexToAddress(req.GetString("address", "")) blockNumOrHash, _ := parseBlockNumberOrHash(req.GetString("blockNumber", "latest")) - balance, err := e.ethAPI.GetBalance(ctx, addr, blockNumOrHash) + balance, err := e.ethAPI.GetBalance(ctx, addr, &blockNumOrHash) if err != nil { return mcp.NewToolResultError(err.Error()), nil } @@ -630,7 +630,7 @@ func (e *ErigonMCPServer) handleGetLogs(ctx context.Context, req mcp.CallToolReq func (e *ErigonMCPServer) handleGetCode(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { addr := common.HexToAddress(req.GetString("address", "")) blockNumOrHash, _ := parseBlockNumberOrHash(req.GetString("blockNumber", "latest")) - code, err := e.ethAPI.GetCode(ctx, addr, blockNumOrHash) + code, err := e.ethAPI.GetCode(ctx, addr, &blockNumOrHash) if err != nil { return mcp.NewToolResultError(err.Error()), nil } @@ -644,7 +644,7 @@ func (e *ErigonMCPServer) handleGetStorageAt(ctx context.Context, req mcp.CallTo addr := common.HexToAddress(req.GetString("address", "")) pos := req.GetString("position", "0x0") blockNumOrHash, _ := parseBlockNumberOrHash(req.GetString("blockNumber", "latest")) - result, err := e.ethAPI.GetStorageAt(ctx, addr, pos, blockNumOrHash) + result, err := e.ethAPI.GetStorageAt(ctx, addr, pos, &blockNumOrHash) if err != nil { return mcp.NewToolResultError(err.Error()), nil } @@ -672,7 +672,7 @@ func (e *ErigonMCPServer) handleGetStorageValues(ctx context.Context, req mcp.Ca requests[addr] = hashes } - result, err := e.ethAPI.GetStorageValues(ctx, requests, blockNumOrHash) + result, err := e.ethAPI.GetStorageValues(ctx, requests, &blockNumOrHash) if err != nil { return mcp.NewToolResultError(err.Error()), nil } @@ -691,7 +691,7 @@ func (e *ErigonMCPServer) handleGetStorageValues(ctx context.Context, req mcp.Ca func (e *ErigonMCPServer) handleGetTransactionCount(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { addr := common.HexToAddress(req.GetString("address", "")) blockNumOrHash, _ := parseBlockNumberOrHash(req.GetString("blockNumber", "latest")) - count, err := e.ethAPI.GetTransactionCount(ctx, addr, blockNumOrHash) + count, err := e.ethAPI.GetTransactionCount(ctx, addr, &blockNumOrHash) if err != nil { return mcp.NewToolResultError(err.Error()), nil } @@ -817,7 +817,7 @@ func (e *ErigonMCPServer) handleGetProof(ctx context.Context, req mcp.CallToolRe } } blockNumOrHash, _ := parseBlockNumberOrHash(req.GetString("blockNumber", "latest")) - result, err := e.ethAPI.GetProof(ctx, addr, keys, blockNumOrHash) + result, err := e.ethAPI.GetProof(ctx, addr, keys, &blockNumOrHash) if err != nil { return mcp.NewToolResultError(err.Error()), nil } diff --git a/rpc/mcp/resources.go b/rpc/mcp/resources.go index a35c853d8d7..66095591463 100644 --- a/rpc/mcp/resources.go +++ b/rpc/mcp/resources.go @@ -204,9 +204,10 @@ func (e *ErigonMCPServer) handleResourceAddressSummary(ctx context.Context, req // This is a simplified example - you'd need proper URI parsing address := req.Params.URI // Would extract {address} parameter - balance, _ := e.ethAPI.GetBalance(ctx, common.HexToAddress(address), rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)) - nonce, _ := e.ethAPI.GetTransactionCount(ctx, common.HexToAddress(address), rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)) - code, _ := e.ethAPI.GetCode(ctx, common.HexToAddress(address), rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)) + latest := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber) + balance, _ := e.ethAPI.GetBalance(ctx, common.HexToAddress(address), &latest) + nonce, _ := e.ethAPI.GetTransactionCount(ctx, common.HexToAddress(address), &latest) + code, _ := e.ethAPI.GetCode(ctx, common.HexToAddress(address), &latest) summary := map[string]any{ "address": address,