Skip to main content

Overview

Liquid Treasury enables institutions to earn competitive yields on stablecoin holdings through blue-chip Tokenized Money Market Funds (TMMFs) — with instant redemptions available 24/7, subject to availability. Built on the Multiliquid Protocol, Liquid Treasury delivers institutional-grade access to Treasury yields with full compliance, on-chain transparency, and seamless integration. Available to U.S. and non-U.S. Accredited Investors. KYC/KYB required for all depositors.

T-Bill Yield

Returns tied to short-term U.S. Treasury Bill rates. Real-world asset backing, not synthetic or DeFi-native.

Instant Liquidity

Redeem to stablecoins or blue-chip TMMFs instantly, 24/7/365, subject to availability.

Issuer Diversification

Multi-issuer TMMF reserve structure reduces counterparty risk. No single point of failure.

The Problem

Institutions must choose between earning yield or having liquidity. Traditional money market products force this tradeoff with settlement delays and redemption caps. No existing product offers all three: true instant liquidity, T-Bill yield, and issuer diversification.

Why Liquid Treasury

FeatureLiquid TreasuryTraditional TMMFs
Liquidity24/7 instant, atomic, subject to availabilityT+1 or daily windows
AccessProgrammatic and automatedLargely manual
InfrastructureOn-chain nativeFiat + On-chain
EligibilityU.S. and non-U.S. Accredited InvestorsVaries

The $TSY Token

PropertyValue
Symbol$TSY
TypeERC-20 (and equivalent)
Decimals18
NetworksEthereum, Solana (coming soon)
BridgeLayerZero OFT
TransfersPermissionless
Deposit stablecoins to mint $TSY tokens 1:1. Your token balance remains constant while interest accrues. Upon redemption, burn $TSY to receive principal plus accrued interest atomically. $TSY is freely-transferrable on secondary. As DeFi integrations expand, holders can use $TSY as collateral in lending protocols, provide liquidity on DEXs, and integrate into yield strategies.

How It Works

1

Deposit

Send USDC to Liquid Treasury and receive $TSY tokens. Primary minters complete KYC/KYB onboarding. Deposits flow into the multi-issuer TMMF reserve, with a dedicated stablecoin buffer for instant redemptions.
2

Earn

Start accruing yield immediately. Returns are contractually tied to prevailing U.S. Treasury Bill yields, providing transparent, market-linked returns. Interest is calculated daily based on the 3-Month U.S. T-Bill Oracle rate.
3

Redeem

Withdraw to stablecoins, subject to availability, or TMMFs instantly, 24/7. The dedicated liquidity buffer enables stablecoin redemptions without waiting for underlying TMMF redemptions.

Reserve Architecture

Liquid Treasury’s reserve is split between yield-generating TMMF holdings and a stablecoin buffer that decouples redemption speed from settlement:

TMMF Holdings (~80-95%)

Allocated across leading blue-chip Tokenized Money Market Funds, the yield-generating core of the reserve. Always available for atomic, in-kind redemptions.

Stablecoin Buffer (~5-20%)

Stablecoin reserve enabling instant redemptions without redeeming underlying TMMFs. Buffer replenishes on T+1/T+2 cycles from new deposits and TMMF redemptions. If the stablecoin buffer hits 0%, all transactions will be reverted.
Traditional tokenized Treasuries require liquidation of underlying assets for redemptions, triggering T+1/T+2 delays. Liquid Treasury’s stablecoin buffer decouples redemption speed from settlement. The system monitors utilization and rebalances dynamically to maintain target liquidity levels. Liquid Treasury operates through a bankruptcy-remote Delaware Special Purpose Vehicle (SPV), providing clear legal separation and investor protection.
  • Contractual Interest: Interest is contractually tied to prevailing U.S. Treasury Bill yields, providing transparent, market-linked returns.
  • Bankruptcy Remote: SPV assets are segregated and bankruptcy-remote, providing structural protection.
  • On-Chain Verifiable: Real-time on-chain reserve verification for full transparency.

DeFi Composability

$TSY is designed for seamless integration across DeFi:
  • Permissionless Transfers: Move $TSY freely between wallets and protocols.
  • DeFi-Ready: Use as collateral, liquidity, or in yield strategies.
  • Secondary Market Liquidity: Trade or swap $TSY on secondary markets.

Compliance

KYC/KYB Verification

Required for all primary participants. Whitelist-enforced on-chain minting ensures only verified addresses receive newly issued tokens.

BSA/AML Compliance

Bank Secrecy Act and Anti-Money Laundering compliance. Blacklist enforcement for sanctioned or restricted addresses.

