Skip to content

Nibiru Oracle (EVM) - Usage Guide

Nibiru EVM includes a precompile for Nibiru's oracle module, providing access to exchange rate data and ChainLink-like oracle smart contracts. This allows developers to query real-time price information for various markets directly on-chain.

SectionPurpose
ChainLink-like Feeds - Nibiru MainnetGo here to find the deployed ChainLink-like oracle contract addresses.
Using the ChainLink-like Nibiru OraclesStart here to learn how to use ChainLike-like oracles in your Web3 app or smart contracts
Example: TypeScript, Ethers v6, and the Oracle PrecompileTo use the Nibiru EVM Oracle precompile
AppendixRelated Pages, and ChainLink-like Feeds on Nibiru Testnet

Smart Contract Implementation: These feeds are deployments of NibiruOracleChainLinkLike.sol, a contract that sources data from the Nibiru Oracle Mechanism and exposes the data in the ChainLink AggregatorV3Interface format.

AssetDecimals, NameAddress
ETH8, Ethereum0x63b8426F71C3eDbF15A55EeA4915625892Ea9A4c
NIBI8, Nibiru0xb15F7a4b9AD2db05D91f06df9eA7D56EBe8e6B27
stNIBI8, Liquid Staked NIBI0x2889206C6eDAfD5de621B5EA3999B449879edC70
BTC8, Bitcoin0xc8FD30cA96B6D120Fc7646108E11c13E8bb128Eb
USDC8, Circle0xBecDA6de445178B3D45aa710F5fB09F72E3e1340
USDT8, Tether0x86C6814Aa44fA22f7B9e0FCEC6F9de6012F322f8
uBTC8, uBTC from B Squared Network0x1BCA696B83D6d6D67398f20C530aAC8033B53dF2
sUSDa8, Yield-bearing USDa (Avalon Labs)0x4B13Cb07F975aEe89448258babb482378ddA4C32

Reference:

The Oracle precompile integrates with ChainLink's AggregatorV3Interface, allowing access to decentralized price feeds.

solidity
interface ChainLinkAggregatorV3Interface {
    function decimals() external view returns (uint8);
    function description() external view returns (string memory);
    function version() external view returns (uint256);
    function getRoundData(uint80 _roundId) external view returns (
        uint80 roundId,
        int256 answer,
        uint256 startedAt,
        uint256 updatedAt,
        uint80 answeredInRound
    );
    function latestRoundData() external view returns (
        uint80 roundId,
        int256 answer,
        uint256 startedAt,
        uint256 updatedAt,
        uint80 answeredInRound
    );
}

To query these oracles in a Web3 application, you can import the @nibiruchain/evm-core package on npm.

bash
npm i @nibiruchain/evm-core@latest ethers@6

Note that in this example, we use the address for ETH. We include the list of all active ChainLink-like feeds in the "Nibiru Mainnet - ChainLink-like Feeds" section.

js
import { ethers } from "ethers";
import { chainlinkLike } from "@nibiruchain/evm-core/ethers";

const doReadChainlink = async (wallet: ethers.ContractRunner) => {
  const oracleAddr = "0x6187b99Cad5fbF30f98A06850d301cb1b31b27b2";
  const oracleCaller = chainlinkLike(wallet, oracleAddr);
  const description = await oracleCaller.description();
  const decimals = await oracleCaller.decimals();
  const out = await oracleCaller.latestRoundData();
  const [roundId, answer, startedAt, updatedAt, answeredInRound] = out;
  console.debug("DEBUG %o: ", {
    out,
    oracleAddr,
    description,
    decimals,
    outCleaner: { roundId, answer, startedAt, updatedAt, answeredInRound },
  });
};

Example output - Oracle for ETH on mainnet

js
DEBUG {
  out: [ 18859259n, 2705840000n, 1739818322n, 1739818322n, 420n ],
  oracleAddr: "0x6187b99Cad5fbF30f98A06850d301cb1b31b27b2",
  description: "Nibiru Oracle ChainLink-like price feed for ueth:uusd",
  decimals: 6n,
  outCleaner: {
    roundId: 18859259n,
    answer: 2705840000n,
    startedAt: 1739818322n,
    updatedAt: 1739818322n,
    answeredInRound: 420n,
  },
}:
bash
npm i @nibiruchain/solidity

Example: TypeScript, Ethers v6, and the Oracle Precompile

To communicate directly with the Nibiru EVM Oracle precompile, you can use the ethers.js library to interact with the contract. The script you provided already demonstrates how to query the Oracle for exchange rates and Chainlink prices using the correct contract address and ABI.

