Live#…
Reading the chain…
Network now · GullyChain Testnet
Block
—
Txs · 30 blocks
—
Gas, gwei
—
Launches
—

Price oracle

On this page

Heads up

Testnet only. The feed verifies RedStone's signed price packages with RedStone's consumer code, which is licensed BUSL-1.1 (non-production use). A production price source will be announced before mainnet. Do not secure real value with this feed.

GullyChain has no push oracle yet. Parent-chain feeds (Chainlink, Pyth, API3 on Arbitrum Sepolia) cannot be read from an L3 contract in the same transaction, so the testnet runs RedStone in pull mode: the transaction that needs a price carries RedStone's signed packages in its calldata, and the contract verifies them on chain.

#Contracts

Contract Address
GullyPriceFeed v1.0.0 (ETH, BTC, USDC) 0x4c64c79ee59a83842a22c14712D66bfef48eb301
ETH / USD adapter (AggregatorV3-style) 0x732b8a31E19827B6c81db7a433fd120e302862c8
BTC / USD adapter 0xE7Df3ec99314C0716510DAcd5B61a089Cf95130c
USDC / USD adapter 0x7cEbF1d241165302b9a0bc2CFD24020ACB7AE44e
  • Prices have 8 decimals. Packages must come from RedStone's primary production data service, signed by at least 3 signers, and be at most 60 seconds old.
  • Feed ids are bytes32("ETH"), bytes32("BTC") and bytes32("USDC").

#Reading a price

Stored price. updatePrices() verifies the packages in its calldata and stores them. Anyone can call it. latestPrice(feedId) returns the last stored (value, timestamp, round), and each adapter exposes it as latestRoundData() for code written against Chainlink's AggregatorV3Interface.

Note

Nobody updates the stored price on a schedule. It moves only when a transaction calls updatePrices(), so always check updatedAt (or use priceIfFresh) before you rely on it.

Fresh price in your transaction. livePrice(feedId) verifies the packages appended to the current call and returns the price without storing it. priceIfFresh(feedId, maxAge) returns the stored price, or reverts StalePrice if it is older than maxAge seconds.

From a browser or script, wrap the contract with RedStone's EVM connector so each call carries the packages:

TypeScript
// @redstone-finance/evm-connector 0.9.0 (1.0.0 does not install from npm)
import { WrapperBuilder } from "@redstone-finance/evm-connector";

const wrapped = WrapperBuilder.wrap(priceFeed).usingDataService({
  dataServiceId: "redstone-primary-prod",
  uniqueSignersCount: 3,
  dataPackagesIds: ["ETH", "BTC", "USDC"],
});
await wrapped.updatePrices();                 // store fresh prices on chain
const [value] = await wrapped.livePrice(ETH); // or read without storing

A contract that calls livePrice must pass the calldata suffix through, so it is simplest to have the user's transaction call updatePrices() first and then read priceIfFresh.

#USD prices for display

Gully web apps show USD values with the same-origin endpoint /price/eth on gullychain.xyz:

Shell
curl -s https://gullychain.xyz/price/eth
# {"symbol":"ETH","usd":2344.08,"source":"coingecko","ts":1793146177}

It is the mainnet ETH price, cached, for display only. Test ETH has no value. See RPC and indexer API.

#Real-world assets

The TEST-TBILL demo asset has its own mock NAV oracle (AggregatorV3-style, 8 decimals) that accrues a fixed 4.5% a year. See Real-world assets.

#Before mainnet

Consumers code against the AggregatorV3 adapters, so the source behind them can change without touching DeepCore or a lending market. The plan for mainnet: a licensed RedStone feed or a push feed from Chainlink or API3, a staleness bound, and a second source to compare against.