Segregated Reserve Custody

Segregated reserve custody via audited smart contracts using OpenZeppelin standards.

On-Chain Transparency

Real-time on-chain reserve verification. All state changes emit comprehensive events for auditability.

Integration Options

Liquid Treasury is designed for programmatic access — ideal for B2B2C platforms, trading desks, liquid funds, vault curators, exchanges, payment processors, and any business managing treasury operations at scale.
  • Smart Contracts: Direct on-chain interaction via ethers.js or web3.py for DeFi integrations
  • REST API: Full-featured endpoints for deposits, redemptions, balance queries, and transaction history.
  • SDK: TypeScript library for seamless integration into existing stacks
  • CLI Tool: Command-line interface for automated treasury operations and scripting workflows
White-label ready — embed yield functionality into your platform via a simple one-time integration.
For developer integration details, contract ABIs, and technical specifications, see the Integration Guide.

Technical Reference

The sections below provide detailed smart contract documentation for developers integrating directly with Liquid Treasury’s on-chain infrastructure.

Contract Architecture

Treasury Token

contract Treasury is
    Initializable,
    ERC20Upgradeable,
    ERC20BurnableUpgradeable,
    ERC20PermitUpgradeable,
    AccessControlEnumerableUpgradeable,
    PausableUpgradeable,
    ReentrancyGuardUpgradeable,
    UUPSUpgradeable
Base Contracts:
  • ERC20Upgradeable: Standard token functionality
  • ERC20BurnableUpgradeable: Burn capability
  • ERC20PermitUpgradeable: EIP-2612 gasless approvals
  • AccessControlEnumerableUpgradeable: Role-based permissions with enumeration
  • PausableUpgradeable: Emergency pause capability
  • ReentrancyGuardUpgradeable: Reentrancy attack protection
  • UUPSUpgradeable: Secure upgrade mechanism

Deployment Model

The treasury token can be deployed independently on multiple chains, connected via bridge contracts: Each deployment is independent but connected via bridges:
  • Same token name and symbol across chains
  • Separate role administration per chain
  • Bridge contracts handle cross-chain transfers via burn-and-mint

Core Functions

Minting

mint (Primary Issuance) Mint tokens to whitelisted addresses only. Used for initial token issuance to institutional clients after KYC/KYB verification.
function mint(address to, uint256 amount)
    external
    onlyRole(MINTER_ROLE)
    whenNotPaused
    nonReentrant;
Requirements:
  • Caller must have MINTER_ROLE
  • Recipient must be whitelisted (whitelisted[to] == true)
  • Contract must not be paused
  • Amount must be non-zero
Reverts: AccountNotWhitelisted(to) if recipient is not whitelisted, InvalidAmount() if amount is zero
Whitelist enforcement on primary issuance ensures KYC/KYB compliance. Only addresses that have completed the onboarding process can receive newly minted tokens.
bridgeMint (Cross-Chain) Mint tokens for cross-chain bridge operations. No whitelist enforcement, as bridged tokens represent existing supply.
function bridgeMint(address to, uint256 amount)
    external
    onlyRole(BRIDGE_ROLE)
    whenNotPaused
    nonReentrant;
Requirements:
  • Caller must have BRIDGE_ROLE
  • Recipient must not be the zero address
  • Contract must not be paused
  • Amount must be non-zero
Events: Emits BridgeMint(bridge, to, amount) for off-chain monitoring before the standard Transfer event.

Burning

function burn(uint256 amount) public whenNotPaused;
function burnFrom(address from, uint256 amount) public whenNotPaused;
Standard ERC-20 burn functions. burnFrom requires prior approval from the token holder. If the caller has BRIDGE_ROLE, a BridgeBurn event is emitted for off-chain monitoring in addition to the standard Transfer event. Requirements:
  • Amount must be non-zero
  • Contract must not be paused
  • burnFrom requires sufficient allowance

Transfers

Standard ERC-20 transfer and transferFrom functions. Transfers are permissionless with two exceptions:
  • Blacklist enforcement: Both sender and receiver are checked against the blacklist on every transfer (including mints and burns). Blacklisted addresses cannot send or receive tokens.
  • Pause enforcement: All transfers are blocked when the contract is paused.
Whitelist enforcement applies only to mint() (primary issuance). Transfers between addresses are unrestricted beyond blacklist and pause checks. This enables $TSY to trade freely on secondary markets and integrate with DeFi protocols.

EIP-2612 Permit

