MDLR for developers
Integrate MDLR.
An ERC-20 with 6 decimals and EIP-2612 permit, on Midas Chain testnet (chain ID 64327). Every contract is source-verified on the explorer, where its ABI can be read and downloaded.
Chain ID
64327
RPC
https://rpc.testnet.onmidas.xyz
Explorer
https://explorer.testnet.onmidas.xyz
Gas
MIDS
Addresses
| Contract | Address | Notes |
|---|---|---|
| MDLR | 0x2b001a9401aEB7641318d48aEEB5938693Ab4B5f | MDLR token. Immutable, no owner, no admin. |
| USDMDController (proxy) | 0xBB62559701b7FF33C4dF71E5AE58112F184C849f | The only minter. UUPS proxy; upgrades run through the timelock. |
| USDMDController (implementation) | 0xF3892667Cb917816Fccb35650a6d90AF48eBf12c | The implementation deployed on 2026-09-27: version 1, which pays par at any collateral ratio. An upgrade through the timelock replaces it; the proxy's Read as proxy tab on the explorer shows the implementation in use. |
| TimelockController | 0x6D6E9f1D20e2cc0b4C7E1edd46c3aa421fce32EE | 1-hour delay on testnet. Anyone can execute a ready operation. |
| CollateralRegistry | 0xa7B1c6Fc562531b65aa2C08A570D3bBDd59fe13a | Accepted reserve assets and their haircuts and caps. |
| OracleAdapter | 0x89Ea8c262a5612Cd5c44A37613D2553b4BfE4FF2 | XAU/USD: median of fresh sources, at least 2, spread under 1.5%, 120 s freshness. |
| ReserveManager | 0xC6010490A292Dcb7Fa7C9c47D73d983Be3646a41 | Holds the reserve's on-chain gold. Only the controller can pay out. |
| ProofOfReserves | 0x4436f86f32aFa40d2260D0c1BBBa6fA228C67fFF | Hourly epochs. epochCount(), epoch(n), latestOffchain(). |
| USDMDDispenser | 0xA3047Abd4149039b80a8284397D3B7E9fFCF3809 | claim(): 1,000 MDLR per address per 24 hours. |
| Treasury | 0x8e97178fc4d5b180e69AD36C72eaC27582cE6656 | Receives mint and redeem fees. An account, not a contract. |
| MockXAU (XAU-MOCK) | 0xd47F0EcD6f53bA48524c6C2E454aE716bC6174D5 | Testnet only, not gold. 18 decimals, 1 token = 1 troy ounce by convention. drip() gives 0.05 a day. |
| Bridged PAXG | 0x0Da5029c9567dAa3926d5754146F59606007026a | Listed, empty. For Sepolia PAXG over the canonical bridge. |
ABIs: open any contract on the explorer, where its verified source and ABI are published. The contracts' source is in the chain/src/usdmd directory of the Midas Chain repository.
The token
- Name Midas Dollar, symbol MDLR, 6 decimals. Amounts are integers in millionths: 1 MDLR is 1000000.
- EIP-2612 permit. EIP-712 domain: name "Midas Dollar", version "1", chain ID 64327, verifying contract the token address.
- Transfers are unrestricted. There is no fee on transfer, no rebase, no pause and no blacklist, and none can be added: the contract has no upgrade path.
- mint and burn can be called only by the controller. burn burns only the controller's own balance.
Minting and redeeming
- mint(asset, amountIn, minOut, to): pulls amountIn of a registry asset into the reserve, and mints its value at the oracle price, less haircut and mint fee, to to. Approve the controller for the asset first.
- redeem(amount, asset, minOut, to): takes amount MDLR, burns it less the redeem fee, and pays the asset at the oracle price. While the collateral ratio is at least 1.00 the net amount is paid at par. Below 1.00 the controller version decides. Version 1, deployed on 2026-09-27, pays par at any ratio. Version 2 pays the net amount times the ratio, computed from live prices or, when another held asset cannot be priced, from the latest proof-of-reserves epoch; it adds redemptionRatio() and previewRedeem(amount, asset), and applies once its upgrade has run through the timelock. To tell them apart, call redemptionRatio(): version 1 reverts with no data. Approve the controller for MDLR first, or call redeemWithPermit with a signed permit.
- minOut protects against the price moving between your quote and the block. Quote with OracleAdapter.read(keccak256("XAU/USD")) and valueOf(asset, amount, price) on the controller, or, from version 2, with previewRedeem(amount, asset), which applies the ratio too.
- Reverts carry custom errors: MintIsPaused, MintCapExceeded(requested, remaining), RedeemCapExceeded(requested, remaining), CollateralRatioTooLow(crBps, floorBps), ProofStale(age, maxAge), Slippage(out, minOut), RatioUnavailable() from version 2 and, from the oracle, PriceUnavailable(id, fresh, spreadTooWide).
Events
- Token: Transfer and Approval (ERC-20).
- Controller: Minted(caller, to, asset, amountIn, price, minted, fee) and Redeemed(caller, to, asset, amount, price, paid, fee). From version 2, every Redeemed is preceded by RedeemedAtRatio(caller, net, value, crBps, reserveValue, supply, source, porEpoch). MintPausedSet(paused, by) and ParamsSet(params) for state changes.
- ProofOfReserves: EpochPublished(epoch, supersedes, supply, onchainValue, offchainValue, crBps, docsRoot, docsCid).
- Dispenser: Claimed(to, amount).
Public API
Read-only, no key, CORS open, cached for 10 seconds. Base URL https://api.krysos.xyz. Amounts are decimal strings, already scaled.
| Route | Returns |
|---|---|
GET /v1/usdmd/supply/total | Total supply as a plain number. |
GET /v1/usdmd/supply/circulating | Supply less the issuer's own holdings, as a plain number. |
GET /v1/usdmd/reserves | The reserve now: per-asset holdings and values, price, ratio, buffer, mint capacity, latest epoch. |
GET /v1/usdmd/reserves/history | Every proof-of-reserves epoch. |
GET /v1/usdmd/docs | Every epoch statement with its hash and location. |
GET /v1/usdmd/flows | Mints and redemptions by day, and the latest 50. |
GET /v1/usdmd/status | Oracle sources and their age, mint paused, parameters, caps used. |
GET /v1/usdmd/contracts | Addresses, chain ID, decimals. |
GET /v1/usdmd/governance | Timelock operations: queued, ready, executed, cancelled. |
Examples
curl -s https://api.krysos.xyz/v1/usdmd/supply/total
curl -s https://api.krysos.xyz/v1/usdmd/reserves | jq '{supply, collateral_ratio_bps, xau_usd}'import { createPublicClient, http, parseAbi, formatUnits } from "viem";
const client = createPublicClient({ transport: http("https://rpc.testnet.onmidas.xyz") });
const erc20 = parseAbi(["function balanceOf(address) view returns (uint256)"]);
const raw = await client.readContract({
address: "0x2b001a9401aEB7641318d48aEEB5938693Ab4B5f", abi: erc20,
functionName: "balanceOf", args: ["0xYourAddress"],
});
console.log(formatUnits(raw, 6)); // MDLR has 6 decimals// approve, then mint with MockXAU (18 decimals) at a quoted minimum out
const ctl = parseAbi([
"function mint(address asset, uint256 amountIn, uint256 minOut, address to) returns (uint256)",
"function redeem(uint256 amount, address asset, uint256 minOut, address to) returns (uint256)",
]);
await wallet.writeContract({ address: "0xBB62559701b7FF33C4dF71E5AE58112F184C849f", abi: ctl,
functionName: "mint", args: ["0xd47F0EcD6f53bA48524c6C2E454aE716bC6174D5", amountIn, minOut, account] });Nothing on these pages is an offer, a solicitation or a recommendation to buy, sell or hold any asset, in any jurisdiction. Test MDLR is not sold and has no value.