Gas Network Tutorial - Getting Started

Blocknative Ethereum Web3

Introduction

Gas prices fluctuate constantly, and onchain contracts often need those prices to make decisions or to expose up‑to‑date information to apps. Gas Network solves this by delivering signed, accurate gas estimates for many chains directly on‑chain via its Oracle.

This tutorial expands on the Oracle docs and explains how to build and integrate the Gas Network Oracle. It is meant to be accessible to everyone, including those who may be newer to solidity.

Roadmap

In this post we will:

  1. Look up the oracle's address for your network.
  2. Declare a Solidity interface so our code can talk to the oracle.
  3. Call the oracle's getInTime function (and explain every parameter).
  4. Use the returned gas price inside contract logic.
  5. Finish with a fully‑annotated example contract you can deploy in Remix.

1. Find the Oracle Address

Each supported EVM chain already has an Oracle deployed. The official docs list them here https://gas.network/docs/oracle#Update-Consumer-Chain-Oracle.

We suggest to start off with the Ethereum Sepolia (testnet)

2. Describe the Oracle with a Solidity Interface

Copy the interface below into a new file named IGasOracleV2.sol or at the top of your contract:

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.17;

/**
 * @title IGasOracleV2
 * @dev Minimal interface for the Gas Network Oracle V2.
 */
interface IGasOracleV2 {
    /**
     * @notice Fetch a gas value.
     * @param systemId Architecture ID -- always 2 for any EVM chain. Gas Network has provisioned systemId 1 for BTC.
     * @param chainId Chain ID to query (use block.chainid for current chain).
     * @param typeId Which metric? 107 = base fee, 322 = p90 priority fee, etc. See docs for more!
     * @param maxAge Freshness in ms. Oracle returns 0 if data is older.
     * @return value The gas metric (wei).
     * @return blockNumber Block number of the estimate.
     * @return timestamp When the estimate was created (ms UTC).
     */
    function getInTime(
        uint8 systemId,
        uint64 chainId,
        uint16 typeId,
        uint64 maxAge
    ) external view returns (
        uint256 value,
        uint64 blockNumber,
        uint64 timestamp
    );
}

Why an interface?

Solidity needs a function's ABI to call it. By giving the compiler this interface, we can treat the on‑chain oracle contract as if it were a local object. No source code from the oracle itself is required.

3. Connect & Read: line‑by‑line explanation

Create a new contract named GasPriceReader.sol. We start by storing the oracle's address and casting it to our interface:

contract GasPriceReader {
    // 1️⃣ Address of the v2 Oracle on Sepolia.
    address constant GAS_ORACLE = 0xCc936bE977BeDb5140C5584d8B6043C9068622A6;
    
    // 2️⃣ Create a typed handle so we can call its functions.
    IGasOracleV2 oracle = IGasOracleV2(GAS_ORACLE);

    /**
     * @notice Get the latest base fee.
     * @dev Returns both raw wei and more human‑friendly gwei.
     */
    function getCurrentBaseFee()
        external
        view
        returns (uint256 baseFeeWei, uint256 baseFeeGwei)
    {
        // 3️⃣ Call the oracle. Parameters:
        // 2 → EVM system
        // block.chainid → current chain
        // 107 → metric ID for base fee
        // 60000 → only accept data younger than 60 s
        (uint256 value,,) = oracle.getInTime(
            2,
            uint64(block.chainid),
            107,
            60_000
        );
        
        // 4️⃣ If oracle has no fresh data it returns all zeros.
        require(value > 0, "No recent gas data");
        
        baseFeeWei = value;
        baseFeeGwei = value / 1e9; // 1 Gwei = 1e9 wei
    }
}

What just happened?

  • We asked for record type 107 (base fee).
  • maxAge = 60,000 ms means "don't accept oracle data older than 60s."
  • value is the base fee in wei; dividing by 1e9 gives Gwei for readability.
  • A zero return means data is stale or not yet published for this chain.

4. Using gas data in conditional logic

Here's a mini‑game/dapp idea: Run a function only when gas is cheap.

/**
 * @notice Only succeeds if base fee ≤ maxBaseFeeGwei.
 */
function doActionIfGasCheap(uint256 maxBaseFeeGwei) external {
    (uint256 baseFeeWei,,) = oracle.getInTime(2, uint64(block.chainid), 107, 60_000);
    require(baseFeeWei > 0, "No recent gas data");
    
    uint256 currentBaseFeeGwei = baseFeeWei / 1e9;
    require(currentBaseFeeGwei <= maxBaseFeeGwei, "Gas too high");
    
    // (Put real logic here)
    emit ActionDone(currentBaseFeeGwei);
}

event ActionDone(uint256 baseFeeAtExecution);

⚠️Gas cost warning: Reading an external contract (oracle.getInTime) inside a state‑changing transaction adds ~2k gas. This is because the EVM needs to execute that external call as part of the state change. So, the "free read" becomes part of a paid "write." Not very much, but account for it if every byte matters.

5. Full annotated example

Below is a self‑contained contract you can paste into Remix > "Solidity" and deploy on Sepolia. Inline comments explain each part thoroughly.

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.17;

interface IGasOracleV2 {
    function getInTime(
        uint8 systemId,
        uint64 chainId,
        uint16 typeId,
        uint64 maxAge
    ) external view returns (uint256, uint64, uint64);
}

