eth_estimateGas
Estimates the amount of gas required to execute a transaction on Avalanche C-Chain.
When to Use This Method
eth_estimateGas
is essential for:
- Transaction Cost Calculation - Calculate total transaction costs before sending
- Gas Optimization - Optimize gas limits to prevent overpaying
- Smart Contract Testing - Verify contract functions will execute successfully
- User Experience - Show users estimated fees before transaction confirmation
Parameters
Transaction Object with the following fields:
from
- (optional) Address sending the transactionto
- Address receiving the transactionvalue
- (optional) Value to transfer in weidata
- (optional) Contract method call datagas
- (optional) Gas limit (for estimation boundary)gasPrice
- (optional) Gas price in weimaxFeePerGas
- (optional) Maximum fee per gas (EIP-1559)maxPriorityFeePerGas
- (optional) Maximum priority fee (EIP-1559)
{
"jsonrpc": "2.0",
"method": "eth_estimateGas",
"params": [{
"from": "0xaff3454fce5edbc8cca8697c15331677e6ebcccc",
"to": "0xfff7ac99c8e4feb60c9750054bdc14a3b2f0fb8",
"value": "0xde0b6b3a7640000",
"data": "0xa9059cbb000000000000000000000000fff7ac99c8e4feb60c9750054bdc14a3b2f0fb8000000000000000000000000000000000000000000000000000000000000000a"
}],
"id": 1
}
Returns
QUANTITY
- Estimated gas amount in hex format.
Implementation Examples
- cURL
- JavaScript
- Python
- Go
curl -X POST https://api-avalanche-mainnet-archive.n.dwellir.com/YOUR_API_KEY/ext/bc/C/rpc \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "eth_estimateGas",
"params": [{
"from": "0xaff3454fce5edbc8cca8697c15331677e6ebcccc",
"to": "0xfff7ac99c8e4feb60c9750054bdc14a3b2f0fb8",
"value": "0xde0b6b3a7640000"
}],
"id": 1
}'
import { JsonRpcProvider, Contract, parseEther, formatEther, formatUnits } from 'ethers';
const provider = new JsonRpcProvider('https://api-avalanche-mainnet-archive.n.dwellir.com/YOUR_API_KEY/ext/bc/C/rpc');
// Estimate gas for simple AVAX transfer
async function estimateTransferGas(from, to, value) {
const tx = {
from: from,
to: to,
value: parseEther(value)
};
const gasEstimate = await provider.estimateGas(tx);
const gasPrice = await provider.getGasPrice();
const totalCost = gasEstimate * gasPrice;
return {
gasLimit: gasEstimate.toString(),
gasPrice: formatUnits(gasPrice, 'gwei') + ' gwei',
estimatedCost: formatEther(totalCost) + ' AVAX'
};
}
// Estimate gas for contract interaction
async function estimateContractGas(contractAddress, abi, methodName, params, from) {
const contract = new Contract(contractAddress, abi, provider);
// Get unsigned transaction data
const txData = contract.interface.encodeFunctionData(methodName, params);
const tx = {
from: from,
to: contractAddress,
data: txData
};
try {
const gasEstimate = await provider.estimateGas(tx);
const feeData = await provider.getFeeData();
// Calculate costs with EIP-1559 pricing
const maxFeePerGas = feeData.maxFeePerGas;
const maxCost = gasEstimate * maxFeePerGas;
return {
success: true,
gasLimit: gasEstimate.toString(),
maxFeePerGas: formatUnits(maxFeePerGas, 'gwei') + ' gwei',
maxCost: formatEther(maxCost) + ' AVAX',
method: methodName
};
} catch (error) {
return {
success: false,
error: error.message,
method: methodName
};
}
}
// Advanced gas estimation with optimization
async function optimizedGasEstimation(tx) {
try {
// Get base estimate
const baseEstimate = await provider.estimateGas(tx);
// Add safety margin (10-20% extra)
const safetyMargin = 1.15; // 15% extra
const optimizedGasLimit = Math.ceil(Number(baseEstimate) * safetyMargin);
// Get current network conditions
const feeData = await provider.getFeeData();
const latestBlock = await provider.getBlock('latest');
// Calculate network utilization
const utilization = Number(latestBlock.gasUsed) / Number(latestBlock.gasLimit);
// Adjust fees based on network congestion
let adjustedMaxFee = feeData.maxFeePerGas;
let adjustedPriorityFee = feeData.maxPriorityFeePerGas;
if (utilization > 0.8) {
// High congestion - increase fees
adjustedMaxFee = (adjustedMaxFee * 120n) / 100n;
adjustedPriorityFee = (adjustedPriorityFee * 130n) / 100n;
} else if (utilization < 0.3) {
// Low congestion - reduce fees
adjustedMaxFee = (adjustedMaxFee * 90n) / 100n;
adjustedPriorityFee = (adjustedPriorityFee * 85n) / 100n;
}
const estimatedCost = BigInt(optimizedGasLimit) * adjustedMaxFee;
return {
baseGasEstimate: baseEstimate.toString(),
optimizedGasLimit: optimizedGasLimit.toString(),
maxFeePerGas: formatUnits(adjustedMaxFee, 'gwei') + ' gwei',
maxPriorityFeePerGas: formatUnits(adjustedPriorityFee, 'gwei') + ' gwei',
estimatedCost: formatEther(estimatedCost) + ' AVAX',
networkUtilization: (utilization * 100).toFixed(1) + '%'
};
} catch (error) {
throw new Error(`Gas estimation failed: ${error.message}`);
}
}
// Batch gas estimations for multiple transactions
async function batchGasEstimation(transactions) {
const estimates = await Promise.allSettled(
transactions.map(async (tx, index) => {
try {
const gasEstimate = await provider.estimateGas(tx);
return {
index,
success: true,
gasLimit: gasEstimate.toString(),
transaction: tx
};
} catch (error) {
return {
index,
success: false,
error: error.message,
transaction: tx
};
}
})
);
return estimates.map(result => result.value);
}
from web3 import Web3
from web3.exceptions import Web3Exception
w3 = Web3(Web3.HTTPProvider('https://api-avalanche-mainnet-archive.n.dwellir.com/YOUR_API_KEY/ext/bc/C/rpc'))
def estimate_transfer_gas(from_address, to_address, value_avax):
"""Estimate gas for AVAX transfer"""
transaction = {
'from': from_address,
'to': to_address,
'value': w3.to_wei(value_avax, 'ether')
}
try:
gas_estimate = w3.eth.estimate_gas(transaction)
gas_price = w3.eth.gas_price
total_cost = gas_estimate * gas_price
return {
'gas_limit': gas_estimate,
'gas_price_gwei': w3.from_wei(gas_price, 'gwei'),
'estimated_cost_avax': w3.from_wei(total_cost, 'ether'),
'success': True
}
except Web3Exception as e:
return {
'success': False,
'error': str(e)
}
def estimate_contract_gas(contract_address, abi, method_name, params, from_address):
"""Estimate gas for contract method call"""
contract = w3.eth.contract(address=contract_address, abi=abi)
try:
# Build transaction
transaction = contract.functions[method_name](*params).build_transaction({
'from': from_address,
'gasPrice': w3.eth.gas_price
})
# Remove gas from transaction for estimation
transaction.pop('gas', None)
gas_estimate = w3.eth.estimate_gas(transaction)
return {
'success': True,
'gas_limit': gas_estimate,
'method': method_name,
'contract': contract_address
}
except Exception as e:
return {
'success': False,
'error': str(e),
'method': method_name
}
def optimize_gas_estimation(transaction):
"""Optimize gas estimation with safety margins and network conditions"""
try:
# Base gas estimate
base_estimate = w3.eth.estimate_gas(transaction)
# Add safety margin (15%)
safety_margin = 1.15
optimized_gas_limit = int(base_estimate * safety_margin)
# Get network conditions
latest_block = w3.eth.get_block('latest')
utilization = latest_block['gasUsed'] / latest_block['gasLimit']
# Adjust gas price based on utilization
base_gas_price = w3.eth.gas_price
if utilization > 0.8:
# High congestion
adjusted_gas_price = int(base_gas_price * 1.2)
elif utilization < 0.3:
# Low congestion
adjusted_gas_price = int(base_gas_price * 0.9)
else:
adjusted_gas_price = base_gas_price
estimated_cost = optimized_gas_limit * adjusted_gas_price
return {
'base_gas_estimate': base_estimate,
'optimized_gas_limit': optimized_gas_limit,
'adjusted_gas_price_gwei': w3.from_wei(adjusted_gas_price, 'gwei'),
'estimated_cost_avax': w3.from_wei(estimated_cost, 'ether'),
'network_utilization_percent': utilization * 100,
'safety_margin_percent': (safety_margin - 1) * 100
}
except Exception as e:
raise Exception(f"Gas estimation failed: {str(e)}")
def compare_gas_estimates(transactions):
"""Compare gas estimates for multiple transactions"""
estimates = []
total_gas = 0
for i, tx in enumerate(transactions):
try:
gas_estimate = w3.eth.estimate_gas(tx)
gas_price = w3.eth.gas_price
cost = gas_estimate * gas_price
estimates.append({
'transaction_index': i,
'success': True,
'gas_estimate': gas_estimate,
'cost_avax': w3.from_wei(cost, 'ether'),
'transaction': tx
})
total_gas += gas_estimate
except Exception as e:
estimates.append({
'transaction_index': i,
'success': False,
'error': str(e),
'transaction': tx
})
successful_estimates = [est for est in estimates if est['success']]
return {
'individual_estimates': estimates,
'total_gas': total_gas,
'successful_count': len(successful_estimates),
'failed_count': len(estimates) - len(successful_estimates),
'average_gas': total_gas / len(successful_estimates) if successful_estimates else 0
}
package main
import (
"context"
"fmt"
"log"
"math/big"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
)
func main() {
client, err := ethclient.Dial("https://api-avalanche-mainnet-archive.n.dwellir.com/YOUR_API_KEY/ext/bc/C/rpc")
if err != nil {
log.Fatal(err)
}
// Estimate gas for simple transfer
fromAddress := common.HexToAddress("0xaff3454fce5edbc8cca8697c15331677e6ebcccc")
toAddress := common.HexToAddress("0xfff7ac99c8e4feb60c9750054bdc14a3b2f0fb8")
value := big.NewInt(1000000000000000000) // 1 AVAX
msg := ethereum.CallMsg{
From: fromAddress,
To: &toAddress,
Value: value,
}
gasEstimate, err := client.EstimateGas(context.Background(), msg)
if err != nil {
log.Fatal(err)
}
gasPrice, err := client.SuggestGasPrice(context.Background())
if err != nil {
log.Fatal(err)
}
totalCost := new(big.Int).Mul(big.NewInt(int64(gasEstimate)), gasPrice)
fmt.Printf("Gas Estimate: %d\n", gasEstimate)
fmt.Printf("Gas Price: %s wei\n", gasPrice.String())
fmt.Printf("Total Cost: %s wei\n", totalCost.String())
}
func estimateContractGas(client *ethclient.Client, contractAddress common.Address, data []byte, fromAddress common.Address) (uint64, error) {
msg := ethereum.CallMsg{
From: fromAddress,
To: &contractAddress,
Data: data,
}
gasEstimate, err := client.EstimateGas(context.Background(), msg)
if err != nil {
return 0, fmt.Errorf("failed to estimate gas: %v", err)
}
// Add safety margin (15%)
safeGasLimit := gasEstimate * 115 / 100
return safeGasLimit, nil
}
func optimizedGasEstimation(client *ethclient.Client, msg ethereum.CallMsg) (*GasEstimate, error) {
// Base estimation
baseEstimate, err := client.EstimateGas(context.Background(), msg)
if err != nil {
return nil, err
}
// Get current gas price
gasPrice, err := client.SuggestGasPrice(context.Background())
if err != nil {
return nil, err
}
// Get network conditions
latestBlock, err := client.BlockByNumber(context.Background(), nil)
if err != nil {
return nil, err
}
utilization := float64(latestBlock.GasUsed()) / float64(latestBlock.GasLimit())
// Adjust gas price based on utilization
adjustedGasPrice := gasPrice
if utilization > 0.8 {
adjustedGasPrice = new(big.Int).Mul(gasPrice, big.NewInt(120))
adjustedGasPrice = new(big.Int).Div(adjustedGasPrice, big.NewInt(100))
} else if utilization < 0.3 {
adjustedGasPrice = new(big.Int).Mul(gasPrice, big.NewInt(90))
adjustedGasPrice = new(big.Int).Div(adjustedGasPrice, big.NewInt(100))
}
// Add safety margin to gas limit
safeGasLimit := baseEstimate * 115 / 100
totalCost := new(big.Int).Mul(big.NewInt(int64(safeGasLimit)), adjustedGasPrice)
return &GasEstimate{
BaseGasEstimate: baseEstimate,
SafeGasLimit: safeGasLimit,
AdjustedGasPrice: adjustedGasPrice,
TotalCost: totalCost,
NetworkUtilization: utilization,
}, nil
}
type GasEstimate struct {
BaseGasEstimate uint64
SafeGasLimit uint64
AdjustedGasPrice *big.Int
TotalCost *big.Int
NetworkUtilization float64
}
Response Example
Successful Response
{
"jsonrpc": "2.0",
"id": 1,
"result": "0x5208"
}
This represents 21,000 gas units in decimal.
Error Response
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32000,
"message": "insufficient funds for gas * price + value"
}
}
Common Use Cases
1. Pre-Transaction Cost Calculator
Calculate total transaction costs before execution:
async function calculateTransactionCost(from, to, value, data = '0x') {
const tx = { from, to, value, data };
try {
const gasEstimate = await provider.estimateGas(tx);
const feeData = await provider.getFeeData();
// Calculate different fee scenarios
const scenarios = {
low: {
gasLimit: gasEstimate,
maxFeePerGas: feeData.gasPrice, // Fallback to legacy
cost: gasEstimate * feeData.gasPrice
},
standard: {
gasLimit: gasEstimate,
maxFeePerGas: feeData.maxFeePerGas,
cost: gasEstimate * feeData.maxFeePerGas
},
fast: {
gasLimit: gasEstimate,
maxFeePerGas: feeData.maxFeePerGas * 150n / 100n, // 50% higher
cost: gasEstimate * (feeData.maxFeePerGas * 150n / 100n)
}
};
return {
success: true,
gasEstimate: gasEstimate.toString(),
scenarios: Object.entries(scenarios).reduce((acc, [key, scenario]) => {
acc[key] = {
gasLimit: scenario.gasLimit.toString(),
maxFeePerGas: formatUnits(scenario.maxFeePerGas, 'gwei') + ' gwei',
cost: formatEther(scenario.cost) + ' AVAX',
costUSD: null // Add USD conversion if needed
};
return acc;
}, {})
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
2. Smart Contract Gas Profiler
Profile gas usage for different contract methods:
async function profileContractMethods(contractAddress, abi, testCases) {
const contract = new Contract(contractAddress, abi, provider);
const results = [];
for (const testCase of testCases) {
const { method, params, from } = testCase;
try {
// Encode function data
const txData = contract.interface.encodeFunctionData(method, params);
const tx = {
from: from,
to: contractAddress,
data: txData
};
const gasEstimate = await provider.estimateGas(tx);
const gasPrice = await provider.getGasPrice();
results.push({
method: method,
params: params,
gasEstimate: gasEstimate.toString(),
estimatedCost: formatEther(gasEstimate * gasPrice) + ' AVAX',
success: true
});
} catch (error) {
results.push({
method: method,
params: params,
error: error.message,
success: false
});
}
}
// Calculate statistics
const successful = results.filter(r => r.success);
const gasEstimates = successful.map(r => Number(r.gasEstimate));
const stats = {
totalMethods: results.length,
successfulMethods: successful.length,
averageGas: gasEstimates.reduce((sum, gas) => sum + gas, 0) / gasEstimates.length,
maxGas: Math.max(...gasEstimates),
minGas: Math.min(...gasEstimates)
};
return { results, stats };
}
3. Gas Optimization Advisor
Provide gas optimization recommendations:
async function gasOptimizationAdvisor(transactions) {
const advice = [];
for (const tx of transactions) {
try {
const baseEstimate = await provider.estimateGas(tx);
// Test different optimization strategies
const optimizations = {};
// 1. Test with explicit gas limit
if (!tx.gas) {
optimizations.explicitGasLimit = {
suggestion: "Add explicit gas limit",
gasLimit: Math.ceil(Number(baseEstimate) * 1.1).toString(),
rationale: "Explicit gas limits prevent estimation failures"
};
}
// 2. Test with reduced value for contract calls
if (tx.data && tx.value && tx.value > 0n) {
try {
const reducedValueTx = { ...tx, value: 0n };
const reducedEstimate = await provider.estimateGas(reducedValueTx);
if (reducedEstimate < baseEstimate) {
optimizations.reduceValue = {
suggestion: "Consider reducing transaction value",
gasReduction: (Number(baseEstimate) - Number(reducedEstimate)).toString(),
rationale: "Lower values may reduce gas consumption"
};
}
} catch (e) {
// Ignore - reduction not possible
}
}
// 3. Check if method is view/pure (should use eth_call instead)
if (tx.data) {
try {
await provider.call(tx);
optimizations.useCall = {
suggestion: "Use eth_call instead of transaction",
gasReduction: baseEstimate.toString(),
rationale: "This appears to be a read-only operation"
};
} catch (e) {
// Not a read-only operation
}
}
advice.push({
transaction: tx,
baseGasEstimate: baseEstimate.toString(),
optimizations: optimizations,
hasOptimizations: Object.keys(optimizations).length > 0
});
} catch (error) {
advice.push({
transaction: tx,
error: error.message,
success: false
});
}
}
return advice;
}
4. Network Congestion Gas Predictor
Predict optimal gas prices based on network conditions:
async function predictOptimalGas(urgency = 'standard') {
const currentBlock = await provider.getBlock('latest');
const feeData = await provider.getFeeData();
// Analyze recent blocks for congestion
const recentBlocks = await Promise.all(
Array.from({ length: 10 }, (_, i) =>
provider.getBlock(currentBlock.number - i)
)
);
const avgUtilization = recentBlocks.reduce(
(sum, block) => sum + (Number(block.gasUsed) / Number(block.gasLimit)), 0
) / recentBlocks.length;
// Base recommendations
const recommendations = {
slow: {
multiplier: 0.9,
description: "Low priority, may take longer",
expectedTime: "30-60 seconds"
},
standard: {
multiplier: 1.0,
description: "Normal priority",
expectedTime: "10-20 seconds"
},
fast: {
multiplier: 1.3,
description: "High priority",
expectedTime: "5-10 seconds"
},
instant: {
multiplier: 1.6,
description: "Highest priority",
expectedTime: "2-5 seconds"
}
};
// Adjust based on network congestion
const congestionMultiplier = avgUtilization > 0.8 ? 1.2 :
avgUtilization < 0.3 ? 0.8 : 1.0;
const selectedRec = recommendations[urgency];
const adjustedMultiplier = selectedRec.multiplier * congestionMultiplier;
const recommendedMaxFee = feeData.maxFeePerGas * BigInt(Math.floor(adjustedMultiplier * 100)) / 100n;
const recommendedPriorityFee = feeData.maxPriorityFeePerGas * BigInt(Math.floor(adjustedMultiplier * 100)) / 100n;
return {
urgency: urgency,
networkUtilization: (avgUtilization * 100).toFixed(1) + '%',
congestionLevel: avgUtilization > 0.8 ? 'High' : avgUtilization < 0.3 ? 'Low' : 'Medium',
recommendations: {
maxFeePerGas: recommendedMaxFee,
maxPriorityFeePerGas: recommendedPriorityFee,
maxFeePerGasGwei: formatUnits(recommendedMaxFee, 'gwei') + ' gwei',
maxPriorityFeePerGasGwei: formatUnits(recommendedPriorityFee, 'gwei') + ' gwei'
},
description: selectedRec.description,
expectedConfirmationTime: selectedRec.expectedTime
};
}
Performance Optimization
Batch Gas Estimations
Estimate gas for multiple transactions efficiently:
async function batchGasEstimations(transactions) {
const batch = transactions.map((tx, i) => ({
jsonrpc: '2.0',
method: 'eth_estimateGas',
params: [tx],
id: i
}));
const response = await fetch('https://api-avalanche-mainnet-archive.n.dwellir.com/YOUR_API_KEY/ext/bc/C/rpc', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(batch)
});
const results = await response.json();
return results.map((result, index) => ({
transactionIndex: index,
success: !result.error,
gasEstimate: result.result ? parseInt(result.result, 16) : null,
error: result.error?.message
}));
}
Error Handling
Common errors and solutions:
Error Code | Description | Solution |
---|---|---|
-32000 | Insufficient funds | Check account balance |
-32000 | Execution reverted | Review contract logic and parameters |
-32602 | Invalid transaction object | Validate transaction fields |
async function safeGasEstimate(tx, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
const gasEstimate = await provider.estimateGas(tx);
return { success: true, gasEstimate };
} catch (error) {
if (error.message.includes('insufficient funds')) {
return {
success: false,
error: 'Insufficient balance for transaction',
suggestion: 'Check account balance and reduce transaction value'
};
}
if (error.message.includes('execution reverted')) {
return {
success: false,
error: 'Transaction would revert',
suggestion: 'Check contract requirements and parameters'
};
}
if (i === maxRetries - 1) {
return { success: false, error: error.message };
}
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
}
Need help? Contact our support team or check the Avalanche documentation.