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​
- 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 transactiontransactionIndex
- Position in the blockblockHash
- Hash of the blockblockNumber
- Block numberfrom
- Sender addressto
- Receiver address (null for contract creation)cumulativeGasUsed
- Total gas used in block up to this transactiongasUsed
- Gas used by this specific transactioneffectiveGasPrice
- Actual gas price paidcontractAddress
- Created contract address (if contract creation)logs
- Array of log objects from eventslogsBloom
- Bloom filter for logsstatus
-0x1
(success) or0x0
(failure)type
- Transaction typel1Fee
- L1 data posting fee (Base specific)l1GasPrice
- L1 gas price used (Base specific)l1GasUsed
- L1 gas consumed (Base specific)
Implementation Examples​
- JavaScript
- Python
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');
}
}
from web3 import Web3
from eth_utils import event_signature_to_log_topic
import json
import time
from typing import Dict, List, Any, Optional
w3 = Web3(Web3.HTTPProvider('https://api-base-mainnet.n.dwellir.com/YOUR_API_KEY'))
class ReceiptAnalyzer:
"""Analyze and process transaction receipts on Base"""
def __init__(self, w3_instance):
self.w3 = w3_instance
def get_receipt_details(self, tx_hash: str) -> Optional[Dict[str, Any]]:
"""Get comprehensive receipt details"""
try:
receipt = self.w3.eth.get_transaction_receipt(tx_hash)
if not receipt:
return None
return {
'transaction_hash': receipt['transactionHash'].hex(),
'status': 'success' if receipt['status'] == 1 else 'failed',
'block_number': receipt['blockNumber'],
'block_hash': receipt['blockHash'].hex(),
'from': receipt['from'],
'to': receipt.get('to'),
'contract_address': receipt.get('contractAddress'),
'gas_used': receipt['gasUsed'],
'effective_gas_price': receipt.get('effectiveGasPrice', 0),
'cumulative_gas_used': receipt['cumulativeGasUsed'],
'logs_count': len(receipt['logs']),
'transaction_index': receipt['transactionIndex'],
'type': receipt.get('type', 0),
# Base L2 specific
'l1_fee': receipt.get('l1Fee'),
'l1_gas_price': receipt.get('l1GasPrice'),
'l1_gas_used': receipt.get('l1GasUsed')
}
except Exception as e:
return {'error': str(e), 'tx_hash': tx_hash}
def decode_logs(self, tx_hash: str, abi: List[Dict]) -> List[Dict[str, Any]]:
"""Decode event logs from receipt"""
receipt = self.w3.eth.get_transaction_receipt(tx_hash)
if not receipt:
return []
# Create contract instance for decoding
contract = self.w3.eth.contract(abi=abi)
decoded_logs = []
for log in receipt['logs']:
try:
# Try to decode the log
decoded = contract.events[log['topics'][0]].process_log(log)
decoded_logs.append({
'event': decoded['event'],
'args': dict(decoded['args']),
'address': log['address'],
'block_number': log['blockNumber'],
'transaction_index': log['transactionIndex'],
'log_index': log['logIndex']
})
except:
# Could not decode this log with provided ABI
decoded_logs.append({
'event': 'Unknown',
'topics': [t.hex() for t in log['topics']],
'data': log['data'],
'address': log['address']
})
return decoded_logs
def monitor_erc20_events(self, tx_hash: str) -> Dict[str, Any]:
"""Monitor ERC20 token events in transaction"""
# Standard ERC20 events
transfer_topic = self.w3.keccak(text="Transfer(address,address,uint256)").hex()
approval_topic = self.w3.keccak(text="Approval(address,address,uint256)").hex()
receipt = self.w3.eth.get_transaction_receipt(tx_hash)
if not receipt:
return {'status': 'no_receipt'}
transfers = []
approvals = []
for log in receipt['logs']:
if len(log['topics']) > 0:
topic0 = log['topics'][0].hex()
if topic0 == transfer_topic and len(log['topics']) == 3:
# Decode Transfer event
transfers.append({
'token': log['address'],
'from': '0x' + log['topics'][1].hex()[26:],
'to': '0x' + log['topics'][2].hex()[26:],
'value': int(log['data'], 16) if log['data'] != '0x' else 0,
'block': log['blockNumber'],
'log_index': log['logIndex']
})
elif topic0 == approval_topic and len(log['topics']) == 3:
# Decode Approval event
approvals.append({
'token': log['address'],
'owner': '0x' + log['topics'][1].hex()[26:],
'spender': '0x' + log['topics'][2].hex()[26:],
'value': int(log['data'], 16) if log['data'] != '0x' else 0,
'block': log['blockNumber'],
'log_index': log['logIndex']
})
return {
'transaction_hash': tx_hash,
'status': 'success' if receipt['status'] == 1 else 'failed',
'transfers': transfers,
'approvals': approvals,
'total_events': len(transfers) + len(approvals)
}
def calculate_transaction_costs(self, tx_hash: str) -> Dict[str, Any]:
"""Calculate detailed transaction costs including L1 fees"""
receipt = self.w3.eth.get_transaction_receipt(tx_hash)
tx = self.w3.eth.get_transaction(tx_hash)
if not receipt or not tx:
return {'error': 'Transaction or receipt not found'}
# L2 gas costs
gas_used = receipt['gasUsed']
effective_gas_price = receipt.get('effectiveGasPrice', tx.get('gasPrice', 0))
l2_cost = gas_used * effective_gas_price
# L1 costs (Base specific)
l1_fee = receipt.get('l1Fee', 0)
# Total cost
total_cost = l2_cost + l1_fee
return {
'transaction_hash': tx_hash,
'gas_used': gas_used,
'gas_limit': tx['gas'],
'gas_efficiency': f"{(gas_used / tx['gas'] * 100):.2f}%",
'effective_gas_price_gwei': self.w3.from_wei(effective_gas_price, 'gwei'),
'l2_cost_eth': self.w3.from_wei(l2_cost, 'ether'),
'l1_cost_eth': self.w3.from_wei(l1_fee, 'ether'),
'total_cost_eth': self.w3.from_wei(total_cost, 'ether'),
'status': 'success' if receipt['status'] == 1 else 'failed'
}
def wait_for_receipt(
self,
tx_hash: str,
timeout: int = 60,
poll_interval: int = 2
) -> Optional[Dict[str, Any]]:
"""Wait for transaction receipt with timeout"""
start_time = time.time()
while time.time() - start_time < timeout:
try:
receipt = self.w3.eth.get_transaction_receipt(tx_hash)
if receipt:
return self.get_receipt_details(tx_hash)
except:
pass
time.sleep(poll_interval)
return None
# Usage examples
analyzer = ReceiptAnalyzer(w3)
# Get receipt details
receipt = analyzer.get_receipt_details(
"0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"
)
if receipt:
print(f"Status: {receipt['status']}")
print(f"Gas Used: {receipt['gas_used']}")
print(f"Block: {receipt['block_number']}")
# Calculate costs
costs = analyzer.calculate_transaction_costs(
"0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"
)
print(f"Total Cost: {costs['total_cost_eth']} ETH")
print(f"L1 Cost: {costs['l1_cost_eth']} ETH")
# Monitor token events
events = analyzer.monitor_erc20_events(
"0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"
)
print(f"Token Transfers: {len(events['transfers'])}")
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 Scenario | Description | Solution |
---|---|---|
null receipt | Transaction not mined yet | Wait and retry |
Status 0x0 | Transaction failed | Check revert reason |
Missing L1 fee data | Old transaction format | Handle 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.