function permit(
    address owner,
    address spender,
    uint256 value,
    uint256 deadline,
    uint8 v,
    bytes32 r,
    bytes32 s
) external;
Enables gasless approvals:
  1. User signs an approval message off-chain
  2. A relayer submits the permit() transaction (pays gas)
  3. Approval is set without requiring a transaction from the user
  4. Subsequent transferFrom() or burnFrom() can execute immediately

Bridge Integration

Bridge Management

Bridges are managed through role-based access control. The OPERATOR_ROLE can add and remove bridges:
function addBridge(address bridge) external onlyRole(OPERATOR_ROLE);
function removeBridge(address bridge) external onlyRole(OPERATOR_ROLE);
Adding a bridge grants BRIDGE_ROLE; removing a bridge revokes it. Each operation emits BridgeAdded or BridgeRemoved events. Multiple bridges can operate simultaneously, providing redundancy, distributed risk, and competitive routing options.

TreasuryOFTAdapter (LayerZero)

A reference bridge implementation using LayerZero’s OFT (Omnichain Fungible Token) protocol:
  • Source chain: Burns tokens via Treasury.burnFrom() (requires user approval of the adapter)
  • Destination chain: Mints tokens via Treasury.bridgeMint() (requires BRIDGE_ROLE)
  • Routes zero-address recipients to 0xdead to prevent token loss
Setup:
  1. Deploy TreasuryOFTAdapter on each chain
  2. Grant BRIDGE_ROLE to the adapter: treasury.addBridge(adapterAddress)
  3. Configure LayerZero peers: adapter.setPeer(dstEid, peerAddress)

Compliance Controls

Whitelist

Whitelist enforcement applies only to primary issuance minting (mint()). Managed by WHITELISTER_ROLE:
function addToWhitelist(address account) external onlyRole(WHITELISTER_ROLE);
function removeFromWhitelist(address account) external onlyRole(WHITELISTER_ROLE);
Whitelist status is stored in a public mapping: mapping(address => bool) public whitelisted Lifecycle:
  1. Institution completes KYC/KYB onboarding
  2. Compliance team adds the institution’s address to the whitelist
  3. Address can now receive primary issuance mints
  4. If needed, address is removed from the whitelist during offboarding

Blacklist

Blacklisted addresses cannot send or receive tokens in any context (transfers, mints, burns). Managed by BLACKLISTER_ROLE:
function addToBlacklist(address account) external onlyRole(BLACKLISTER_ROLE);
function removeFromBlacklist(address account) external onlyRole(BLACKLISTER_ROLE);
function addToBlacklistBatch(address[] calldata accounts) external onlyRole(BLACKLISTER_ROLE);
function removeFromBlacklistBatch(address[] calldata accounts) external onlyRole(BLACKLISTER_ROLE);
Blacklist status is stored in a public mapping: mapping(address => bool) public blacklisted Batch operations enable efficient compliance actions across multiple addresses in a single transaction.

Administrative Functions

Force Burn

function forceBurn(address from, uint256 amount) external onlyRole(OPERATOR_ROLE);
Burns tokens from any address without requiring approval. Bypasses pause and blacklist checks by calling super._update() directly. Use cases: Regulatory compliance (e.g., court orders), security incident response, recovery from compromised addresses. Events: Emits ForcedBurn(operator, from, amount).

Force Transfer

function forceTransfer(address from, address to, uint256 amount) external onlyRole(OPERATOR_ROLE);
Transfers tokens between any addresses without approval. Bypasses pause and blacklist checks. Use cases: Wallet recovery with verified identity, regulatory compliance, emergency fund movement. Events: Emits ForcedTransfer(operator, from, to, amount).

Pause / Unpause

function pause() external onlyRole(PAUSER_ROLE);
function unpause() external onlyRole(PAUSER_ROLE);
Pausing blocks all standard token operations (mints, burns, transfers). Emergency functions (forceBurn, forceTransfer) remain operational when the contract is paused.

Yield-Bearing Integration (Treasury Delegate)

When integrated with MultiliquidSwap, the Liquid Treasury token becomes a yield-bearing asset through the Treasury Delegate contract. The delegate manages daily interest rate accrual, a credit-based redemption system, and swap operations.

Overview

The Treasury Delegate extends the standard Multiliquid delegate model with yield mechanics:
  1. Users deposit RWAs or stablecoins via MultiliquidSwap and receive $TSY tokens
  2. The delegate tracks credits (deposit entitlements) separately from token balances
  3. An off-chain worker posts daily interest rates sourced from the 3-Month US T-Bill Oracle
  4. Credits accrue yield over time via a compounding multiplier
  5. When users redeem, they receive their principal plus accumulated yield
contract TreasuryDelegate is StablecoinDelegateBase, IYieldBearingDelegate

