Technical Protocol Overview

Technical documentation of USD.estate's smart contract architecture, onchain/offchain interplay, share pricing and security model.

Architecture

%%{init: {'theme':'base','themeVariables':{'primaryColor':'#eef0ff','primaryBorderColor':'#4d4dff','primaryTextColor':'#1e293b','lineColor':'#94a3b8','secondaryColor':'#e9f5f2','tertiaryColor':'#f8fafc','clusterBkg':'#f6f9fc','clusterBorder':'#dbe3ec','edgeLabelBackground':'#ffffff','actorBkg':'#eef0ff','actorBorder':'#4d4dff','signalColor':'#475569','signalTextColor':'#1e293b','labelBoxBkgColor':'#eef0ff','labelBoxBorderColor':'#4d4dff','noteBkgColor':'#fff7e6','noteBorderColor':'#c2a06a'}}}%%
flowchart LR
    subgraph Reserve
      USDC[(USDC)] --- BASE[BasePositionManager<br/>reserve custodian]
      TB[(T-bill fund token)] --- BASE
    end
    USDest[USDest<br/>token + mint/burn accounting] -->|stake| V[sUSDest vault<br/>ERC-4626 / ERC-7540]
    BASE -. protocolMint / releaseUSDC .- USDest
    V --- BPM[BondPositionManager<br/>ONCHAINID holder]
    V --- BASE
    BPM --- B1[(ERC-3643 bond A)]
    BPM --- B2[(ERC-3643 bond B)]
    G[BondAllowlist &<br/>RiskParameters] -. checks .- BPM
    TL[TimelockController] -. governs .- G

USDest

USDest is a USDC-backed synthetic dollar. It is mainly the entry and exit point for Staked USDest (sUSDest). The reserve behind it — USDC plus approved tokenized T-bill fund tokens — is custodied by the BasePositionManager. The USDest contract itself holds no reserve assets: it is token and mint/burn accounting, and it pulls USDC from the BasePositionManager to settle institutional redemptions.

Minting

KYC'd institutions on the mint/redeem allowlist can mint USDest by depositing USDC. The USDC goes straight into reserve custody at the BasePositionManager.

/**
 * @notice Deposit USDC and mint USDest
 * @param depositAmount USDC amount
 * @param usdestAmountMinimum Minimum USDest to receive (after fees)
 * @return USDest amount minted
 */
function deposit(
    uint256 depositAmount,
    uint256 usdestAmountMinimum
) external returns (uint256);

/**
 * @notice Whether an account is on the institutional mint/redeem allowlist
 * @param account Wallet to check
 */
function isMintAllowlisted(address account) external view returns (bool);

The App and integrators use isMintAllowlisted to check an institution's status. Changes to this allowlist are compliance actions and take effect immediately; the 7-day ALLOWLIST_DELAY applies to the bond allowlist only.

%%{init: {'theme':'base','themeVariables':{'primaryColor':'#eef0ff','primaryBorderColor':'#4d4dff','primaryTextColor':'#1e293b','lineColor':'#94a3b8','secondaryColor':'#e9f5f2','tertiaryColor':'#f8fafc','clusterBkg':'#f6f9fc','clusterBorder':'#dbe3ec','edgeLabelBackground':'#ffffff','actorBkg':'#eef0ff','actorBorder':'#4d4dff','signalColor':'#475569','signalTextColor':'#1e293b','labelBoxBkgColor':'#eef0ff','labelBoxBorderColor':'#4d4dff','noteBkgColor':'#fff7e6','noteBorderColor':'#c2a06a'}}}%%
sequenceDiagram
    actor Institution
    participant USDest
    participant BASE as BasePositionManager
    Institution->>USDest: Deposit USDC
    USDest->>BASE: USDC into reserve custody
    USDest->>Institution: Mint USDest

Burning

KYC'd institutions on the mint/redeem allowlist can burn USDest and withdraw USDC, up to the USDC buffer the BasePositionManager holds (BasePositionManager.availableUsdcBuffer()). USDest holds no USDC itself: it pulls the USDC from the BasePositionManager (releaseUSDC) and pays it to the recipient.

