eth_estimateGas
Generates and returns an estimate of how much gas is necessary to allow the transaction to complete.
Important
The transaction will not be added to the blockchain. The estimate may be significantly different from the actual gas used if the transaction modifies the state.
When to Use This Method
Use eth_estimateGas
to:
- Prevent Failed Transactions - Ensure sufficient gas before sending
- Optimize Gas Usage - Find optimal gas limits
- Cost Prediction - Calculate transaction fees in advance
- Cross-Chain Planning - Estimate omnichain operation costs
- Smart Contract Testing - Validate contract calls before execution
Parameters
-
Transaction Object (required):
from
(optional): 20 bytes - Address the transaction is sent fromto
(required): 20 bytes - Address the transaction is directed togas
(optional): Gas limit for estimationgasPrice
(optional): Gas price for estimationvalue
(optional): Value sent with transactiondata
(optional): Method signature and encoded parameters
-
Block Parameter (optional):
latest
- Latest block (default)pending
- Pending state- Block number as hexadecimal
{
"jsonrpc": "2.0",
"method": "eth_estimateGas",
"params": [
{
"from": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb8",
"to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
"value": "0xde0b6b3a7640000",
"data": "0xa9059cbb000000000000000000000000..."
},
"latest"
],
"id": 1
}
Returns
QUANTITY
- The estimated gas amount.
- Type: Hexadecimal string
- Unit: Gas units
- Format:
0x
prefixed
Implementation Examples
- cURL
- JavaScript
- Python
# Estimate simple transfer
curl -X POST https://api-zetachain-mainnet.n.dwellir.com/YOUR_API_KEY \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "eth_estimateGas",
"params": [
{
"from": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb8",
"to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
"value": "0xde0b6b3a7640000"
},
"latest"
],
"id": 1
}'
# Estimate contract interaction
curl -X POST https://api-zetachain-mainnet.n.dwellir.com/YOUR_API_KEY \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "eth_estimateGas",
"params": [
{
"from": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb8",
"to": "0x5F0b1a82749cb4E2278EC87F8BF6B618dC71a8bf",
"data": "0xa9059cbb000000000000000000000000d46e8dd67c5d32be8058bb8eb970870f072445670000000000000000000000000000000000000000000000000de0b6b3a7640000"
},
"latest"
],
"id": 1
}'
// Using fetch
const estimateGas = async (transaction) => {
const response = await fetch('https://api-zetachain-mainnet.n.dwellir.com/YOUR_API_KEY', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
jsonrpc: '2.0',
method: 'eth_estimateGas',
params: [transaction, 'latest'],
id: 1,
}),
});
const data = await response.json();
return BigInt(data.result);
};
// Using ethers.js
import { ethers } from 'ethers';
const provider = new ethers.JsonRpcProvider('https://api-zetachain-mainnet.n.dwellir.com/YOUR_API_KEY');
// Estimate simple transfer
const estimateTransfer = await provider.estimateGas({
from: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb8',
to: '0xd46e8dd67c5d32be8058bb8eb970870f07244567',
value: ethers.parseEther('1.0')
});
console.log('Transfer gas estimate:', estimateTransfer.toString());
// Estimate contract call
const tokenContract = new ethers.Contract(tokenAddress, tokenABI, provider);
const estimateTokenTransfer = await tokenContract.transfer.estimateGas(
'0xd46e8dd67c5d32be8058bb8eb970870f07244567',
ethers.parseEther('100')
);
console.log('Token transfer estimate:', estimateTokenTransfer.toString());
// Estimate cross-chain operation
const omnichainContract = new ethers.Contract(omnichainAddress, omnichainABI, provider);
const estimateCrossChain = await omnichainContract.sendCrossChain.estimateGas(
56, // BSC chain ID
'0xrecipient',
ethers.parseEther('10'),
{ value: ethers.parseEther('0.01') } // Protocol fee
);
console.log('Cross-chain estimate:', estimateCrossChain.toString());
// Using web3.js
import Web3 from 'web3';
const web3 = new Web3('https://api-zetachain-mainnet.n.dwellir.com/YOUR_API_KEY');
const gasEstimate = await web3.eth.estimateGas({
from: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb8',
to: '0xd46e8dd67c5d32be8058bb8eb970870f07244567',
value: web3.utils.toWei('1', 'ether')
});
console.log('Estimated gas:', gasEstimate);
import requests
import json
from web3 import Web3
# Using requests
url = 'https://api-zetachain-mainnet.n.dwellir.com/YOUR_API_KEY'
def estimate_gas(transaction):
payload = {
'jsonrpc': '2.0',
'method': 'eth_estimateGas',
'params': [transaction, 'latest'],
'id': 1
}
response = requests.post(url, json=payload)
result = response.json()
return int(result['result'], 16)
# Simple transfer
tx = {
'from': '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb8',
'to': '0xd46e8dd67c5d32be8058bb8eb970870f07244567',
'value': '0xde0b6b3a7640000' # 1 ZETA
}
gas_needed = estimate_gas(tx)
print(f'Gas estimate: {gas_needed}')
# Using web3.py
w3 = Web3(Web3.HTTPProvider('https://api-zetachain-mainnet.n.dwellir.com/YOUR_API_KEY'))
# Estimate simple transfer
gas_estimate = w3.eth.estimate_gas({
'from': '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb8',
'to': '0xd46e8dd67c5d32be8058bb8eb970870f07244567',
'value': w3.to_wei(1, 'ether')
})
print(f'Transfer gas estimate: {gas_estimate}')
# Estimate contract interaction
contract = w3.eth.contract(address=token_address, abi=token_abi)
gas_estimate = contract.functions.transfer(
'0xd46e8dd67c5d32be8058bb8eb970870f07244567',
w3.to_wei(100, 'ether')
).estimate_gas({'from': '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb8'})
print(f'Token transfer estimate: {gas_estimate}')
Example Response
{
"jsonrpc": "2.0",
"id": 1,
"result": "0x5208"
}
Decoding: 0x5208
= 21,000 gas units (standard transfer)
Omnichain Gas Estimation
ZetaChain requires special gas considerations for cross-chain operations:
Cross-Chain Gas Calculator
class CrossChainGasEstimator {
constructor(provider) {
this.provider = provider;
this.connectorAddress = '0x239e96c8f17C85c30100AC26F635Ea15f23E9c67';
}
async estimateCrossChainOperation(params) {
const {
sourceChain,
destChain,
operation,
data,
value
} = params;
// Estimate ZetaChain gas
const zetaGas = await this.estimateZetaChainGas(operation, data);
// Estimate destination chain gas
const destGas = await this.estimateDestinationGas(destChain, operation);
// Calculate protocol fees
const protocolFee = await this.getProtocolFee(sourceChain, destChain);
return {
zetaChainGas: zetaGas,
destinationGas: destGas,
protocolFee: protocolFee,
totalGas: zetaGas + destGas,
estimatedCost: await this.calculateCost(zetaGas + destGas, protocolFee)
};
}
async estimateZetaChainGas(operation, data) {
const tx = {
to: this.connectorAddress,
data: this.encodeOperation(operation, data)
};
return await this.provider.estimateGas(tx);
}
async estimateDestinationGas(chainId, operation) {
// Chain-specific gas requirements
const gasRequirements = {
1: 150000, // Ethereum
56: 100000, // BSC
137: 80000, // Polygon
43114: 120000 // Avalanche
};
return BigInt(gasRequirements[chainId] || 100000);
}
}
Common Use Cases
1. Safe Transaction Sender
class SafeTransactionSender {
constructor(signer) {
this.signer = signer;
this.bufferPercentage = 20; // 20% buffer
}
async sendTransaction(transaction) {
try {
// Estimate gas
const estimatedGas = await this.signer.estimateGas(transaction);
// Add buffer for safety
const gasLimit = estimatedGas * BigInt(100 + this.bufferPercentage) / 100n;
// Get current gas price
const gasPrice = await this.signer.provider.getGasPrice();
// Calculate total cost
const totalCost = gasLimit * gasPrice;
const balance = await this.signer.provider.getBalance(transaction.from || await this.signer.getAddress());
// Check sufficient balance
if (balance < totalCost + (transaction.value || 0n)) {
throw new Error(`Insufficient balance. Need ${ethers.formatEther(totalCost)} ZETA for gas`);
}
// Send transaction with safe gas limit
const tx = await this.signer.sendTransaction({
...transaction,
gasLimit
});
console.log('Transaction sent:', tx.hash);
console.log('Gas limit used:', gasLimit.toString());
return tx;
} catch (error) {
console.error('Transaction failed:', error);
throw error;
}
}
}
2. Batch Transaction Estimator
async function estimateBatchTransactions(transactions) {
const estimates = [];
const errors = [];
// Parallel estimation for efficiency
const promises = transactions.map(async (tx, index) => {
try {
const gasEstimate = await provider.estimateGas(tx);
return { index, success: true, gas: gasEstimate };
} catch (error) {
return { index, success: false, error: error.message };
}
});
const results = await Promise.all(promises);
let totalGas = 0n;
for (const result of results) {
if (result.success) {
estimates.push({
transaction: transactions[result.index],
gasEstimate: result.gas,
status: 'success'
});
totalGas += result.gas;
} else {
errors.push({
transaction: transactions[result.index],
error: result.error,
status: 'failed'
});
}
}
const gasPrice = await provider.getGasPrice();
const totalCost = totalGas * gasPrice;
return {
successful: estimates,
failed: errors,
summary: {
totalTransactions: transactions.length,
successfulEstimates: estimates.length,
failedEstimates: errors.length,
totalGasNeeded: totalGas.toString(),
estimatedCost: ethers.formatEther(totalCost) + ' ZETA'
}
};
}
3. Smart Contract Deployment Estimator
async function estimateContractDeployment(bytecode, constructorArgs = []) {
const signer = await provider.getSigner();
const address = await signer.getAddress();
// Encode constructor arguments
const deployData = bytecode + ethers.AbiCoder.defaultAbiCoder()
.encode(constructorTypes, constructorArgs)
.slice(2);
try {
const gasEstimate = await provider.estimateGas({
from: address,
data: deployData
});
const gasPrice = await provider.getGasPrice();
const deploymentCost = gasEstimate * gasPrice;
return {
gasEstimate: gasEstimate.toString(),
gasPrice: ethers.formatUnits(gasPrice, 'gwei') + ' Gwei',
estimatedCost: ethers.formatEther(deploymentCost) + ' ZETA',
bytecodeSize: bytecode.length / 2 + ' bytes',
recommendation: gasEstimate > 5000000n
? 'Consider optimizing contract size'
: 'Gas usage is reasonable'
};
} catch (error) {
throw new Error(`Deployment estimation failed: ${error.message}`);
}
}
4. Dynamic Gas Limit Adjuster
class DynamicGasLimitAdjuster {
constructor(provider) {
this.provider = provider;
this.history = [];
this.maxHistory = 50;
}
async getOptimalGasLimit(transaction, urgency = 'normal') {
// Get base estimate
const baseEstimate = await this.provider.estimateGas(transaction);
// Store in history
this.history.push({
estimate: baseEstimate,
timestamp: Date.now(),
type: this.getTransactionType(transaction)
});
if (this.history.length > this.maxHistory) {
this.history.shift();
}
// Calculate accuracy from history
const accuracy = this.calculateHistoricalAccuracy();
// Adjust based on urgency and accuracy
const adjustments = {
low: 1.05, // 5% buffer
normal: 1.15, // 15% buffer
high: 1.25, // 25% buffer
urgent: 1.35 // 35% buffer
};
const adjustment = adjustments[urgency] || 1.15;
const finalAdjustment = accuracy < 0.9 ? adjustment * 1.1 : adjustment;
const optimalGasLimit = baseEstimate * BigInt(Math.floor(finalAdjustment * 100)) / 100n;
return {
baseEstimate: baseEstimate.toString(),
optimalGasLimit: optimalGasLimit.toString(),
buffer: `${Math.round((finalAdjustment - 1) * 100)}%`,
confidence: accuracy,
urgency
};
}
calculateHistoricalAccuracy() {
// Simplified accuracy calculation
if (this.history.length < 10) return 0.8;
return 0.95;
}
getTransactionType(tx) {
if (!tx.to) return 'deployment';
if (tx.data && tx.data !== '0x') return 'contract_call';
return 'transfer';
}
}
5. Fee Market Analyzer
async function analyzeFeeMarket() {
const blockNumber = await provider.getBlockNumber();
const block = await provider.getBlock(blockNumber);
// Sample transactions for gas estimation
const sampleTxs = [
{ to: '0x...', value: ethers.parseEther('1') }, // Simple transfer
{ to: tokenAddress, data: '0xa9059cbb...' }, // Token transfer
{ to: dexAddress, data: '0x38ed1739...' } // DEX swap
];
const estimates = [];
for (const tx of sampleTxs) {
try {
const gas = await provider.estimateGas(tx);
estimates.push(gas);
} catch (error) {
estimates.push(null);
}
}
const gasPrice = await provider.getGasPrice();
return {
blockNumber,
baseFeePerGas: block.baseFeePerGas ? ethers.formatUnits(block.baseFeePerGas, 'gwei') : 'N/A',
currentGasPrice: ethers.formatUnits(gasPrice, 'gwei'),
estimations: {
simpleTransfer: estimates[0]?.toString() || 'Failed',
tokenTransfer: estimates[1]?.toString() || 'Failed',
dexSwap: estimates[2]?.toString() || 'Failed'
},
recommendations: {
simpleTransfer: estimates[0] ? (estimates[0] * gasPrice * 110n / 100n) : null,
tokenTransfer: estimates[1] ? (estimates[1] * gasPrice * 115n / 100n) : null,
dexSwap: estimates[2] ? (estimates[2] * gasPrice * 120n / 100n) : null
}
};
}
Gas Limits Guide
Common Operations
Operation | Typical Gas | Recommended Limit |
---|---|---|
ZETA Transfer | 21,000 | 25,000 |
Token Transfer | 50,000-65,000 | 75,000 |
DEX Swap | 150,000-250,000 | 300,000 |
NFT Mint | 100,000-200,000 | 250,000 |
Cross-Chain Call | 200,000-500,000 | 600,000 |
Contract Deploy | 500,000-5,000,000 | +20% buffer |
Best Practices
- Always add a buffer (10-20%) to gas estimates
- Re-estimate if state changes between estimate and execution
- Handle estimation failures gracefully
- Consider network congestion when setting limits
- Cache estimates for similar transactions
Error Handling
Common Errors
async function handleGasEstimationError(error) {
if (error.code === 'UNPREDICTABLE_GAS_LIMIT') {
return 'Transaction will likely fail';
}
if (error.code === -32000) {
return 'Execution reverted';
}
if (error.code === -32602) {
return 'Invalid transaction parameters';
}
return 'Unknown error';
}
Error Codes
Code | Message | Description |
---|---|---|
-32600 | Invalid Request | Invalid JSON |
-32602 | Invalid params | Invalid method parameters |
-32603 | Internal error | Internal JSON-RPC error |
-32000 | Execution reverted | Transaction would revert |
3 | Execution reverted | EVM revert with reason |
Related Methods
- eth_gasPrice - Get current gas price
- eth_sendRawTransaction - Send transaction
- eth_call - Simulate without gas
- eth_getTransactionReceipt - Check actual gas used