Here's a breakdown of the necessary steps to ensure a smooth communication with the precompile, along with some refinements:

javascript
const { ethers } = require("hardhat");

async function main() {
  const provider = new ethers.JsonRpcProvider(
    "https://evm-rpc.testnet-2.nibiru.fi/" // Nibiru Testnet RPC URL
  );
  const precompileAddress = "0x0000000000000000000000000000000000000801"; // Oracle Precompile Address

  // Define the IOracle ABI for querying the exchange rate and ChainLink data
  const abi = [
    "function queryExchangeRate(string pair) view returns (uint256 price, uint64 blockTimeMs, uint64 blockHeight)",
    "function chainLinkLatestRoundData(string pair) view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound)",
  ];

  // Connect to the Oracle precompile contract using the ABI and provider
  const oracle = new ethers.Contract(precompileAddress, abi, provider);

  // Define asset pairs to query the exchange rates
  const pairs = [
    "uatom:uusd",
    "ubtc:uusd",
    "ueth:uusd",
    "uusdc:uusd",
    "uusdt:uusd",
  ];

  // Loop through the pairs and query the Oracle for exchange rates and ChainLink prices
  for (const pair of pairs) {
    try {
      // Query the exchange rate for the asset pair
      console.log(`Querying exchange rate for ${pair}...`);
      const [price, blockTimeMs, blockHeight] = await oracle.queryExchangeRate(pair);
      console.log(`Pair: ${pair}`);
      console.log(`Exchange Rate: ${ethers.formatUnits(price, 18)}`); // Format the price to 18 decimals
      console.log(`Block Time (ms): ${blockTimeMs.toString()}`);
      console.log(`Block Height: ${blockHeight.toString()}`);
    } catch (error) {
      console.error(`Error querying exchange rate for ${pair}:`, error);
    }

    try {
      // Query the ChainLink price for the asset pair
      console.log(`Querying ChainLink price for ${pair}...`);
      const [roundId, answer, startedAt, updatedAt, answeredInRound] = await oracle.chainLinkLatestRoundData(pair);

      console.log(`Pair: ${pair}`);
      console.log(`ChainLink Price: ${ethers.formatUnits(answer, 18)}`); // Format the price to 18 decimals
      console.log(`Round ID: ${roundId.toString()}`);
      console.log(`Started At: ${startedAt.toString()}`);
      console.log(`Updated At: ${updatedAt.toString()}`);
      console.log(`Answered In Round: ${answeredInRound.toString()}`);
    } catch (error) {
      console.error(`Error querying ChainLink price for ${pair}:`, error);
    }
  }
}

// Execute the script
main().catch(console.error);

How This Script Works

  1. The script connects to the Nibiru EVM Oracle precompile using the predefined address and ABI.
  2. It queries the queryExchangeRate function to get the price, block time, and block height for each asset pair.
  3. It also queries the chainLinkLatestRoundData function to fetch the latest ChainLink price data.
  4. The results are logged to the console for each pair, with appropriate formatting for clarity.

Explanation of Key Components

  1. Provider Setup: Connects to the Nibiru Testnet via the RPC endpoint (https://evm-rpc.testnet-2.nibiru.fi/) to establish communication with the Ethereum-compatible network.

  2. ABI Definition: Specifies the functions available for interaction with the Oracle smart contracts, allowing querying of prices and exchange rates.

  3. Supported Asset Pairs: Lists the asset pairs (e.g., "ueth:uusd", "unibi:uusd") supported by Nibiru’s Oracle system for querying price data.

  4. Error Handling: Implements robust error management using try-catch statements to handle potential failures gracefully during queries to the Oracle or ChainLink-like feeds.

  5. Formatted Output: Provides clear and precise price data formatted to 18 decimals, ensuring readability and ease of interpretation.

This approach directly communicates with the Nibiru Oracle precompile, and you can extend this to include other queries or add additional functionality as needed.


Appendix

  1. Understanding the Oracle Precompile
  2. @nibiruchain/evm-core package on npm
  3. @nibiruchain/solidity package on npm

Reference: Nibiru Networks and RPCs

AssetDecimals, NameAddress
BTC:USD8, Bitcoin0x1CA6d404DB645a88aE7af276f3E2CdF64A153107
ETH:USD8, Ethereum0xcAF7BaB290E540f607c977a2e95182514Aeb957f
NIBI:USD8, Nibiru0x2b6C81886001E12341b54b14731358EbAD3a83bd
USDC:USD8, Circle0x9fc81892ea19d6d3Db770A632C8D5Dd1889DE075
USDT:USD8, Tether0xBC3bac25cdf3410D3f2Bd66DC4f156dB49ac92Cb