/**
 * @notice Burn USDest and withdraw USDC
 * @param usdestAmount USDest amount to burn
 * @param recipient USDC recipient
 * @return USDC amount withdrawn (after fees)
 */
function withdraw(
    uint256 usdestAmount,
    address recipient
) external returns (uint256);
%%{init: {'theme':'base','themeVariables':{'primaryColor':'#eef0ff','primaryBorderColor':'#4d4dff','primaryTextColor':'#1e293b','lineColor':'#94a3b8','secondaryColor':'#e9f5f2','tertiaryColor':'#f8fafc','clusterBkg':'#f6f9fc','clusterBorder':'#dbe3ec','edgeLabelBackground':'#ffffff','actorBkg':'#eef0ff','actorBorder':'#4d4dff','signalColor':'#475569','signalTextColor':'#1e293b','labelBoxBkgColor':'#eef0ff','labelBoxBorderColor':'#4d4dff','noteBkgColor':'#fff7e6','noteBorderColor':'#c2a06a'}}}%%
sequenceDiagram
    actor Institution
    participant USDest
    participant BASE as BasePositionManager
    Institution->>USDest: Burn USDest
    USDest->>BASE: releaseUSDC()
    BASE->>Institution: USDC

If a redemption exceeds the USDC buffer, it is escrowed and filled once T-bill fund units have been redeemed:

/**
 * @notice Request a USDest redemption larger than the USDC buffer
 * @param usdestAmount USDest amount to escrow
 * @param recipient USDC recipient
 * @return requestId Withdrawal request ID
 */
function requestWithdraw(uint256 usdestAmount, address recipient) external returns (uint256 requestId);

/**
 * @notice Fulfill an escrowed withdrawal once USDC is available (STRATEGY_ADMIN_ROLE)
 * @param requestId Withdrawal request ID
 */
function fulfillWithdraw(uint256 requestId) external;

Staked USDest

Staked USDest (sUSDest) is a yield-bearing ERC-4626 vault token with ERC-7540 asynchronous redemptions. It earns yield from USDest reserve (T-bill) yield and from real-estate bond positions held by the BondPositionManager. USDest can be staked for sUSDest and later redeemed back for USDest. Unlike USDest, sUSDest is not a stablecoin. It floats freely and represents shares in a portfolio of permissioned bond positions plus unallocated USDest.

Staking

Anyone can stake USDest to receive sUSDest at the current deposit share price. Staking is a synchronous ERC-4626 deposit.

function deposit(uint256 assets, address receiver) external returns (uint256 shares);
function mint(uint256 shares, address receiver) external returns (uint256 assets);
%%{init: {'theme':'base','themeVariables':{'primaryColor':'#eef0ff','primaryBorderColor':'#4d4dff','primaryTextColor':'#1e293b','lineColor':'#94a3b8','secondaryColor':'#e9f5f2','tertiaryColor':'#f8fafc','clusterBkg':'#f6f9fc','clusterBorder':'#dbe3ec','edgeLabelBackground':'#ffffff','actorBkg':'#eef0ff','actorBorder':'#4d4dff','signalColor':'#475569','signalTextColor':'#1e293b','labelBoxBkgColor':'#eef0ff','labelBoxBorderColor':'#4d4dff','noteBkgColor':'#fff7e6','noteBorderColor':'#c2a06a'}}}%%
sequenceDiagram
    actor User
    User->>+sUSDest: Stake USDest (deposit()/mint())
    Note right of sUSDest: USDest transferred to sUSDest
    sUSDest->>+User: Mint sUSDest tokens

deposit() and mint() have overloads with slippage protection for EOAs.

Unstaking