contract GasOracleExample {
    /**
     * @notice Using Sepolia testnet below - change as needed
     **/
    address constant ORACLE = 0xCc936bE977BeDb5140C5584d8B6043C9068622A6;
    IGasOracleV2 constant oracle = IGasOracleV2(ORACLE);
    
    /**
     * @notice Read current base fee and P90 priority tip in Gwei.
     */
    function getGasPrices()
        public
        view
        returns (uint256 baseFeeGwei, uint256 priorityFeeGwei)
    {
        (uint256 baseWei,,) = oracle.getInTime(2, uint64(block.chainid), 107, 300_000);
        (uint256 tipWei,,) = oracle.getInTime(2, uint64(block.chainid), 322, 300_000);
        
        require(baseWei > 0 && tipWei > 0, "Oracle missing");
        
        baseFeeGwei = baseWei / 1e9;
        priorityFeeGwei = tipWei / 1e9;
    }
    
    function doActionIfGasCheap(uint256 maxBaseFeeGwei) external {
        (uint256 baseWei,,) = oracle.getInTime(2, uint64(block.chainid), 107, 60_000);
        uint256 baseGwei = baseWei / 1e9;
        
        require(baseGwei <= maxBaseFeeGwei, "Gas too high");
        
        emit ActionExecuted(baseGwei);
    }
    
    event ActionExecuted(uint256 baseGwei);
    
    /**
     * @dev Convenience helper -- returns a ready‑to‑sign maxFeePerGas.
     *
     * What happens under the hood?
     * 1. Fetches baseFeePerGas (type 107) -- the mandatory part every
     *    transaction must pay; this portion is burned.
     * 2. Fetches the oracle's 90‑percentile priority tip (type 322).
     *    That is, a tip big enough to be included ~90% of the time.
     * 3. Adds them together and returns the sum in wei.
     *
     * How do wallets use it?
     * 1. Set `maxFeePerGas = recommendedMaxFeeWei()` -- the value returned
     *    by this helper (already base + tip).
     * 2. Set `maxPriorityFeePerGas = p90 priority tip` (see getGasPrices).
     *
     * Why is this useful for devs?
     * ✔ You don't need to do EIP‑1559 math or handle units manually.
     * ✔ It compresses two oracle calls into one 256‑bit integer.
     * ✔ Front‑ends can `eth_call` this view method for free and drop the
     *   result straight into ethers.js / web3.js transaction objects.
     *
     * @return recommendedWei Total recommended `maxFeePerGas` (wei).
     */
    function recommendedMaxFeeWei() public view returns (uint256 recommendedWei) {
        (uint256 baseWei,,) = oracle.getInTime(2, uint64(block.chainid), 107, 300_000);
        (uint256 tipWei,,) = oracle.getInTime(2, uint64(block.chainid), 322, 300_000);
        
        require(baseWei > 0 && tipWei > 0, "Oracle missing");
        
        return baseWei + tipWei;
    }
}

6. Deploy & Test in Remix

  1. Open https://remix.ethereum.org and create a new file GasOracleExample.sol.
  2. Paste the full contract above.
  3. Compile with Solidity 0.8.x.
  4. In the 'Deploy & Run' sidebar select Sepolia network via MetaMask (Or any other EVM Wallet).
  5. Deploy. After confirmation, expand the contract and click getGasPrices(). You should see two numbers (base fee & p90 priority fee) returned in Gwei.

🚨Troubleshooting:

  • If any value is 0, the oracle might not have published recently. Try a higher maxAge (e.g. 900000ms).
  • Wrong chain? Make sure MetaMask (or any other EVM wallet you use) is on the same network whose oracle address you set in ORACLE.

7. Bonus: How a dApp or wallet could use the recommendedMaxFeeWei() helper

By exposing this helper function the contract becomes a "gas oracle proxy" that any front-end (or even another contract) can consume without needing to worry about type IDs, units, or fee mathematics. Below is a lightweight JS example using the ethers.js library.

import { ethers } from "ethers";

const gasOracle = new ethers.Contract(
    GAS_ORACLE_ADDRESS,
    ["function recommendedMaxFeeWei() view returns(uint256)",
     "function getGasPrices() view returns(uint256,uint256)"],
    provider
);

const maxFee = await gasOracle.recommendedMaxFeeWei(); // wei
const [baseG, prioG] = await gasOracle.getGasPrices(); // gwei

const tx = {
    to: recipient,
    value: ethers.parseEther("0.1"),
    maxFeePerGas: maxFee, // wei (already base+tip)
    maxPriorityFeePerGas: ethers.parseUnits(prioG.toString(), "gwei"),
    gasLimit: 21000 // 21k for transfers
};

const receipt = await signer.sendTransaction(tx);

Conclusion

You now have a complete, well‑commented template for reading Gas Network estimates. Yay!

From here you can customise:

  • Different typeId values (see docs for new metrics).
  • Freshness windows (maxAge) to balance speed vs. certainty.
  • On‑chain automations that react to gas spikes in real time.

Enjoy building gas‑aware apps!

Gas Extension

Blocknative's proven & powerful Gas API is available in a browser extension to help you quickly and accurately price transactions on 20+ chains.

Download the Extension

Want to keep reading?

Good choice! We have more articles.

gas-network-tutorial---getting-started
Featured

Gas Network Tutorial - Getting Started

Introduction Gas prices fluctuate constantly, and onchain contracts often need those prices to make..

tl;dr-on-gas-network-⛽
Gas

TL;DR on Gas Network ⛽

Gas Network is a decentralized oracle network that brings gas prices onchain—securely,..

exploring-the-gas-network-community-dashboard
Gas

Exploring the Gas Network Community Dashboard

The Gas Network Community Dashboard A Cross Chain Fee Analysis Tool The blockchain ecosystem has..

Connect with us. Build with us.

We love to connect with teams who are building with Blocknative. Tell us about your team and what you would like to learn.

"After first building our own infrastructure, we appreciate that mempool management is a difficult, expensive problem to solve at scale. That's why we partner with Blocknative to power the transaction notifications in our next-generation wallet."

Schedule a demo