Token/Credit Separation

$TSY tokens (ERC-20) and credits are independent:
  • Tokens can be freely transferred on the open market
  • Credits track a user’s yield entitlement and are non-transferable
  • Secondary market buyers receive tokens but no credits (no yield benefit until depositing via MultiliquidSwap)
  • Redemption requires sufficient credits to prevent negative backing
ScenarioTokensCreditsCan Redeem?
User deposits via MultiliquidSwapReceives tokensReceives creditsYes
User buys tokens on secondary marketHas tokensNo creditsNo (must deposit first)
User transfers tokens to another walletLoses tokensKeeps creditsYes, with tokens bought back on secondary market

Daily Rate System

Posting Rates An off-chain worker posts daily interest rates sourced from the 3-Month US T-Bill Oracle :
function postDailyRate(uint256 dayNumber, uint256 grossRate)
    external
    onlyRole(RATE_POSTER_ROLE);
  • dayNumber: The day number (block.timestamp / 1 days)
  • grossRate: The APY before management fee (WAD-scaled, e.g., 4.5% = 4.5e16)
  • The management fee is subtracted on-chain; the net APY is stored
  • The net APY is converted to a per-day compounding rate
Rates must be posted sequentially (including weekend backfills) at 0:01 UTC of the following day. Yield does not accrue for days where rates have yet to be posted. Yield is backfilled upon bootup in the event of the offchain worker crashing. Correcting Rates
function correctDailyRate(uint256 dayNumber, uint256 grossRate)
    external
    onlyRole(OPERATOR_ROLE);
Operators can correct or backfill past rates within the existing series (between firstRateDay and lastRatePostingDay). The operator cannot advance the rate posting frontier. Management Fee
function setManagementFee(uint256 fee) external onlyIssuerAdmin;
The management fee is a WAD-scaled APY (e.g., 50 bps = 5e15) subtracted from the gross rate at posting time. Only the issuer admin can update it.

Withheld Credits

New deposits enter a withheld credits queue before becoming full credits. These withheld credits become full credits after 24 hours of yield-generation. Withheld credits are selected first when any withdrawals are being made. If they have not reached the 24 hour maturity period upon withdrawal, the credits have yield generated withheld (if any). This prevents timing exploits of the underlying RWA NAVs. Each withheld credit entry tracks:
struct WithheldCredits {
    address tokenAddress;        // Source token (RWA or stablecoin)
    uint256 credits;             // Amount of credits withheld
    uint256 releaseTimestamp;    // When credits can be released (24hr hold)
    uint256 earningStartTimestamp; // When credits start earning yield
    bool isRWA;                  // Determines yield calculation method
}
Yield earning rules differ by deposit type:
Deposit TypeEarning StartYield MethodRationale
RWA depositImmediateDaily only (no partial days)Already invested in underlying fund
Stablecoin depositT+1 (next day)Continuous (includes partial days)Settlement delay for stablecoin backing
Queue operations:
  • Additions: New deposits are pushed to the back of the deque
  • Reductions (withdrawals): Consumed from the back (LIFO — most recent deposits first, which have accrued the least yield)
  • Merges: Released from the front (FIFO — oldest deposits mature first) when 24-hour hold period expires
When withheld credits merge into main credits, a weighted average yield multiplier is calculated to blend existing and new credits.

Interest Accrual

Interest accrual is permissionless — anyone can trigger it for any user:
function accrueInterest(address user) external nonReentrant whenNotPaused;
function batchAccrueInterest(address[] calldata users) external nonReentrant whenNotPaused;
function accrueInterestPaged(address user, uint256 maxDays)
    external nonReentrant whenNotPaused
    returns (uint256 daysAccrued, bool isComplete);
Interest accrual is called daily after rate posting by an off-chain worker to make sure all accounts are up to date. Yield multiplier: Each user’s effective redeemable value is credits * yieldMultiplier / WAD. The multiplier starts at 1e18 (1.0) and compounds daily.

View Functions

// Returns the yield-scaled value for a given redemption amount
function getYieldAmount(address user, uint256 redeemValue, bool stablecoinWithdrawal)
    external view returns (uint256 yieldScaledAmount);

// Returns $TSY tokens needed to achieve a target dollar value
function getAmountForTargetValue(address user, uint256 targetValue, bool stablecoinWithdrawal)
    external view returns (uint256 treasuryNeeded);

// Returns all withheld credit entries for a user
function getWithheldCredits(address user)
    external view returns (WithheldCredits[] memory);

// Returns the current day number (block.timestamp / 1 days)
function getCurrentDay() external view returns (uint256);