Holders unstake sUSDest to receive USDest at the redemption share price in force when their request is serviced. Unstaking is an asynchronous ERC-7540 redeem. Requests are serviced at the close of each epoch (EPOCH_LENGTH). A request must be at least MIN_REDEEM_SHARES (1 sUSDest); a wallet may have any number of requests open, each its own FIFO entry. Once serviced, a request is claimed either per request with claimRequest() (what the App uses) or through the ERC-7540 redeem() / withdraw() path, which claims serviced requests oldest-first.

function requestRedeem(uint256 shares, address controller, address owner) external returns (uint256 requestId);
function claimRequest(uint256 requestId, address receiver) external returns (uint256 assets);
function redeem(uint256 shares, address receiver, address controller) external returns (uint256 assets);
function withdraw(uint256 assets, address receiver, address controller) external returns (uint256 shares);
%%{init: {'theme':'base','themeVariables':{'primaryColor':'#eef0ff','primaryBorderColor':'#4d4dff','primaryTextColor':'#1e293b','lineColor':'#94a3b8','secondaryColor':'#e9f5f2','tertiaryColor':'#f8fafc','clusterBkg':'#f6f9fc','clusterBorder':'#dbe3ec','edgeLabelBackground':'#ffffff','actorBkg':'#eef0ff','actorBorder':'#4d4dff','signalColor':'#475569','signalTextColor':'#1e293b','labelBoxBkgColor':'#eef0ff','labelBoxBorderColor':'#4d4dff','noteBkgColor':'#fff7e6','noteBorderColor':'#c2a06a'}}}%%
sequenceDiagram
    actor User
    User->>+sUSDest: Unstake sUSDest (requestRedeem())
    Note right of sUSDest: Shares escrowed in queue
    sUSDest->>+User: Redemption ID
    Note over sUSDest: Epoch close: serviceRedemptions()
    User->>+sUSDest: claimRequest() / redeem() / withdraw()
    sUSDest->>+User: USDest

Queued shares stay in total supply until they are serviced. They keep sharing in NAV changes, gains and impairments alike, until then.

Position Managers

The sUSDest vault's underlying asset is USDest. The vault earns base yield on it and deploys it into bond positions through position managers.

Interacting with position managers requires STRATEGY_ADMIN_ROLE, held by the strategy multisig. Its allocation decisions are discretionary, but every call is checked against the guardrails in RiskParameters and BondAllowlist.

The BasePositionManager custodies the USDC and T-bill reserve behind USDest and harvests base yield on it. Base yield is the amount by which reserve value exceeds USDest supply. harvestBaseYield() takes BASE_YIELD_ADMIN_FEE_BPS to the treasury and calls USDest.protocolMint(vault, netSurplus, "BASE_YIELD"), which mints the net surplus as USDest into the sUSDest vault, then credits the vault's accounted reserve. protocolMint is callable only by contracts holding RESERVE_MANAGER_ROLE (the position managers).

/**
 * @notice Harvest base yield (reserve value above USDest supply)
 * @return Harvested USDest amount
 * @return Admin fee
 */
function harvestBaseYield() external returns (uint256, uint256);

/**
 * @notice Move reserve USDC into an approved T-bill fund, respecting USDC_BUFFER_BPS
 * @param fund Approved T-bill fund token
 * @param usdcAmount USDC amount
 */
function allocateReserve(address fund, uint256 usdcAmount) external;

/**
 * @notice Redeem T-bill fund units back to USDC
 * @param fund Approved T-bill fund token
 * @param units Fund units to redeem
 */
function deallocateReserve(address fund, uint256 units) external;

On the USDest side, two protocol paths mint or burn without an institutional deposit. Both are gated by RESERVE_MANAGER_ROLE, held only by the position managers:

/**
 * @notice Mint USDest against USDC already held in reserve custody (RESERVE_MANAGER_ROLE)
 *         Reasons: BASE_YIELD, COUPON, PRINCIPAL, RECOVERY
 * @param to Recipient of the minted USDest (the sUSDest vault)
 * @param usdcIn USDC amount already in reserve custody
 * @param reason Mint reason
 * @return minted USDest amount minted
 */
function protocolMint(address to, uint256 usdcIn, bytes32 reason) external returns (uint256 minted);

