The Market and token functions you call to quote, buy, sell, and claim payouts on Base.
Everything you need to trade lives on two contracts: Market (quotes + buy/sell)
and the RWA token itself (ERC-20 balance/approve + payouts). The functions below are
the trader-facing subset — admin/governance functions are intentionally omitted.
The token is a standard ERC-20 (18 decimals) plus a few reads for the asset terms.
There are no coupon payments. Yield accrues into the Market price instead — see
How yield accrues. hasPeriodicPayouts() still exists on the
contract and returns payoutFrequency != NONE, but no payment happens on any
schedule; treat it as a descriptive label, not as behaviour. The former
calculatePayout() and claimPayout() functions have been removed.
interface IRWAToken { // ---- ERC-20 ---- function decimals() external view returns (uint8); // 18 function balanceOf(address account) external view returns (uint256); function allowance(address owner, address spender) external view returns (uint256); function approve(address spender, uint256 amount) external returns (bool); function transfer(address to, uint256 amount) external returns (bool); // ---- Asset info ---- function payoutToken() external view returns (address); // settlement currency function hasMaturity() external view returns (bool); function maturityDate() external view returns (uint256); // 0 if none function paused() external view returns (bool); // trading/transfers paused? // ---- Yield ---- // Yield is carried by the Market price, not by this token. There is nothing to claim. function interestRateBps() external view returns (uint256); // declared rate; restated on a reset // (the Market's rate is what accrues) function redeemPrincipal() external returns (uint256); // after maturity, self-service}
payoutToken() also tells you which ERC-20 you’ll spend when buying and receive when
selling — it’s the asset’s settlement currency.
Your balance never changes, and nothing is ever pushed to you. Interest is carried by
the asset’s price on the Market, which rises every second at the contractual rate:
price(t) = checkpointPrice x (1 + rateBps / 10000 x elapsed / 365 days)
So a holding is worth balance x price, and that figure grows continuously without any
transaction. Accrual stops at maturity — a matured note does not keep earning.Read the value with the Market, not the token:
// What the asset is worth per whole token, in hundredths of its payoutToken.const price = await market.currentPrice(token);// What you would ACTUALLY receive for `amount`, net of fees. Prefer this for display:// it is exact, whereas currentPrice() is rounded to whole hundredths.const [gross, fee, net] = await market.calculateSellPayout(token, amount);
currentPrice() is rounded down to whole hundredths of the payout token. On a
low-priced asset that figure can sit unchanged for weeks while the value genuinely
accrues — a 1.00 note at 16.5% takes about 22 days to move by one hundredth. The
underlying accrual is carried at far finer precision and is paid in full; only this
display value is rounded. Use calculateSellPayout when the number matters.
There are two ways to realise the accrued value:
Sell on the Market at any time, at the accreted price less the asset’s fee.
Redemption is self-service — you must call it yourself. Nothing is pushed to you
automatically. It pays principal plus all accrued interest in one transfer, gross, with no
fee charged at maturity:
if (await rwaToken.hasMaturity()) { const maturity = await rwaToken.maturityDate(); // unix seconds if (BigInt(Math.floor(Date.now() / 1000)) > maturity) { await (await rwaToken.redeemPrincipal()).wait(); // burns your balance, pays out }}
redeemPrincipal() returns 0 and does nothing if the asset has no maturity — funds and
equity are perpetual, so for those, selling on the Market is the only exit.Separately, the issuer may wind an asset down before maturity. That path burns every
holder and pays out at a single snapshot price; you do not need to call anything for it,
and trading is halted when it begins.