Skip to main content

eth_getTransactionReceipt

Returns the receipt of a transaction by transaction hash. Provides execution status, gas consumption, and emitted logs.

When to Use This Method​

eth_getTransactionReceipt is essential for:

  • Transaction Confirmation - Verify successful execution
  • Event Monitoring - Access emitted logs and events
  • Gas Analysis - Track actual gas consumption
  • Contract Deployment - Get deployed contract addresses

Parameters​

  1. Transaction Hash - DATA, 32 Bytes
    • Hash of the executed transaction
    • Format: 0x followed by 64 hexadecimal characters
{
"jsonrpc": "2.0",
"method": "eth_getTransactionReceipt",
"params": [
"0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"
],
"id": 1
}

Returns​

Object - Receipt object, or null when no receipt was found:

  • transactionHash - Hash of the transaction
  • transactionIndex - Position in the block
  • blockHash - Hash of the block
  • blockNumber - Block number
  • from - Sender address
  • to - Receiver address (null for contract creation)
  • cumulativeGasUsed - Total gas used in block up to this transaction
  • gasUsed - Gas used by this specific transaction
  • effectiveGasPrice - Actual gas price paid
  • contractAddress - Created contract address (if contract creation)
  • logs - Array of log objects from events
  • logsBloom - Bloom filter for logs
  • status - 0x1 (success) or 0x0 (failure)
  • type - Transaction type
  • l1Fee - L1 data posting fee (Base specific)
  • l1GasPrice - L1 gas price used (Base specific)
  • l1GasUsed - L1 gas consumed (Base specific)

Implementation Examples​

import { JsonRpcProvider, Contract, ethers } from 'ethers';

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

// Enhanced receipt processor
class ReceiptProcessor {
constructor(provider) {
this.provider = provider;
}

async getReceipt(txHash) {
const receipt = await this.provider.getTransactionReceipt(txHash);

if (!receipt) {
return null;
}

return {
hash: receipt.hash,
status: receipt.status === 1 ? 'success' : 'failed',
blockNumber: receipt.blockNumber,
blockHash: receipt.blockHash,
from: receipt.from,
to: receipt.to,
contractAddress: receipt.contractAddress,
gasUsed: receipt.gasUsed.toString(),
effectiveGasPrice: receipt.effectiveGasPrice.toString(),
cumulativeGasUsed: receipt.cumulativeGasUsed.toString(),
logs: receipt.logs.length,
type: receipt.type,
// Base L2 specific fields
l1Fee: receipt.l1Fee?.toString(),
l1GasPrice: receipt.l1GasPrice?.toString(),
l1GasUsed: receipt.l1GasUsed?.toString()
};
}

async parseEvents(txHash, abi) {
const receipt = await this.provider.getTransactionReceipt(txHash);

if (!receipt) {
throw new Error('Receipt not found');
}

const iface = new ethers.Interface(abi);
const events = [];

for (const log of receipt.logs) {
try {
const parsed = iface.parseLog({
topics: log.topics,
data: log.data
});

events.push({
name: parsed.name,
signature: parsed.signature,
args: Object.fromEntries(
Object.entries(parsed.args).filter(([key]) => isNaN(key))
),
address: log.address,
blockNumber: log.blockNumber,
transactionIndex: log.transactionIndex,
logIndex: log.logIndex
});
} catch {
// Not an event from this ABI
events.push({
name: 'Unknown',
topics: log.topics,
data: log.data,
address: log.address
});
}
}

return events;
}

async calculateTotalCost(txHash) {
const [receipt, tx] = await Promise.all([
this.provider.getTransactionReceipt(txHash),
this.provider.getTransaction(txHash)
]);

if (!receipt || !tx) {
throw new Error('Transaction or receipt not found');
}

const l2GasCost = receipt.gasUsed * receipt.effectiveGasPrice;
const l1GasCost = receipt.l1Fee || 0n;
const totalCost = l2GasCost + l1GasCost;

return {
l2Cost: ethers.formatEther(l2GasCost),
l1Cost: ethers.formatEther(l1GasCost),
totalCost: ethers.formatEther(totalCost),
gasUsed: receipt.gasUsed.toString(),
effectiveGasPrice: ethers.formatGwei(receipt.effectiveGasPrice),
status: receipt.status === 1 ? 'success' : 'failed'
};
}

async waitForReceipt(txHash, confirmations = 1, timeout = 60000) {
const startTime = Date.now();

while (Date.now() - startTime < timeout) {
const receipt = await this.provider.getTransactionReceipt(txHash);

if (receipt) {
const currentBlock = await this.provider.getBlockNumber();
const confirmationCount = currentBlock - receipt.blockNumber;

if (confirmationCount >= confirmations) {
return receipt;
}
}

await new Promise(resolve => setTimeout(resolve, 2000));
}

throw new Error(`Receipt not found within ${timeout}ms`);
}
}