/**
 * @notice Burn USDest and release the matching USDC from reserve custody (RESERVE_MANAGER_ROLE)
 * @param from Holder whose USDest is burned
 * @param usdestAmount USDest amount to burn
 * @param usdcTo USDC recipient
 * @return usdcOut USDC amount released
 */
function protocolBurn(address from, uint256 usdestAmount, address usdcTo) external returns (uint256 usdcOut);

Settlement of a bond subscription burns the committed USDest via protocolBurn, and the BasePositionManager releases the USDC to the issuer.

%%{init: {'theme':'base','themeVariables':{'primaryColor':'#eef0ff','primaryBorderColor':'#4d4dff','primaryTextColor':'#1e293b','lineColor':'#94a3b8','secondaryColor':'#e9f5f2','tertiaryColor':'#f8fafc','clusterBkg':'#f6f9fc','clusterBorder':'#dbe3ec','edgeLabelBackground':'#ffffff','actorBkg':'#eef0ff','actorBorder':'#4d4dff','signalColor':'#475569','signalTextColor':'#1e293b','labelBoxBkgColor':'#eef0ff','labelBoxBorderColor':'#4d4dff','noteBkgColor':'#fff7e6','noteBorderColor':'#c2a06a'}}}%%
sequenceDiagram
    actor Strategy
    participant BASE as BasePositionManager
    participant USDest
    participant sUSDest
    Strategy->>BASE: harvestBaseYield()
    BASE->>BASE: reserve value − USDest supply
    BASE->>USDest: protocolMint(vault, netSurplus, "BASE_YIELD")
    USDest->>sUSDest: mint USDest (net of admin fee)
    BASE->>sUSDest: creditReserve(netSurplus)

The BondPositionManager deploys USDest into bond subscriptions and deposits coupons, principal and recoveries. Its address is registered as an ONCHAINID identity, with claims issued for the Holding Subsidiary, in the identity registry of each allowlisted ERC-3643 bond.

Subscriptions are funded from the Subscription Timelock. USDest is committed against a hash of the agreed subscription terms and released only at settlement.

/**
 * @notice Commit USDest to a bond subscription
 * @param bondToken Allowlisted ERC-3643 bond token
 * @param subscriptionTermsHash Hash of (bondToken, units, price, issuerPayout, settlementDate)
 * @param usdestAmount USDest amount committed
 * @param expiration Expiration timestamp (≤ MAX_SUBSCRIPTION_EXPIRY)
 */
function depositSubscriptionTimelock(
    address bondToken,
    bytes32 subscriptionTermsHash,
    uint256 usdestAmount,
    uint64 expiration
) external;

The commitment reverts unless:

\text{bondToken} \in \text{Allowlist} \;\wedge\; t \geq t^{allow}_{bond}
\frac{E_{g} + \text{usdestAmount}}{\mathrm{NAV}^{redeem}} \leq \text{ISSUER\_CAP}
\frac{U - \text{usdestAmount} - Q}{\mathrm{NAV}^{redeem}} \geq \text{RESERVE\_FLOOR}

where E_g is current exposure to the bond's issuer group (positions plus pending commitments), U is USDest held by the vault and Q is USDest-equivalent redemptions queued for the current epoch.

%%{init: {'theme':'base','themeVariables':{'primaryColor':'#eef0ff','primaryBorderColor':'#4d4dff','primaryTextColor':'#1e293b','lineColor':'#94a3b8','secondaryColor':'#e9f5f2','tertiaryColor':'#f8fafc','clusterBkg':'#f6f9fc','clusterBorder':'#dbe3ec','edgeLabelBackground':'#ffffff','actorBkg':'#eef0ff','actorBorder':'#4d4dff','signalColor':'#475569','signalTextColor':'#1e293b','labelBoxBkgColor':'#eef0ff','labelBoxBorderColor':'#4d4dff','noteBkgColor':'#fff7e6','noteBorderColor':'#c2a06a'}}}%%
sequenceDiagram
    actor Strategy
    Strategy->>+sUSDest: Deposit Subscription Timelock
    sUSDest->>+Subscription Timelock: USDest tokens

