Contracts

SEDA Price Feeds

On-chain price feeds for MANTRA Chain via the SEDA FAST relayer (SedaPriceStore)

SedaPriceStore is a UUPS upgradeable contract on MANTRA Chain EVM that stores (price, timestamp, roundId) per feed. A relayer polls SEDA FAST oracle programs and pushes signed price data on-chain. Reads are exposed both as a simple getter and through the standard Chainlink AggregatorV3Interface shape, so existing DeFi integrations work without changes.

All prices are reported with 18 decimals.

Deployment

ContractAddress
SedaPriceStore (UUPS proxy)0xa249A4FfaE48f0f404Ab262eB04b6068F4efECCa
Implementation0xE3674D1C43FE249d468C362f663A01BcC1c3C318

Verified on Blockscout.

Supported Feeds

Each feed is identified by bytes32 feedId = keccak256(abi.encodePacked(symbol)).

SymbolSourcefeedId
HYPE/USDPyth via SEDA0xc5f3d8462b1cf323f17cd65568a8349b94a47e414db695620043be926eb5fbfd
MANTRA/USDBinance, Bybit, Gate.io0xcd0f31baa49ff3fbccfe0ece74135c3a6a9cb32ae57fd36272ad812bb58a0cf3
HYPE/MANTRACEX + Pyth cross-rate0xf07f96b99794a6dc491a1eb3cc06f4effda805e0ee6ec8102205a3f33ab48551
USDC/USDPyth via SEDA0xff064b881a0c0fff844177f881a313ff894bfc6093d33b5514e34d7faa41b7ef
USDT/USDPyth via SEDA0x91879a0c0be4e43cacda1599ac414205651f4a62b614b6be9e5318a182c33eb0
stMANTRA/MANTRAERC-4626 vault ratio0x9383700fa8a8ef44ad75bc49dfafac6b028d32c54c9805ae6db6de00164f344c
wmantraUSD-Yld/USDAccountant rate0xd12021a04f97a016a1894eb4123056141bbabc0ffde255b5c6371cde11a4018e

Seven immutable adapter contracts wrap SedaPriceStore and expose each feed as a standard per-feed Chainlink AggregatorV3Interface — one address per pair, no feedId argument. Use these when integrating with DeFi protocols that expect a dedicated feed address.

SymbolAdapter address
HYPE/USD0xb28cd0fbbb24b5b28f3ed95cf67d2d4394220729
MANTRA/USD0xc69f6f95a2d55329d0de757769d4dd57430ae04a
HYPE/MANTRA0x90192ab09e06218fbc774c37ea3e7b83cdb0a08b
USDC/USD0x6b45a6fc15c37053d2f64b0509e25a60a88eef69
USDT/USD0xa07c33b6bec39291c4bb6a01679a4119d9e4b811
stMANTRA/MANTRA0xb409c180921775aaae15d8a33a9acfca071de8e6
wmantraUSD-Yld/USD0xdd8af298e3b45ba90f6df69a08430641defeccb9

All adapters are source-verified on Blockscout and were deployed 2026-05-08.

Key parameters shared across all adapters:

ParameterValue
Output decimals8
MAX_STALENESS600 seconds
Upstream SedaPriceStore0xa249A4FfaE48f0f404Ab262eB04b6068F4efECCa

Note

Adapters output 8 decimals, not 18. The underlying data comes from SedaPriceStore (18 decimals) and is scaled down. If you read SedaPriceStore directly and switch to an adapter, update your decimal handling.

import { ethers } from "ethers";

const ABI = [
  "function latestRoundData() view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound)",
  "function decimals() view returns (uint8)",
];

// One address per feed — no feedId argument
const adapter = new ethers.Contract(
  "0xc69f6f95a2d55329d0de757769d4dd57430ae04a", // MANTRA/USD
  ABI,
  provider,
);

const [, answer, , updatedAt] = await adapter.latestRoundData();
console.log(ethers.formatUnits(answer, 8), new Date(Number(updatedAt) * 1000));

Reading Prices

There are two read methods on SedaPriceStore — same underlying data, different shape.

getLatestPrice(feedId)

Simple getter, returns three values.

interface ISedaPriceStore {
    function getLatestPrice(bytes32 feedId)
        external
        view
        returns (int256 price, uint256 timestamp, uint80 roundId);
}

ISedaPriceStore priceStore = ISedaPriceStore(0xa249A4FfaE48f0f404Ab262eB04b6068F4efECCa);

bytes32 feedId = keccak256(abi.encodePacked("HYPE/USD"));
(int256 price, uint256 timestamp, uint80 roundId) = priceStore.getLatestPrice(feedId);

latestRoundData(feedId)

Chainlink AggregatorV3Interface-compatible shape. Use this when integrating with DeFi protocols that already speak Chainlink.

interface ISedaPriceStore {
    function latestRoundData(bytes32 feedId)
        external
        view
        returns (
            uint80 roundId,
            int256 answer,
            uint256 startedAt,
            uint256 updatedAt,
            uint80 answeredInRound
        );

    function decimals() external pure returns (uint8); // always 18
}

(uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound)
    = priceStore.latestRoundData(feedId);

Note

startedAt and updatedAt are both set to the source timestamp, and answeredInRound equals roundId. Note that feedId is a per-call argument here — the standard Chainlink interface takes no arguments, so a single SedaPriceStore deployment serves all feeds rather than one address per pair.

Reading via ethers.js

import { ethers } from "ethers";

const priceStore = new ethers.Contract(
  "0xa249A4FfaE48f0f404Ab262eB04b6068F4efECCa",
  [
    "function getLatestPrice(bytes32) view returns (int256, uint256, uint80)",
    "function latestRoundData(bytes32) view returns (uint80, int256, uint256, uint256, uint80)",
    "function decimals() pure returns (uint8)",
  ],
  provider,
);

const feedId = ethers.id("MANTRA/USD"); // keccak256(toUtf8Bytes(...))
const [price, timestamp, roundId] = await priceStore.getLatestPrice(feedId);
console.log(ethers.formatUnits(price, 18), new Date(Number(timestamp) * 1000));

Update Behavior

The relayer polls SEDA FAST on a fixed interval (default ~10s) and batches all updated feeds into a single updatePrices transaction. A feed is skipped if its source timestamp has not advanced since the last on-chain write, so updatedAt is the freshness signal consumers should check.

// onlyRelayer, whenNotPaused
function updatePrices(
    bytes32[] calldata feedIds,
    int256[] calldata prices,
    uint256[] calldata timestamps
) external;

event PriceUpdated(bytes32 indexed feedId, int256 price, uint256 timestamp, uint80 roundId);

Tip

Always validate updatedAt against your protocol's staleness threshold before consuming a price. Reject answers older than your tolerance window rather than assuming the latest stored value is current.

Admin Functions

Owner-controlled. Listed for completeness — integrators do not call these.

function addRelayer(address relayer) external;     // onlyOwner
function removeRelayer(address relayer) external;  // onlyOwner
function pause() external;                         // onlyOwner
function unpause() external;                       // onlyOwner

PriceUpdated, RelayerAdded, and RelayerRemoved events are emitted for off-chain indexing.