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.