Settlement is delivery-versus-payment. Once the issuer's token agent has delivered the bond tokens to the BondPositionManager, anyone can call settleSubscription() with the agreed terms, at any time up to the commitment's expiry; the contract recomputes the terms hash and requires it to match the commitment. The settlementDate in the terms is informational for offchain DvP coordination, so an issuer that settles a day early does not cause a revert; expiry (MAX_SUBSCRIPTION_EXPIRY) is the only hard bound.

/**
 * @notice Settle a subscription once bond tokens are delivered (DvP)
 * @param terms Agreed subscription terms (bondToken, units, price, issuerPayout, settlementDate);
 *        re-hashed onchain and required to match the commitment
 */
function settleSubscription(SubscriptionTerms calldata terms) external;

If terms change or the commitment expires, the USDest is returned to the vault with cancelSubscriptionTimelock():

/**
 * @notice Cancel subscription timelock
 * @param subscriptionTermsHash Subscription terms hash
 */
function cancelSubscriptionTimelock(bytes32 subscriptionTermsHash) external;
%%{init: {'theme':'base','themeVariables':{'primaryColor':'#eef0ff','primaryBorderColor':'#4d4dff','primaryTextColor':'#1e293b','lineColor':'#94a3b8','secondaryColor':'#e9f5f2','tertiaryColor':'#f8fafc','clusterBkg':'#f6f9fc','clusterBorder':'#dbe3ec','edgeLabelBackground':'#ffffff','actorBkg':'#eef0ff','actorBorder':'#4d4dff','signalColor':'#475569','signalTextColor':'#1e293b','labelBoxBkgColor':'#eef0ff','labelBoxBorderColor':'#4d4dff','noteBkgColor':'#fff7e6','noteBorderColor':'#c2a06a'}}}%%
sequenceDiagram
    participant Agent as Issuer Token Agent
    participant BPM as BondPositionManager
    participant ST as Subscription Timelock
    participant USDest
    participant BASE as BasePositionManager
    participant Issuer
    Agent->>BPM: Deliver ERC-3643 bond tokens
    BPM->>ST: settleSubscription(terms)
    ST->>ST: Verify units delivered, terms hash matches
    BPM->>USDest: protocolBurn(committed USDest)
    USDest->>BASE: release USDC
    BASE->>Issuer: USDC (issuer payout)

Coupons and principal are paid in USDC to the BondPositionManager. Eligibility requires USDC coupons, so a receipt in another currency is exceptional; when one must be swapped, it goes through a timelock-managed allowlisted router with an onchain minOut bounded by MAX_SWAP_SLIPPAGE_BPS. The BondPositionManager then converts the USDC through USDest.protocolMint(vault, amount, "COUPON") (or "PRINCIPAL") and calls sUSDest.creditReserve(amount, reason); the redemption share price steps up on that credit.

/**
 * @notice Deposit a coupon payment
 * @param bondToken Bond token the coupon relates to
 * @param currencyToken Currency received
 * @param depositAmount Amount received
 * @param usdestAmountMinimum Minimum USDest after swap and performance fee
 * @param data Swap data (if currencyToken is not USDC)
 */
function depositCoupon(
    address bondToken,
    address currencyToken,
    uint256 depositAmount,
    uint256 usdestAmountMinimum,
    bytes calldata data
) external;

/**
 * @notice Deposit a principal repayment (maturity, amortisation, issuer redemption)
 * @param bondToken Bond token the principal relates to
 * @param currencyToken Currency received
 * @param depositAmount Amount received
 * @param unitsRetired Bond units redeemed or cancelled
 * @param usdestAmountMinimum Minimum USDest after swap
 * @param data Swap data (if currencyToken is not USDC)
 */
