Gas Management
Overview
Wafra implements a comprehensive gas management system that provides reliable transaction execution, optimizes gas efficiency, and tracks gas usage across all blockchain operations. The system focuses on predictable gas handling and real-time cost monitoring, ensuring transparent and cost-effective transaction execution.
Gas Management Architecture
Simplified Gas Handling
Wafra uses a streamlined approach to gas management that focuses on reliability and cost optimization for the Base L2 network. The system automatically determines appropriate gas parameters without requiring complex estimation algorithms.
Gas Management Sources:
- Base Network Data: Current network conditions and gas prices
- Conservative Limits: Predetermined safe gas limits based on transaction patterns
- Safety Margin: 20% buffer to prevent out-of-gas failures
- Historical Data: Analysis of actual vs predicted gas usage
Gas Management Service
Simplified Gas Handling:
Wafra uses a streamlined approach to gas management that leverages Base L2’s predictable and low gas costs. The system applies conservative gas limits with built-in safety margins rather than complex estimation algorithms.
Transaction Gas Management
Gas Handling Approach:
Wafra applies conservative gas limits for different transaction types based on Base L2 network characteristics. The system uses predetermined gas limits with safety margins rather than dynamic calculation, ensuring reliable transaction execution while maintaining cost efficiency.
Transaction Gas Handling
Client-Side Integration
Simplified Transaction Processing:
The client-side transaction handling focuses on reliable execution rather than complex gas calculation. Transactions use predetermined gas limits based on transaction type, with the server handling all gas-related calculations and optimizations.
User Interface Integration
Gas Cost Communication:
The user interface displays approximate transaction costs based on current Base L2 network conditions. Since gas costs on Base are typically very low (usually under $0.01), the focus is on providing users with confidence in cost predictability rather than precise calculation.
Cost Calculation & Monitoring
ETH Price Service
Real-Time Price Tracking:
export class EthPriceService {
private cache: Map<string, { price: number; timestamp: number }> = new Map();
private readonly CACHE_DURATION = 60000; // 1 minute
async getCurrentEthPrice(): Promise<number> {
const cached = this.cache.get("eth-usd");
if (cached && Date.now() - cached.timestamp < this.CACHE_DURATION) {
return cached.price;
}
try {
// Fetch from multiple sources for reliability
const sources = [
this.fetchFromCoinGecko(),
this.fetchFromCoinbase(),
this.fetchFromBinance(),
];
const prices = await Promise.allSettled(sources);
const validPrices = prices
.filter((result) => result.status === "fulfilled")
.map((result) => result.value);
if (validPrices.length === 0) {
throw new Error("All price sources failed");
}
// Use median price for accuracy
const medianPrice = this.calculateMedian(validPrices);
// Cache the result
this.cache.set("eth-usd", {
price: medianPrice,
timestamp: Date.now(),
});
return medianPrice;
} catch (error) {
logger.error("Failed to fetch ETH price:", error);
// Return last known price or fallback
return cached?.price || 3000; // Conservative fallback
}
}
calculateGasCostUsd(
gasUsed: string,
gasPrice: string,
ethPriceUsd: number
): string {
const gasUsedBigInt = BigInt(gasUsed);
const gasPriceBigInt = BigInt(gasPrice);
// Calculate gas cost in Wei
const gasCostWei = gasUsedBigInt * gasPriceBigInt;
// Convert Wei to ETH
const gasCostEth = Number(gasCostWei) / 1e18;
// Convert ETH to USD
const gasCostUsd = gasCostEth * ethPriceUsd;
return gasCostUsd.toFixed(8);
}
}Transaction Cost Tracking
Gas Usage Analytics:
interface GasCostTracker {
transactionHash: string;
transactionType: string;
gasUsed: bigint;
gasPrice: bigint;
totalCostETH: bigint;
totalCostUSD: number;
ethPriceUSD: number;
estimatedGas: bigint;
actualGas: bigint;
estimationAccuracy: number;
timestamp: Date;
}
export class TransactionTracker {
async trackTransaction(
address: string,
transactionHash: string,
transactionType: string,
memo?: string
): Promise<void> {
try {
// Wait for transaction confirmation
const gasInfo = await this.getTransactionGasInfo(transactionHash);
if (!gasInfo) {
logger.warn(`Could not get gas info for ${transactionHash}`);
return;
}
// Store detailed gas analytics
await this.storeGasAnalytics({
address,
transactionHash,
transactionType,
...gasInfo,
memo,
});
logger.info(`Tracked transaction ${transactionHash}`, {
type: transactionType,
gasUsed: gasInfo.gasUsed,
costUSD: gasInfo.gasCostUsd,
});
} catch (error) {
logger.error(`Failed to track transaction ${transactionHash}:`, error);
}
}
private async getTransactionGasInfo(txHash: string) {
const MAX_RETRIES = 30; // 5 minutes with 10-second intervals
const RETRY_DELAY = 10000;
// Wait for transaction confirmation with retries
for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
try {
const [transaction, receipt] = await Promise.all([
baseClient.getTransaction({ hash: txHash as `0x${string}` }),
baseClient.getTransactionReceipt({ hash: txHash as `0x${string}` }),
]);
if (transaction && receipt) {
return this.calculateGasCosts(transaction, receipt);
}
await new Promise((resolve) => setTimeout(resolve, RETRY_DELAY));
} catch (error) {
if (attempt === MAX_RETRIES) throw error;
await new Promise((resolve) => setTimeout(resolve, RETRY_DELAY));
}
}
return null;
}
}Gas Optimization Strategies
Transaction Batching
Batch Operation Support:
interface BatchTransaction {
transactions: Transaction[];
totalGasEstimate: GasEstimation;
individualGasEstimates: GasEstimation[];
gasSavings: {
individual: bigint;
batched: bigint;
savings: bigint;
savingsPercentage: number;
};
}
export class BatchTransactionService {
async prepareBatchTransaction(
transactions: Transaction[]
): Promise<BatchTransaction> {
// Estimate gas for individual transactions
const individualEstimates = await Promise.all(
transactions.map((tx) => this.estimateIndividualGas(tx))
);
// Estimate gas for batch transaction
const batchEstimate = await this.estimateBatchGas(transactions);
// Calculate savings
const individualTotal = individualEstimates.reduce(
(sum, estimate) => sum + BigInt(estimate.gasLimit),
0n
);
const batchTotal = BigInt(batchEstimate.gasLimit);
const savings = individualTotal - batchTotal;
const savingsPercentage = Number((savings * 100n) / individualTotal);
return {
transactions,
totalGasEstimate: batchEstimate,
individualGasEstimates: individualEstimates,
gasSavings: {
individual: individualTotal,
batched: batchTotal,
savings,
savingsPercentage,
},
};
}
}Gas Price Management
Dynamic Fee Optimization:
Wafra automatically manages gas prices by monitoring current Base network conditions and applying appropriate fee calculations. The system uses real-time data to determine optimal gas prices that balance transaction confirmation speed with cost efficiency.
Fee Calculation Process:
Gas prices are calculated based on current network base fees plus dynamic priority fees. The system applies safety margins to prevent transaction failures while optimizing for the low-cost characteristics of the Base L2 network. Priority fees are adjusted based on network congestion and transaction urgency.
Performance Analytics
Gas Efficiency Metrics
Current Tracking:
interface GasMetrics {
// Accuracy metrics
estimationAccuracy: {
averageAccuracy: number;
underestimationRate: number;
overestimationRate: number;
accuracyTrend: number[];
};
// Cost metrics
costAnalysis: {
averageCostUSD: number;
totalCostUSD: number;
costByTransactionType: Record<string, number>;
costTrend: number[];
};
// Performance metrics
executionPerformance: {
successRate: number;
averageConfirmationTime: number;
failureReasons: Record<string, number>;
};
// Network metrics
networkConditions: {
averageBaseFee: bigint;
networkCongestion: number;
optimalGasPrice: bigint;
};
}Real-Time Monitoring
Gas Monitoring Dashboard:
export class GasMonitoringService {
async getGasDashboard(): Promise<GasDashboard> {
const [recentTransactions, networkStatus, costAnalysis, userMetrics] =
await Promise.all([
this.getRecentTransactions(),
this.getNetworkStatus(),
this.getCostAnalysis(),
this.getUserGasMetrics(),
]);
return {
summary: {
totalTransactions: recentTransactions.length,
averageCost: costAnalysis.averageCostUSD,
successRate: userMetrics.successRate,
estimationAccuracy: userMetrics.estimationAccuracy,
},
networkConditions: networkStatus,
recentActivity: recentTransactions,
optimizationSuggestions: this.getOptimizationSuggestions(userMetrics),
};
}
private getOptimizationSuggestions(metrics: UserGasMetrics): string[] {
const suggestions: string[] = [];
if (metrics.estimationAccuracy < 0.8) {
suggestions.push("Consider using conservative gas estimates");
}
if (metrics.averageCostUSD > 10) {
suggestions.push("Consider batching transactions to reduce costs");
}
if (metrics.failureRate > 0.1) {
suggestions.push("Increase gas limits to prevent failed transactions");
}
return suggestions;
}
}Development & Testing Tools
Gas Estimation Testing
Development Utilities:
export class GasTestingService {
async testGasEstimation(
transactionType: string,
testCases: TestCase[]
): Promise<TestResults> {
const results: TestResult[] = [];
for (const testCase of testCases) {
try {
// Estimate gas
const estimate = await this.estimateGas(
transactionType,
testCase.params
);
// Execute transaction
const execution = await this.executeTestTransaction(
transactionType,
testCase.params,
estimate
);
// Calculate accuracy
const accuracy = this.calculateAccuracy(estimate, execution.actualGas);
results.push({
testCase: testCase.name,
estimated: estimate.gasLimit,
actual: execution.actualGas,
accuracy,
success: execution.success,
cost: execution.costUSD,
});
} catch (error) {
results.push({
testCase: testCase.name,
error: error.message,
success: false,
});
}
}
return this.generateTestReport(results);
}
}Gas Simulation Environment
Controlled Testing:
export class GasSimulator {
async simulateNetworkConditions(
conditions: NetworkConditions
): Promise<SimulationResult> {
// Simulate different network conditions
const baseFeeMocks = this.generateBaseFeeVariations(conditions);
const congestionLevels = this.generateCongestionScenarios(conditions);
const results = [];
for (const baseFee of baseFeeMocks) {
for (const congestion of congestionLevels) {
const scenario = await this.runGasScenario({
baseFee,
congestion,
transactions: conditions.sampleTransactions,
});
results.push(scenario);
}
}
return this.analyzeSimulationResults(results);
}
}Best Practices & Guidelines
Gas Estimation Best Practices
-
Step 1: Get gas estimates before transaction preparation
-
Step 2: Display estimated costs in USD for transparency
-
Step 3: Apply 20% buffer to prevent out-of-gas failures
-
Step 4: Have conservative estimates when API fails
-
Step 5: Track estimation vs actual gas usage
-
Step 6: Group related transactions to save gas
Error Handling
Gas-Related Error Management:
export enum GasErrorType {
ESTIMATION_FAILED = "estimation_failed",
INSUFFICIENT_FUNDS = "insufficient_funds",
GAS_LIMIT_EXCEEDED = "gas_limit_exceeded",
NETWORK_CONGESTION = "network_congestion",
API_UNAVAILABLE = "api_unavailable",
}
export class GasErrorHandler {
handleGasError(
error: GasError,
context: TransactionContext
): GasErrorResponse {
switch (error.type) {
case GasErrorType.ESTIMATION_FAILED:
return {
fallbackGas: this.getConservativeEstimate(context.transactionType),
userMessage: "Using safe gas estimate",
shouldProceed: true,
};
case GasErrorType.INSUFFICIENT_FUNDS:
return {
userMessage: "Insufficient balance for gas fees",
shouldProceed: false,
suggestedAction: "Add more ETH to cover gas costs",
};
case GasErrorType.GAS_LIMIT_EXCEEDED:
return {
fallbackGas: this.getHigherGasLimit(context),
userMessage: "Transaction requires higher gas limit",
shouldProceed: true,
};
default:
return this.getDefaultErrorResponse(error);
}
}
}This comprehensive gas management system ensures cost-effective, reliable, and transparent blockchain transactions while providing users with accurate cost predictions and developers with powerful optimization tools.