SPEC 02 · DOC-2026-07-11

Issuance

Issuance is the act of bringing collateral to the vault and emitting a calibrated stablecoin against it. The path is deliberately short: admit collateral, prove the ratio, mint, and let redemption run the exact same math in reverse. Every unit in circulation is backed by a recorded deposit, and every deposit is priced through the oracle mesh before a single unit is emitted.

Lifecycle

Seven instructions carry a stablecoin from registration to redemption. The order is enforced on-chain — you cannot mint before collateral is deposited, and you cannot redeem collateral you have not first unlocked by burning supply.

StepInstructionEffect
1initialize_configAdmin sets global thresholds and admin key
2register_stableRegisters a mint under a peg currency and mode
3deposit_collateralMoves collateral into the vault ATA
4mint_stableEmits units after ratio and breaker checks
5burn_stableRetires supply, unlocks redemption
6redeem_collateralReturns proportional collateral to the issuer
7commit_attestationAttestor writes a signed reserve snapshot

Collateral modes

Three modes. One demo path. No fiat claims.

A stablecoin is registered under exactly one collateral mode, fixed at register_stable time. The mode sets the minimum mint ratio the program will accept. The public demo registers only in the crypto over-collateralized mode — Pegd holds no fiat and makes no real-dollar backing claim.

Modemin_ratio_bpsReserve basis
OVERCOLLATERALIZED_CRYPTO15000On-chain crypto, 150% floor (demo mode)
ATTESTED_FIAT10100Off-chain fiat proven by signed attestation
RWA_BACKED10500Tokenized T-bills or notes with attestation

The two attested modes exist in the type system and the registration path, but they require a custody attestor role and are not exercised by the public demo. Only the crypto mode mints in a fully on-chain, self-verifiable way.

Collateral ratio

The ratio is the single number the whole framework calibrates against. It is stored as basis points in collateral_ratio_bps — a u32, wide enough that a heavily over-collateralized vault never overflows. A ratio of 10000 is exactly one-to-one; 15000 is 150 percent.

// Ratio in basis points. Peg currency valuation via the oracle.
// collateral_value and minted_value are both e6 fixed-point USD.
fn ratio_bps(collateral_value_e6: u128, minted_value_e6: u128) -> u32 {
    if minted_value_e6 == 0 {
        return u32::MAX; // nothing minted yet: unbounded coverage
    }
    ((collateral_value_e6 * 10_000) / minted_value_e6) as u32
}

// A mint is only accepted if the POST-mint ratio still clears the floor.
fn assert_mint_allowed(v: &VaultState, cfg: &Config, add_value_e6: u128) -> Result<()> {
    require!(!v.is_paused, PegdError::IssuancePaused);
    let post = ratio_bps(v.collateral_value_e6, v.minted_value_e6 + add_value_e6);
    require!(post >= cfg.circuit_bps, PegdError::CircuitBreaker); // 12000
    require!(post >= cfg.min_ratio_bps, PegdError::BelowMinRatio); // 15000 crypto
    Ok(())
}

Two floors guard every mint. The circuit-breaker floor (circuit_bps, 12000 / 120 percent) is checked first — below it, issuance halts entirely. The mode floor (min_ratio_bps, 15000 / 150 percent for crypto) is the healthy operating minimum a new mint must clear. The ratio is recomputed on-chain from live vault balances on every mint; a client-side number is never trusted.

Mint and burn accounting

SUPPLY GROWS

Mint

mint_stable revalues the vault, checks both floors on the post-mint state, then CPIs into Token-2022 to emit units. The vault PDA is the mint authority — no external key can inflate supply.

SUPPLY SHRINKS

Burn

burn_stable retires units and decrements total_minted. Burning raises the ratio, so it is always permitted — even while issuance is paused — and it is what unlocks proportional redemption.

Redemption is strictly proportional. Burning x percent of outstanding supply releases at most x percent of the vault's collateral, so no redeemer can drain reserves ahead of the peg. The program computes the release amount from raw balances at the moment of the call, never from a cached figure.

Token-2022 interest-bearing yield

Every Pegd stablecoin is a Token-2022 mint with the interest-bearing extension attached at allocation. The extension does not move tokens — it declares a rate, and wallets and explorers compute the accrued amount from it. The rate may be zero; when it is set, the vault PDA is the sole rate authority, updated through a single CPI.

// set_yield_rate: only the vault PDA may change the accrual rate.
// rate is in basis points per year; interest is non-custodial display accrual.
pub fn set_yield_rate(ctx: Context<SetYieldRate>, new_rate_bps: i16) -> Result<()> {
    require_keys_eq!(
        ctx.accounts.authority.key(),
        ctx.accounts.config.admin,
        PegdError::Unauthorized
    );
    anchor_spl::token_2022_extensions::interest_bearing_mint_update_rate(
        ctx.accounts.into_update_rate_ctx().with_signer(&[vault_seeds]),
        new_rate_bps,
    )?;
    Ok(())
}

Because the yield is expressed through the mint extension rather than a rebasing balance, it never touches the collateral ratio math above — issuance accounting stays denominated in raw minted units, and the interest figure is a presentation layer on top.

Program-derived addresses

Issuance state lives in a small set of PDAs derived from the stablecoin mint. The collateral itself sits in an associated token account owned by the vault PDA, so custody is program-controlled from the first deposit.

config    = pda([b"config"], program_id);              // global thresholds
stable    = pda([b"stable", authority.as_ref()], program_id);
vault     = pda([b"vault", stable_mint.as_ref()], program_id);
risk      = pda([b"risk", stable_mint.as_ref()], program_id);

// Collateral custody: an ATA owned by the vault PDA.
collateral_vault = associated_token_address(
    /* owner */ vault,
    /* mint  */ collateral_mint,
);

Read next

Back to Docs