function depositPrincipal(
    address bondToken,
    address currencyToken,
    uint256 depositAmount,
    uint256 unitsRetired,
    uint256 usdestAmountMinimum,
    bytes calldata data
) external;
%%{init: {'theme':'base','themeVariables':{'primaryColor':'#eef0ff','primaryBorderColor':'#4d4dff','primaryTextColor':'#1e293b','lineColor':'#94a3b8','secondaryColor':'#e9f5f2','tertiaryColor':'#f8fafc','clusterBkg':'#f6f9fc','clusterBorder':'#dbe3ec','edgeLabelBackground':'#ffffff','actorBkg':'#eef0ff','actorBorder':'#4d4dff','signalColor':'#475569','signalTextColor':'#1e293b','labelBoxBkgColor':'#eef0ff','labelBoxBorderColor':'#4d4dff','noteBkgColor':'#fff7e6','noteBorderColor':'#c2a06a'}}}%%
sequenceDiagram
    actor Strategy
    participant BPM as BondPositionManager
    participant Router as Allowlisted router
    participant USDest
    participant sUSDest
    Strategy->>BPM: depositCoupon() / depositPrincipal()
    BPM->>Router: Swap to USDC (exceptional, only if not USDC)
    Router->>BPM: USDC
    BPM->>USDest: protocolMint(vault, amount, "COUPON" / "PRINCIPAL")
    USDest->>sUSDest: mint USDest (coupons net of performance fee)
    BPM->>sUSDest: creditReserve(amount, reason)

Credit events are recorded by the Holding Subsidiary under CREDIT_AGENT_ROLE, following the published rule:

/**
 * @notice Record a credit event; stops coupon accrual for the position
 * @param bondToken Bond token
 * @param evidenceHash Hash of the supporting notice or record
 */
function recordCreditEvent(address bondToken, bytes32 evidenceHash) external;

/**
 * @notice Flag a formal insolvency or enforcement notice, opening the early impairment path
 * @param bondToken Bond token
 * @param evidenceHash Hash of the notice
 */
function flagInsolvency(address bondToken, bytes32 evidenceHash) external;

/**
 * @notice Write the position down to its impairment value
 * @param bondToken Bond token
 * @param impairedValue Carrying value after impairment (USDest terms)
 * @param evidenceHash Hash of the impairment computation inputs
 */
function recordImpairment(address bondToken, uint256 impairedValue, bytes32 evidenceHash) external;

/**
 * @notice Deposit recoveries and close the position
 * @param bondToken Bond token
 * @param currencyToken Currency received
 * @param depositAmount Amount recovered
 * @param usdestAmountMinimum Minimum USDest after swap
 * @param data Swap data
 */
function recordRecovery(
    address bondToken,
    address currencyToken,
    uint256 depositAmount,
    uint256 usdestAmountMinimum,
    bytes calldata data
) external;

recordImpairment is only callable once IMPAIRMENT_DELAY has elapsed since the credit event, or once flagInsolvency has been called for that position. The delayed path stays the norm; the early path is explicit and evidenced. Impairment lowers the position's carrying value inside the BondPositionManager; the vault reads that value into both share prices.

Bond Allowlist & Risk Parameters

BondAllowlist stores each eligible bond's token address, ISIN, issuer group, day-count convention, coupon schedule and the timestamp from which it may receive allocation. Additions, removals and parameter changes can be made only by the TimelockController:

/**
 * @notice Add a bond to the allowlist (callable only by TimelockController)
 * @param bondToken ERC-3643 bond token
 * @param params Bond parameters (ISIN, issuer group, coupon rate, frequency, day count, maturity)
 */
function addBond(address bondToken, BondParams calldata params) external;

/**
 * @notice Remove a bond from the allowlist; existing positions are unaffected
 * @param bondToken ERC-3643 bond token
 */
function removeBond(address bondToken) external;

RiskParameters exposes reserveFloorBps(), issuerCapBps(), bondCapBps(), allowlistDelay(), maxSubscriptionExpiry(), epochLength(), epochCutoff(), minRedeemShares(), usdcBufferBps(), maxSwapSlippageBps(), impairmentDelay(), impairmentHaircutBps() and the fee rates. Every setter can be called only by the TimelockController. Setters enforce range bounds (bps ≤ 10 000, and every fee rate capped in code at 3000 bps) but no cross-parameter checks, so an emergency change can never be blocked by an unrelated value.