// ERC20 Transfer event monitoring
async function monitorTokenTransfers(txHash) {
const processor = new ReceiptProcessor(provider);

const ERC20_ABI = [
"event Transfer(address indexed from, address indexed to, uint256 value)",
"event Approval(address indexed owner, address indexed spender, uint256 value)"
];

const events = await processor.parseEvents(txHash, ERC20_ABI);

const transfers = events.filter(e => e.name === 'Transfer');

for (const transfer of transfers) {
console.log(`Transfer detected:`);
console.log(` From: ${transfer.args.from}`);
console.log(` To: ${transfer.args.to}`);
console.log(` Amount: ${ethers.formatUnits(transfer.args.value, 18)}`);
console.log(` Token: ${transfer.address}`);
}

return transfers;
}

// Contract deployment tracking
async function trackDeployment(txHash) {
const processor = new ReceiptProcessor(provider);
const receipt = await processor.waitForReceipt(txHash);

if (receipt.contractAddress) {
console.log('Contract deployed at:', receipt.contractAddress);

// Verify deployment
const code = await provider.getCode(receipt.contractAddress);
const isDeployed = code !== '0x';

return {
success: receipt.status === 1,
address: receipt.contractAddress,
deploymentCost: await processor.calculateTotalCost(txHash),
verified: isDeployed,
blockNumber: receipt.blockNumber
};
} else {
throw new Error('Not a contract deployment transaction');
}
}

Common Use Cases​

1. Smart Contract Event Monitoring​

// Monitor DeFi protocol events
async function monitorDeFiEvents(txHash) {
const DEFI_ABI = [
"event Deposit(address indexed user, uint256 amount, uint256 shares)",
"event Withdraw(address indexed user, uint256 amount, uint256 shares)",
"event Swap(address indexed user, address tokenIn, address tokenOut, uint256 amountIn, uint256 amountOut)"
];

const processor = new ReceiptProcessor(provider);
const events = await processor.parseEvents(txHash, DEFI_ABI);

for (const event of events) {
switch(event.name) {
case 'Deposit':
console.log(`User ${event.args.user} deposited ${event.args.amount}`);
break;
case 'Withdraw':
console.log(`User ${event.args.user} withdrew ${event.args.amount}`);
break;
case 'Swap':
console.log(`Swap: ${event.args.amountIn} ${event.args.tokenIn} -> ${event.args.amountOut} ${event.args.tokenOut}`);
break;
}
}

return events;
}

2. Failed Transaction Debugging​

// Debug failed transactions
async function debugFailedTransaction(txHash) {
const receipt = await provider.getTransactionReceipt(txHash);

if (!receipt) {
return { error: 'Receipt not found' };
}

if (receipt.status === 1) {
return { status: 'success' };
}

// Get transaction details for more context
const tx = await provider.getTransaction(txHash);

// Try to decode revert reason
try {
const result = await provider.call({
to: tx.to,
from: tx.from,
data: tx.data,
value: tx.value,
gasLimit: tx.gasLimit
}, tx.blockNumber - 1);
} catch (error) {
return {
status: 'failed',
gasUsed: receipt.gasUsed.toString(),
gasLimit: tx.gasLimit.toString(),
revertReason: error.reason || error.message,
block: receipt.blockNumber
};
}
}

3. Multi-Transaction Batch Analysis​

// Analyze batch of transactions
async function analyzeBatch(txHashes) {
const processor = new ReceiptProcessor(provider);
const results = [];

for (const hash of txHashes) {
const receipt = await processor.getReceipt(hash);
const cost = await processor.calculateTotalCost(hash);

results.push({
hash: hash,
status: receipt?.status,
gasUsed: receipt?.gasUsed,
totalCost: cost?.totalCost,
l1Cost: cost?.l1Cost,
blockNumber: receipt?.blockNumber
});
}

// Calculate statistics
const successful = results.filter(r => r.status === 'success').length;
const totalGas = results.reduce((sum, r) => sum + BigInt(r.gasUsed || 0), 0n);

return {
transactions: results,
statistics: {
total: txHashes.length,
successful: successful,
failed: txHashes.length - successful,
totalGasUsed: totalGas.toString()
}
};
}

Error Handling​

Error ScenarioDescriptionSolution
null receiptTransaction not mined yetWait and retry
Status 0x0Transaction failedCheck revert reason
Missing L1 fee dataOld transaction formatHandle gracefully
async function robustGetReceipt(txHash, maxRetries = 10) {
for (let i = 0; i < maxRetries; i++) {
try {
const receipt = await provider.getTransactionReceipt(txHash);

if (receipt) {
// Ensure all fields are present
return {
...receipt,
l1Fee: receipt.l1Fee || 0n,
l1GasPrice: receipt.l1GasPrice || 0n,
l1GasUsed: receipt.l1GasUsed || 0n,
effectiveGasPrice: receipt.effectiveGasPrice || receipt.gasPrice
};
}

// Exponential backoff
await new Promise(resolve =>
setTimeout(resolve, Math.min(1000 * Math.pow(2, i), 30000))
);
} catch (error) {
if (i === maxRetries - 1) throw error;
}
}

return null;
}

Need help? Contact our support team or check the Base documentation.