// Returns the net APY and posting status for a specific day
function getDailyRate(uint256 dayNumber)
    external view returns (uint256 rate, bool posted);
Withheld credits are always valued at 1:1 in view functions (no yield applied). Only main credits receive the yield multiplier. For stablecoin withdrawals, a partial-day yield is applied using the last posted rate to account for intra-day accrual.

Access Control

Treasury Token Roles

RolePermissionsTypical Holder
DEFAULT_ADMIN_ROLEUpgrade contract, manage all rolesMulti-sig governance
OPERATOR_ROLEBridge management (add/remove), force burn, force transfer. Role admin for BRIDGE_ROLE and MINTER_ROLE.Operations multi-sig
MINTER_ROLEPrimary issuance minting (whitelist-enforced)Treasury Delegate, authorized issuers
BRIDGE_ROLECross-chain bridge minting (no whitelist)Bridge adapter contracts
PAUSER_ROLEPause and unpause all token operationsSecurity team
WHITELISTER_ROLEAdd/remove addresses from whitelistCompliance team
BLACKLISTER_ROLEAdd/remove addresses from blacklist (including batch)Compliance team

Treasury Delegate Roles

RolePermissionsTypical Holder
DEFAULT_ADMIN_ROLEUpgrade delegate contractMulti-sig governance
MULTILIQUID_SWAP_CONTRACTExecute swap operations (deployStablecoin, receiveStablecoin, etc.)MultiliquidSwap contract
Issuer AdminSet management fee, configure custody addresses, manage RWA/stablecoin whitelists, pause delegateProtocol team
RATE_POSTER_ROLEPost sequential daily interest ratesOff-chain rate worker
OPERATOR_ROLECorrect past daily ratesOperations multi-sig
PAUSE_ROLEEmergency pause of delegate operationsSecurity team

Events

Treasury Token Events

event AddedToWhitelist(address indexed account);
event RemovedFromWhitelist(address indexed account);
event AddedToBlacklist(address indexed account);
event RemovedFromBlacklist(address indexed account);
event BridgeMint(address indexed bridge, address indexed to, uint256 amount);
event BridgeBurn(address indexed bridge, address indexed from, uint256 amount);
event ForcedBurn(address indexed operator, address indexed from, uint256 amount);
event ForcedTransfer(address indexed operator, address indexed from, address indexed to, uint256 amount);
event BridgeAdded(address indexed bridge);
event BridgeRemoved(address indexed bridge);

Treasury Delegate Events

event DailyRatePosted(uint256 indexed dayNumber, uint256 rate, address indexed poster);
event DailyRateCorrected(uint256 indexed dayNumber, uint256 oldRate, uint256 newRate, address indexed corrector);
event InterestAccrued(address indexed user, uint256 fromDay, uint256 toDay, uint256 daysAccrued, uint256 multiplierAfter);
event YieldClaimed(address indexed user, uint256 creditsRedeemed, uint256 yieldAmount, uint256 effectiveValue);
event FirstRatePosted(uint256 dayNumber);
event PendingCreditsMerged(address indexed user, uint256 pendingAmount, uint256 newCredits);
event PendingCreditsAdded(address indexed user, uint256 amount, uint256 depositDay);
event ManagementFeeUpdated(uint256 oldFee, uint256 newFee);
event WithheldCreditsReduced(address indexed user, uint256 amount, uint256 remainingWithheld);
event MainCreditsReduced(address indexed user, uint256 amount, uint256 remainingCredits);

Custom Errors

Treasury Token Errors

error AccountNotWhitelisted(address);
error AccountBlacklisted(address);
error ZeroAddress();
error InvalidAmount();

Treasury Delegate Errors

error RateAlreadyPosted(uint256 dayNumber);
error CannotPostFutureRate(uint256 dayNumber, uint256 currentDay);
error CannotPostRateForUnfinishedDay(uint256 dayNumber, uint256 currentDay);
error CannotCorrectBeforeFirstRate(uint256 dayNumber, uint256 firstRateDay);
error RateTooHigh(uint256 rate, uint256 maxRate);
error ManagementFeeTooHigh(uint256 fee);
error InsufficientCredits(uint256 requested, uint256 available);
error MustPostSequentially(uint256 dayNumber, uint256 expectedDay);
error InvalidTargetValues(uint256 feeTarget, uint256 feePlusRedemptionTarget, uint256 totalTarget);

Technical Specifications

PropertyValue
Token StandardERC-20 (with extensions)
Decimals18
Upgrade PatternUUPS Proxy
Solidity Version0.8.30

Next: Integration Guide

Learn how to integrate with the Multiliquid Protocol