Share Pricing - Net Asset Value (NAV)

The net asset value of sUSDest is the value of unallocated USDest plus its bond positions. Bond positions are valued conservatively at carrying value, or optimistically at carrying value plus coupon accrued since the last coupon date.

The deposit share price uses the optimistic NAV; the redemption share price uses the conservative NAV. The deposit share price is always greater than or equal to the redemption share price. The two are equal when no performing bond has accrued unpaid coupon and all base yield has been harvested.

The rest of this section describes the optimistic NAV used for deposit pricing.

In general, the optimistic NAV is defined as:

\begin{aligned}
S_t     &: \text{USDest total supply} \\
r_b     &: \text{reserve (T-bill) yield rate, net of admin fee} \\
F_{i,u} &: \text{face value of bond } i \text{ held at time } u \\
c_i     &: \text{coupon rate of bond } i \text{, net of performance fee} \\
n       &: \text{number of bond positions}
\end{aligned}
\mathrm{NAV}_t = \mathrm{NAV}_0 + \underbrace{\int_0^t \sum_{i=1}^{n} c_i F_{i,u} \, du}_{\text{continuous coupon accrual}} + \underbrace{\int_0^t r_b S_u \, du}_{\text{continuous reserve yield}}

In practice, coupon accrual follows each bond's day-count convention and resets at every coupon date, when the accrued amount is replaced by cash received. After a credit event, the position stops accruing. NAV is therefore defined more precisely with a switch:

\mathbf{1}_{i \text{ live at } u} = \begin{cases} 1 & \text{bond } i \text{ performing} \\ 0 & \text{credit event recorded for bond } i \end{cases}
\mathrm{NAV}_t = \mathrm{NAV}_0 + \underbrace{\int_0^t \sum_{i=1}^{n} c_i F_{i,u} \, \mathbf{1}_{i \text{ live at } u} \, du}_{\text{continuous coupon accrual}} + \underbrace{\int_0^t r_b S_u \, du}_{\text{continuous reserve yield}}

To show how impairment and recovery adjust NAV, define:

\begin{aligned}
\tau    &&&: \text{time the credit event is recorded} \\
T_1     &&&: \text{time an impairment is recorded (if any)} \\
T_2     &&&: \text{time recoveries are returned to the protocol} \\
P_j     &&&: \text{carrying value of position } j \text{ before impairment} \\
V_j    &= F_{j} + A_j(\tau) &&: \text{noteholder claim: face value plus accrued unpaid coupon} \\
K_j     &&&: \text{impairment value under the published rule } (K_j \leq P_j) \\
R_j     &&&: \text{net enforcement proceeds attributable to position } j \\
\Pi_j   &&&: \text{proceeds returned to the protocol}
\end{aligned}

The vault is a creditor, not an equity holder. It cannot recover more than its claim:

\Pi_j = \min\left( R_j, \; V_j \right)

With impairment and recovery, NAV has at most two discrete adjustments in a credit-event lifecycle:

\mathrm{NAV}_{T_1} = \mathrm{NAV}_{T_1^-} - \left( P_j - K_j \right)
\mathrm{NAV}_{T_2} = \mathrm{NAV}_{T_2^-} + \Pi_j - K_j

If no impairment was recorded, K_j = P_j and only the recovery adjustment applies.

For how credit events are handled, see Onchain / Offchain Structure. No service provider has discretion to increase NAV or allocate additional yield outside the disclosed methodology.

Redemption Queue

sUSDest redemptions use a FIFO queue. Requests are collected throughout each epoch and processed at its close.

The STRATEGY_ADMIN_ROLE services redemptions at epoch close by calling serviceRedemptions(). It must release all available USDest (vault USDest not committed to a subscription timelock) to the queue in order:

