Skip to main content

OpenPayPriceFeed

The OpenPayPriceFeed contract aggregates price data from Chainlink decentralized oracles to convert between USD and token amounts. It includes stablecoin shortcuts and staleness protection. Address (BSC Testnet): 0x1f34e070D4BB1eD3AaF37D8E3297b0a9A12a3399 Explorer: View on BscScan

How It Works

Key Design Decisions

Tokens marked as stablecoins (USDT, USDC) skip the oracle call entirely and return a fixed price of $1.00 (represented as 100000000 with 8 decimals). This saves gas and avoids unnecessary oracle dependencies.
The contract rejects price data older than the stalenessThreshold (default: 3600 seconds / 1 hour). If the Chainlink oracle has not updated within this window, all price queries revert with “Stale price”.
BNB (native token, address(0)) uses a dedicated nativeFeed Chainlink oracle rather than the token config mapping. This is set separately via setNativeFeed().

Read Functions

getPrice

Get the current USD price and decimal precision for a token.
function getPrice(address token) external view returns (
    uint256 price,
    uint8 decimals_
)
ParameterTypeDescription
tokenaddressToken address, or address(0) for native BNB
Return ValueTypeDescription
priceuint256USD price (scaled by 10^decimals)
decimals_uint8Price decimal precision (typically 8 for Chainlink)
Behavior:
  • For stablecoins: returns (100000000, 8) — equivalent to $1.00
  • For address(0): queries the nativeFeed Chainlink oracle
  • For other tokens: queries the token-specific Chainlink feed

getAmountInToken

Convert a USD amount to the equivalent token amount at the current price.
function getAmountInToken(address token, uint256 usdAmount) external view returns (uint256)
ParameterTypeDescription
tokenaddressToken address
usdAmountuint256USD amount to convert
Example: “How many BNB tokens do I need to pay $25?“

getAmountInUsd

Convert a token amount to its USD equivalent at the current price.
function getAmountInUsd(address token, uint256 tokenAmount) external view returns (uint256)
ParameterTypeDescription
tokenaddressToken address
tokenAmountuint256Token amount to convert
Example: “How much USD is 0.5 BNB worth?”

Token Configuration

configureToken

Register a token with its Chainlink price feed. Owner only.
function configureToken(address token, address feed, bool isStablecoin) external onlyOwner
ParameterTypeDescription
tokenaddressERC-20 token address
feedaddressChainlink price feed address (can be address(0) for stablecoins)
isStablecoinboolIf true, returns fixed $1.00 price without oracle call
Example configurations:
// USDT - stablecoin, no oracle needed
priceFeed.configureToken(usdtAddress, address(0), true);

// USDC - stablecoin, no oracle needed
priceFeed.configureToken(usdcAddress, address(0), true);

// WBNB - volatile, needs Chainlink feed
priceFeed.configureToken(wbnbAddress, bnbUsdFeed, false);

tokenConfigs

Read the configuration for a registered token.
function tokenConfigs(address token) external view returns (
    address feed,
    bool isStablecoin,
    bool isConfigured
)

Admin Functions (Owner Only)

setNativeFeed

Set the Chainlink price feed for the native token (BNB).
function setNativeFeed(address feed) external onlyOwner

setStalenessThreshold

Set the maximum age (in seconds) for oracle price data. Minimum: 60 seconds.
function setStalenessThreshold(uint256 threshold) external onlyOwner
Setting the threshold too low may cause price queries to fail frequently during periods of low oracle update frequency. The default of 3600 seconds (1 hour) is appropriate for most use cases.

State Variables

VariableTypeDefaultDescription
nativeFeedaddressChainlink BNB/USD feed address
stalenessThresholduint2563600Max oracle data age in seconds

Events

event TokenConfigured(address indexed token, address feed, bool isStablecoin);
event NativeFeedUpdated(address oldFeed, address newFeed);
event StalenessUpdated(uint256 oldThreshold, uint256 newThreshold);

Example: Querying Prices with ethers.js

import { ethers } from "ethers";

const provider = new ethers.JsonRpcProvider("https://data-seed-prebsc-1-s1.bnbchain.org:8545");

const priceFeed = new ethers.Contract(
  "0x1f34e070D4BB1eD3AaF37D8E3297b0a9A12a3399",
  [
    "function getPrice(address) view returns (uint256 price, uint8 decimals_)",
    "function getAmountInToken(address, uint256) view returns (uint256)",
    "function getAmountInUsd(address, uint256) view returns (uint256)",
  ],
  provider
);

// Get BNB/USD price
const [price, decimals] = await priceFeed.getPrice(ethers.ZeroAddress);
console.log(`BNB price: $${ethers.formatUnits(price, decimals)}`);

// How much BNB for $50?
const bnbAmount = await priceFeed.getAmountInToken(
  ethers.ZeroAddress,
  ethers.parseUnits("50", 8) // USD with 8 decimals
);
console.log(`BNB needed for $50: ${ethers.formatEther(bnbAmount)}`);
For mainnet deployment, use the official Chainlink BSC feeds:
PairMainnet FeedTestnet
BNB/USD0x0567F2323251f0Aab15c8dFb1967E4e8A7D42aeEMockPriceFeed
BTC/USD0x264990fbd0A4796A3E3d8E37C4d5F87a3aCa5EbfMockPriceFeed
ETH/USD0x9ef1B8c0E4F7dc8bF5719Ea496883DC6401d5b2eMockPriceFeed
Find all available Chainlink feeds at data.chain.link.