Gas Network V1 Oracle
Fetch Gasnet Estimation Data
Gasnet currently stores estimates in the form of quantiles representing likelihood of estimate being sufficient to be included soon in a block. The full estimation for a specific chain and timestamp has the following structure:
struct Estimation {
EstimationValues Q70;
EstimationValues Q80;
EstimationValues Q90;
EstimationValues Q95;
EstimationValues Q99;
uint8 precision;
uint128 height;
uint256 timestamp;
uint256 chainid;
}
Each EstimationValues
quantile contains the following estimate details:
struct EstimationValues {
uint256 gasPrice;
uint256 maxPriorityFeePerGas;
uint256 maxFeePerGas;
}
Additional estimate values will be added to accommodate chain specific mechanics, such as blob pricing. Gas estimates are available for all the chains currently support by the Blocknative Gas API. The complete list of available chains is listed in the API docs available here: https://docs.blocknative.com/gas-prediction/gas-platform
The following code will fetch a gas estimate from Gasnet using Ethers in Typescript:
const GASNET_URL=https://http-rpc.devnet.gas.network
const GASNET_CONTRACT_ADDRESS = '0xC2F61FAfA65D874725e485f4B52B9B495559F381'
const gasnetProvider = new ethers.JsonRpcProvider(GASNET_URL);
const gasnetContract = new ethers.Contract(
GASNET_CONTRACT_ADDRESS,
abi,
gasnetProvider
);
let est: Estimation; // the estimation data read from Gasnet
let sig: Bytes;
try {
[est, sig] = await gasnetContract.getEstimation('1'); // estimates for ethereum mainnet
} catch (error) {
console.error(error);
return;
}
This estimate containing the supported quantiles for the specified chain includes a signature that the Gasnet Pull Oracle on the Consumer Chain uses to verify the integrity of the estimate.
Update Consumer Chain Oracle
Once a gas estimation is retrieved from Gasnet above, the following sample code puts the data on the Consumer Chain with the Pull Oracle using Ethers in Typescript:
// Ethereum Sepolia Testnet
export const CONSUMER_CHAIN_URL=https://endpoints.omniatech.io/v1/eth/sepolia/public
export const CONSUMER_CHAIN_CONTRACT_ADDRESS = '0xE4859432d9Af6D40C2D923e3F13D66057F4AEcA0'
// Optimism Sepolia Testnet
export const CONSUMER_CHAIN_URL=https://sepolia.optimism.io
export const CONSUMER_CHAIN_CONTRACT_ADDRESS = '0x1a3d7A0bD9585B730e615aE0fD9a2294C33Df1E1'
// Base Sepolia Testnet
export const CONSUMER_CHAIN_URL=https://sepolia.base.org
export const CONSUMER_CHAIN_CONTRACT_ADDRESS = '0x1a3d7A0bD9585B730e615aE0fD9a2294C33Df1E1'
const consumerChainProvider = new ethers.JsonRpcProvider(CONSUMER_CHAIN_URL);
const wallet = new ethers.Wallet(
consumerWalletPrivateKey,
consumerChainProvider
);
const oracle = new ethers.Contract(
CONSUMER_CHAIN_CONTRACT_ADDRESS,
abi,
wallet
);
try {
const transaction = await oracle.setEstimation(est, sig);
const result = await transaction.wait();
return result;
} catch (error) {
console.error(error);
}
At this point the estimates are available on the Consumer Chain for use by other contracts on that chain. You can find example code to update the estimate on the Consumer Chain using an injected provider (i.e. wallet) in the demo dapp .
Read Consumer Chain Oracle
Sample code calling the Pull Oracle to read a gas estimate using ethers in Typescript:
// Ethereum mainnet chain id, 60 second delay, Q99 quantile
const result = await oracle.getGasEstimationQuantile(BigInt('1'), 60, 99);
Sample code calling the Pull Oracle to read a gas estimate using Solidity:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import {Test, console} from "forge-std/Test.sol";
import {Oracle} from "../src/Oracle.sol";
// parameters needed for eip712 verification
contract OracleTest is Test {
Oracle public oracle;
function setUp() public {
oracle = new Oracle(
"GasOracle",
address(0xb690C4CbDE4747FD614477Ab24c7630C5aAa6Ec5),
uint256(6177644545)
);
oracle.setVerifier(address(0x26222b1a8C061f7Ebda1f4a4d15A66683260dBE5));
}
oracle.getGasEstimationQuantile(0xa, 10000000000000, Oracle.Quantile.Q99);
}
You can find example code to read the estimate on the Consumer Chain using an injected provider (i.e. wallet) in the demo dapp .
Oracle Revert Reasons
Updating the Oracle
If the oracle is updated with an Estimation
and a newer Estimation
already exists, the contract will revert.
The revert message newer block estimation already exists
means that an Estimation
already exists with a higher block number. This is the block number of the chainId
of the Estimation
.
The revert message newer timestamp estimation already exists
means that a more recent Estimation
already exists. The timestamp allows for Estimation
updates within the same block, which is particularly important for estimates from slower chains.
These reverts ensure that only more recent (timestamp and/or block height) estimates can update the oracle on the Customer Chain.
Reading the Oracle
If there are no estimates available for the specified chainId
, the contract will revert with message no estimations for network
. To remedy this, call the update function (setEstimation
) of the oracle to place a fresh estimate on the Consumer Chain.
If there are no estimates available within the specified delay
period, the contract will revert with message timeout
. To remedy this, call the update function (setEstimation
) of the oracle to place a fresher estimate on the Consumer Chain, or change the delay
to a longer period of time. The delay
value is indicated in seconds since the block timestamp of the last estimate update for the specified chain.
If there is no estimate for the specified quantile
, the contract will revert with message quantile not supported
. Currently the quantiles 99, 95, 90, 80, and 70 are supported, but this may change in the future.