Docs

eth_getBlockReceipts - Ink RPC Method

Return every transaction receipt in a block on Ink. Useful for indexers, analytics pipelines, and event backfills across low-fee DeFi applications, cross-chain liquidity, and EVM-compatible smart contracts.

Returns all transaction receipts for a block on Ink. This is more efficient than calling eth_getTransactionReceipt once per transaction when you already know the target block.

Why Ink? Build on Kraken's DeFi-focused Ethereum L2 built on the OP Stack and connected to the Optimism Superchain with 1s block times, ETH gas, Kraken-backed infrastructure, OP Stack compatibility, and Superchain interoperability.

When to Use This Method

eth_getBlockReceipts is useful for Ink developers, DeFi builders, and teams deploying Solidity applications on the Superchain:

  • Indexer Backfills: Pull every receipt in a block with one request instead of looping over transaction hashes
  • Event Collection: Scan all logs emitted by a block when building analytics or data pipelines
  • Settlement Auditing: Verify every transaction outcome in a target block for low-fee DeFi applications, cross-chain liquidity, and EVM-compatible smart contracts
  • Operational Debugging: Compare receipt-level gas usage, status, and logs across multiple transactions at once

Common Use Cases

1. Backfill Transaction Receipts for an Indexer

When bootstrapping an indexer for Ink, use eth_getBlockReceipts to backfill historical receipt data efficiently. One RPC call per block replaces dozens of individual eth_getTransactionReceipt calls.

JavaScript
import { JsonRpcProvider } from 'ethers';

const provider = new JsonRpcProvider('https://api-ink-mainnet.n.dwellir.com/YOUR_API_KEY');

async function backfillReceipts(startBlock, endBlock) {
  const receipts = {};

  for (let i = startBlock; i <= endBlock; i++) {
    const hexBlock = '0x' + i.toString(16);
    const results = await provider.send('eth_getBlockReceipts', [hexBlock]);

    if (results) {
      for (const receipt of results) {
        receipts[receipt.transactionHash] = {
          block: i,
          status: receipt.status === '0x1' ? 'success' : 'failed',
          gasUsed: parseInt(receipt.gasUsed, 16),
          logCount: receipt.logs.length,
        };
      }
    }
    console.log(`Backfilled block ${i}: ${results ? results.length : 0} receipts`);
  }

  return receipts;
}

backfillReceipts(10000000, 10000050);

2. Audit Gas Usage Across All Transactions in a Range

Compute total gas consumption and identify high-gas transactions within a target block range on Ink. This is useful for gas cost analysis and identifying optimization targets in smart contract usage.

Python
from web3 import Web3

w3 = Web3(Web3.HTTPProvider('https://api-ink-mainnet.n.dwellir.com/YOUR_API_KEY'))

def audit_gas_usage(block_identifier):
    response = w3.provider.make_request(
        'eth_getBlockReceipts', [block_identifier]
    )

    receipts = response.get('result')
    if not receipts:
        print(f'No receipts found for block {block_identifier}')
        return

    total_gas = 0
    for receipt in receipts:
        gas = int(receipt['gasUsed'], 16)
        total_gas += gas
        if gas > 500_000:
            print(f'High gas tx: {receipt["transactionHash"]} used {gas:,} gas')

    print(f'Block {block_identifier}: {len(receipts)} txs, '
          f'total gas {total_gas:,}')

audit_gas_usage('0x4da3692d55759ca2fa35e8093aaedf76b1075e5c2d6346365e318c153f0327db')

3. Extract Contract Creation Events from Deployment Blocks

When monitoring contract deployments on Kraken's DeFi-focused Ethereum L2 built on the OP Stack and connected to the Optimism Superchain, use eth_getBlockReceipts to scan for receipts where contractAddress is non-null. This identifies all new contract deployments within a block in a single call.

Go
package main

import (
    "context"
    "fmt"
    "log"

    "github.com/ethereum/go-ethereum/rpc"
)

func main() {
    client, _ := rpc.Dial("https://api-ink-mainnet.n.dwellir.com/YOUR_API_KEY")

    var receipts []map[string]interface{}
    err := client.CallContext(
        context.Background(),
        &receipts,
        "eth_getBlockReceipts",
        "0x4da3692d55759ca2fa35e8093aaedf76b1075e5c2d6346365e318c153f0327db",
    )
    if err != nil {
        log.Fatal(err)
    }

    for _, r := range receipts {
        contractAddr, ok := r["contractAddress"]
        if ok && contractAddr != nil {
            fmt.Printf("Contract deployed: %s\n", contractAddr)
            fmt.Printf("  Creator: %s\n", r["from"])
            fmt.Printf("  Tx hash: %s\n", r["transactionHash"])
        }
    }
}

Best Practices

  • Use block hash instead of block number for deterministic results: Hash-based lookups guarantee you are querying the exact block intended, even if chain reorganizations shift block numbers
  • Paginate large receipt arrays client-side: Blocks with thousands of transactions return large payloads; paginate processing to avoid memory pressure in your application
  • Cache individual receipt data per transaction hash: Receipts are immutable once a block is finalized, so cache them indefinitely for repeated lookups
  • For historical blocks, archive nodes may return more complete receipt data: Full nodes may prune older state; archive nodes retain complete historical receipt information

Code Examples

Error Handling

Error CodeMessageDescription
-32602Invalid paramsThe block identifier is malformed
-32000Header not foundThe referenced block does not exist on the node