/**
 * @notice Service pending redemption requests in FIFO order, in batches
 * @param maxRequests Maximum number of requests to process in this call; the next call resumes from the cursor
 * @return Number of requests serviced
 */
function serviceRedemptions(
    uint256 maxRequests
) external returns (uint256);

serviceRedemptions is batched and cursor-based, so a long queue can be worked through in several transactions. The epoch cannot advance until every eligible request has been filled or available USDest is exhausted, so the strategy role cannot hold liquidity back from the queue. Epoch closes are scheduled: the next close is always the previous close plus EPOCH_LENGTH, never the timestamp of the servicing call.

Bond Position Record

Each bond position is an ERC-3643 security token held by the BondPositionManager on behalf of the sUSDest vault. It is the onchain evidence of a position whose legal rights are set by the bond documents and held by the Holding Subsidiary. The bond token is not separately marketed to users. It is not the underlying real estate, it does not replace the bond documents, and depositors never hold it directly.

Function Applicability to bond token Notes
Evidence of ownership Yes The BondPositionManager's balance, held under an ONCHAINID identity backed by the Holding Subsidiary, evidences the position. Where the bond terms designate the token ledger as the register, it is authoritative; otherwise it is reconciled to the issuer or transfer-agent register.
Record of payment right Indirect The bond terms create the right to coupons and principal. Vault accounting records each position's coupon schedule, accrued coupon, receipts and credit status, and reflects them in both share prices.
Routing Yes Coupons, principal and recoveries for a position are deposited into the vault against that bond token, so cash flows are attributed to the right position.
Transfer instrument No Bond tokens do not circulate. ERC-3643 restricts transfer to verified identities, and the protocol moves them only for issuer redemption or maturity. Economic exposure transfers through sUSDest, a fungible ERC-20.

Roles

Role Holder Scope
DEFAULT_ADMIN_ROLE TimelockController Grants and revokes roles, upgrades
STRATEGY_ADMIN_ROLE Strategy multisig Position managers, harvest, subscriptions, redemptions servicing
CREDIT_AGENT_ROLE Holding Subsidiary multisig recordCreditEvent, flagInsolvency, recordImpairment, recordRecovery
MINT_ALLOWLIST_ROLE Foundation compliance multisig Add or remove approved institutions on the mint/redeem allowlist
PAUSE_ADMIN_ROLE Pause guardian multisig Pause and unpause core contracts
RESERVE_MANAGER_ROLE BasePositionManager and BondPositionManager (contracts) USDest.protocolMint / protocolBurn — the only paths that mint USDest without an institutional USDC deposit (base yield, coupons, principal, recoveries) or burn it for subscription settlement

Vault operations execution

Every privileged call is submitted from a Safe multisig, so no single key can move protocol value.

The strategy role does have discretion over allocation: how much capital to keep as USDest, and which allowlisted bonds to subscribe to and when. That discretion is limited by onchain checks (reserve floor, per-issuer cap, per-bond cap, allowlist timelock) and by the published eligibility criteria.

No role has discretion to allocate to non-allowlisted bonds, change the redemption order, hold available liquidity back from the queue, change NAV methodology, redirect ordinary-course payments, or determine yield distribution outside the published rules. Any offchain scheduling process is only a secure way to submit transactions within those rules.

Note: each core contract has a pause function controlled by a dedicated pause-admin role. It is a safety measure. While paused, a contract stops value-moving protocol paths, but all balances stay put and every read function keeps working. In practice, USDest mint and burn, base-yield harvest, subscription commit and settle, and redemption request, servicing and claim are all put on hold. Pausing never freezes ERC-20 transfers of USDest or sUSDest: holders can always send their tokens, and DeFi integrations that only transfer the tokens keep working.

The pause guardian may use this role only in a few urgent cases: a suspected bug or active exploit; abnormal behaviour in a system the protocol relies on, such as USDC, a T-bill fund, a bond token or an oracle; or a brief window for an emergency upgrade.

For security review details, see Audits. For deployed references, see Contract Addresses.