{ "address": "5MBjhNUUguLTPNR5WG6YBUUw7vUcxQ14ARw3NsS3rKu4", "metadata": { "name": "mint_redeem", "version": "0.1.0", "spec": "0.1.0", "description": "Continuum Markets Mint/Redeem Engine" }, "instructions": [ { "name": "add_collateral_vault", "docs": [ "Add a new collateral vault (admin only)" ], "discriminator": [ 142, 7, 10, 27, 165, 53, 72, 33 ], "accounts": [ { "name": "market", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116 ] }, { "kind": "account", "path": "market.asset_symbol", "account": "Market" } ] } }, { "name": "authority", "signer": true, "relations": [ "market" ] }, { "name": "collateral_mint", "docs": [ "The new collateral token mint to add" ] }, { "name": "collateral_vault", "docs": [ "The vault token account for this collateral" ], "writable": true } ], "args": [ { "name": "collateral_type", "type": { "defined": { "name": "CollateralType" } } }, { "name": "weight_bps", "type": "u16" } ] }, { "name": "apply_corporate_action", "docs": [ "Record a corporate action (split, reverse split, or any other pure", "change of share UNITS) by folding its ratio into the market's cumulative", "price adjustment.", "", "**What this does.** Nothing, immediately. It writes two integers and", "touches no price, no supply, no collateral, no γ. Every stored value", "stays exactly as it was, and every outstanding claim is worth exactly", "what it was worth one slot earlier. What changes is the INTERPRETATION", "of the NEXT raw oracle print: from the following `update_risk_state` on,", "an incoming price is multiplied by `num/den` before it is stored.", "", "**Why that is exactly conserving.** A 2-for-1 split halves the price and", "doubles the share count; it creates and destroys no value. So the", "adjusted price `P_adj = P_raw · num/den` is CONTINUOUS across the event:", "identical immediately before and immediately after. Because `l_nav`,", "`K = initial_l_price · initial_s_price` and hence `s_nav` are all", "functions of `P_adj` alone, every leg's NAV is unchanged too, and the", "transfer between longs and shorts is zero by construction.", "", "That is the precise sense in which this is tractable and a spot", "RE-ANCHOR is not. Both look like \"move the reference price\". But a", "re-anchor changes the payoff SHAPE — it moves the vertex of the cosh", "bowl, so the pair is worth something different afterwards, and it cannot", "be made conserving without either moving value between the legs or", "redenominating supply. A split changes only the units the shape is", "measured in, which is why undoing it in the unit mapping costs nothing.", "", "**Operationally.** Ex-dates are published weeks ahead, so arm the ratio", "before the ex-date open and there is no outage at all. Deliberately NOT", "auto-detected: the 25% move guard exists to catch a compromised keeper,", "and teaching it to recognise a split would hand that same keeper a way", "to relabel a bad price as a corporate action.", "", "**Ordering matters below the guard threshold.** A post-action print is", "rejected — and the market safely halts — only when `1 − den/num > 25%`,", "i.e. ratios above about 1.333. Anything gentler (4:3, 5:4, a stock", "dividend) is INDISTINGUISHABLE from a real price move and will be", "absorbed as one if this lands late. There is no on-chain backstop for", "that case; arming ahead of the ex-date is the control.", "", "Authority-gated, not keeper-gated: this is a governance act on the", "market's definition, not part of the hot price loop." ], "discriminator": [ 72, 217, 151, 23, 156, 233, 73, 79 ], "accounts": [ { "name": "market", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116 ] }, { "kind": "account", "path": "market.asset_symbol", "account": "Market" } ] } }, { "name": "authority", "signer": true, "relations": [ "market" ] } ], "args": [ { "name": "params", "type": { "defined": { "name": "CorporateActionParams" } } } ] }, { "name": "cancel_redemption", "docs": [ "Give back the unpaid part of a request and close it (owner only).", "Reads no `Market` and needs no keeper, so it works when the market is", "paused, the price is stale or the keeper is down. Returns the escrowed", "L and S and all rent to the owner. Returns each escrow's ACTUAL balance", "(the unpaid remainder plus any atoms someone sent it), so a donation can", "never block the close or strand the request slot." ], "discriminator": [ 197, 243, 101, 86, 2, 37, 105, 106 ], "accounts": [ { "name": "owner", "writable": true, "signer": true, "relations": [ "request" ] }, { "name": "request", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 114, 101, 100, 101, 109, 112, 116, 105, 111, 110 ] }, { "kind": "account", "path": "request.market", "account": "RedemptionRequest" }, { "kind": "account", "path": "owner" } ] } }, { "name": "escrow_l", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 114, 101, 100, 101, 109, 112, 116, 105, 111, 110, 95, 101, 115, 99, 114, 111, 119 ] }, { "kind": "account", "path": "request" }, { "kind": "account", "path": "request.long_mint", "account": "RedemptionRequest" } ] } }, { "name": "escrow_s", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 114, 101, 100, 101, 109, 112, 116, 105, 111, 110, 95, 101, 115, 99, 114, 111, 119 ] }, { "kind": "account", "path": "request" }, { "kind": "account", "path": "request.short_mint", "account": "RedemptionRequest" } ] } }, { "name": "owner_long_account", "writable": true }, { "name": "owner_short_account", "writable": true }, { "name": "token_program", "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" } ], "args": [] }, { "name": "close_market_admin", "docs": [ "Close a market account for migration/cleanup.", "Uses unchecked account to handle both old and new struct layouts.", "Authority is verified by reading raw bytes at offset [8..40]." ], "discriminator": [ 81, 108, 184, 116, 233, 20, 237, 222 ], "accounts": [ { "name": "market", "docs": [ "Authority is verified by reading raw bytes [8..40] in the instruction body." ], "writable": true }, { "name": "authority", "writable": true, "signer": true }, { "name": "market_advance", "docs": [ "may not exist. Read by `advance_outstanding`." ], "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116, 95, 97, 100, 118, 97, 110, 99, 101 ] }, { "kind": "account", "path": "market" } ] } } ], "args": [] }, { "name": "configure_market_advance", "docs": [ "Set a market's advance cap and lender (market.authority). Creates the", "`MarketAdvance` PDA on first use. `max_advance_bps = 0` turns advances", "off. The lender (the token account advances come from and are repaid", "to) may change only while nothing is outstanding." ], "discriminator": [ 123, 86, 250, 195, 145, 69, 248, 88 ], "accounts": [ { "name": "market", "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116 ] }, { "kind": "account", "path": "market.asset_symbol", "account": "Market" } ] } }, { "name": "authority", "writable": true, "signer": true, "relations": [ "market" ] }, { "name": "market_advance", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116, 95, 97, 100, 118, 97, 110, 99, 101 ] }, { "kind": "account", "path": "market" } ] } }, { "name": "lender", "docs": [ "The token account advances come from and are repaid to." ] }, { "name": "system_program", "address": "11111111111111111111111111111111" } ], "args": [ { "name": "params", "type": { "defined": { "name": "ConfigureAdvanceParams" } } } ] }, { "name": "configure_risk_fees", "docs": [ "Configure risk-based fee parameters (admin only)" ], "discriminator": [ 108, 30, 96, 21, 214, 197, 213, 133 ], "accounts": [ { "name": "market", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116 ] }, { "kind": "account", "path": "market.asset_symbol", "account": "Market" } ] } }, { "name": "authority", "signer": true, "relations": [ "market" ] } ], "args": [ { "name": "params", "type": { "defined": { "name": "ConfigureRiskFeesParams" } } } ] }, { "name": "configure_worst_case_quoting", "docs": [ "Configure worst-case quoting parameters (admin only)" ], "discriminator": [ 40, 82, 32, 30, 103, 189, 226, 15 ], "accounts": [ { "name": "market", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116 ] }, { "kind": "account", "path": "market.asset_symbol", "account": "Market" } ] } }, { "name": "authority", "signer": true, "relations": [ "market" ] } ], "args": [ { "name": "enabled", "type": { "option": "bool" } }, { "name": "normal_multiplier", "type": { "option": "u16" } }, { "name": "proxy_multiplier", "type": { "option": "u16" } }, { "name": "stress_multiplier", "type": { "option": "u16" } } ] }, { "name": "configure_yield_ceiling", "docs": [ "Configure yield ceiling and enable/disable yield management (admin only).", "The ceiling may reach 100%: all idle collateral lent and recalled just in time", "(Rafael, 2026-10-12). It used to stop at 90%. The keeper's allocator still keeps", "a small working float so routine redemptions never wait for a recall." ], "discriminator": [ 101, 122, 64, 206, 15, 3, 90, 217 ], "accounts": [ { "name": "market", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116 ] }, { "kind": "account", "path": "market.asset_symbol", "account": "Market" } ] } }, { "name": "authority", "signer": true, "relations": [ "market" ] } ], "args": [ { "name": "ceiling_bps", "type": { "option": "u16" } }, { "name": "enabled", "type": { "option": "bool" } } ] }, { "name": "create_token_metadata", "docs": [ "Create Metaplex token metadata for a market's L or S mint.", "Must be called by the market authority.", "The market PDA is the mint authority and signs the CPI." ], "discriminator": [ 221, 80, 176, 37, 153, 188, 160, 68 ], "accounts": [ { "name": "market", "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116 ] }, { "kind": "account", "path": "market.asset_symbol", "account": "Market" } ] } }, { "name": "authority", "writable": true, "signer": true, "relations": [ "market" ] }, { "name": "mint", "docs": [ "The L or S mint to create metadata for.", "Must be either market.long_mint or market.short_mint." ] }, { "name": "metadata", "writable": true }, { "name": "token_metadata_program" }, { "name": "system_program", "address": "11111111111111111111111111111111" } ], "args": [ { "name": "name", "type": "string" }, { "name": "symbol", "type": "string" }, { "name": "uri", "type": "string" } ] }, { "name": "deploy_collateral_to_yield", "docs": [ "Deploy a portion of idle collateral to a lending protocol (keeper only).", "", "This instruction moves USDC from the collateral vault to the keeper's", "intermediary account. The keeper then deposits it into Kamino/MarginFi", "in the next instruction of the same atomic transaction.", "", "AUDIT H2 (custody — REMAINING WORK, needs venue integration + governance):", "funds transit a keeper-owned ATA with NO on-chain proof they reach a", "venue; `deployed_to_yield` is a keeper-asserted scalar. The bound today is", "`yield_ceiling_bps` (a fraction of THIS market's total_collateral). Full", "fix (not doable without external CPI wiring / an ops decision):", "1. CPI directly into a WHITELISTED venue so the deposit is proven", "on-chain (or constrain the destination to an admin-approved", "intermediary pubkey — needs a new Market field + realloc migration).", "2. Move `configure_yield_ceiling` + this instruction's authority behind", "a multisig/timelock (ops).", "3. Per-tx / rolling-window cap (needs Market window state → realloc).", "Compensating controls now: `mark_yield_impairment` (M2) socializes a", "venue loss; the off-chain `yield-vault-reconciler` + `solvency-monitor`", "scripts alert when venue-redeemable < deployed_to_yield." ], "discriminator": [ 64, 186, 222, 148, 67, 180, 139, 19 ], "accounts": [ { "name": "market", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116 ] }, { "kind": "account", "path": "market.asset_symbol", "account": "Market" } ] } }, { "name": "keeper", "docs": [ "Must be the market's keeper_authority" ], "signer": true }, { "name": "collateral_vault", "docs": [ "Collateral vault owned by the market PDA" ], "writable": true }, { "name": "keeper_usdc_account", "docs": [ "Keeper's USDC intermediary account (destination before lending deposit).", "Must be owned by the keeper signer." ], "writable": true }, { "name": "token_program", "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" }, { "name": "collateral_authority", "optional": true } ], "args": [ { "name": "amount", "type": "u64" }, { "name": "_protocol", "type": "u8" } ] }, { "name": "donate_to_vault", "docs": [ "Permissionless top-up of the collateral vault.", "", "Increases `total_collateral` and the vault balance without minting any", "tokens, so every holder's collateralization strictly improves. It funds", "the protocol's safety buffer and nothing else: the donor receives no", "reward. (A per-donor fee waiver used to be granted here; it was removed", "on 13 Oct 2026, audit MR-13.)" ], "discriminator": [ 94, 168, 205, 31, 202, 255, 40, 204 ], "accounts": [ { "name": "market", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116 ] }, { "kind": "account", "path": "market.asset_symbol", "account": "Market" } ] } }, { "name": "collateral_vault", "docs": [ "Per-market collateral vault — must match the one bound to this market", "at init. Owned by the Market PDA." ], "writable": true }, { "name": "donor_collateral", "docs": [ "Source ATA. Holds the cUSDC the donor is sending in. Must hold the", "market's collateral mint; the SPL transfer below validates the mint", "match implicitly (cross-mint transfers fail in the SPL token program)." ], "writable": true }, { "name": "donor", "writable": true, "signer": true }, { "name": "token_program", "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" } ], "args": [ { "name": "amount", "type": "u64" } ] }, { "name": "enable_multi_collateral", "docs": [ "Enable multi-collateral mode for a market (admin only)" ], "discriminator": [ 191, 210, 54, 44, 42, 94, 10, 136 ], "accounts": [ { "name": "market", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116 ] }, { "kind": "account", "path": "market.asset_symbol", "account": "Market" } ] } }, { "name": "authority", "signer": true, "relations": [ "market" ] } ], "args": [] }, { "name": "fund_collateral", "docs": [ "Admin top-up of a market's collateral (listing buffers, redistribution).", "Transfers `amount` cUSDC from the authority's token account into", "`market.collateral_vault` and credits `total_collateral`. Like", "`donate_to_vault` there is no price-freshness gate: a deposit only", "raises the ratio." ], "discriminator": [ 55, 123, 168, 146, 36, 55, 209, 213 ], "accounts": [ { "name": "market", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116 ] }, { "kind": "account", "path": "market.asset_symbol", "account": "Market" } ] } }, { "name": "authority", "signer": true, "relations": [ "market" ] }, { "name": "collateral_vault", "writable": true }, { "name": "authority_collateral", "docs": [ "The authority's cUSDC. SPL Token enforces that `authority` owns it." ], "writable": true }, { "name": "token_program", "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" } ], "args": [ { "name": "amount", "type": "u64" } ] }, { "name": "fund_collateral_from", "docs": [ "CPI-friendly twin of `fund_collateral`. The market authority still signs", "(`has_one = authority`), but the cUSDC comes from `funder_collateral`,", "a token account owned by a SEPARATE signer `funder`, which may be a PDA", "signing through CPI (the CLP's GlobalClp backstopping a market from its", "treasury). Credits `total_collateral` exactly like `fund_collateral` and", "emits the same `CollateralFunded` event." ], "discriminator": [ 205, 129, 21, 63, 146, 211, 156, 18 ], "accounts": [ { "name": "market", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116 ] }, { "kind": "account", "path": "market.asset_symbol", "account": "Market" } ] } }, { "name": "authority", "docs": [ "Must equal `market.authority`." ], "signer": true, "relations": [ "market" ] }, { "name": "funder", "docs": [ "Owner of `funder_collateral`; may be a PDA signing through CPI." ], "signer": true }, { "name": "collateral_vault", "writable": true }, { "name": "funder_collateral", "writable": true }, { "name": "token_program", "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" } ], "args": [ { "name": "amount", "type": "u64" } ] }, { "name": "harvest_collateral_yield", "docs": [ "Harvest net collateral yield INTO this market's collateral (keeper only).", "", "Call after recall_collateral_from_yield: principal goes back to the vault,", "then this deposits the net interest (yield_amount) into the same vault and", "credits it to `total_collateral`, so the yield raises this market's CR by", "exactly that amount. Collateral yield is protocol-side; whatever ends up", "above the buffer target still reaches the CLP through `withdraw_excess_to_clp`." ], "discriminator": [ 202, 35, 235, 40, 37, 112, 16, 252 ], "accounts": [ { "name": "market", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116 ] }, { "kind": "account", "path": "market.asset_symbol", "account": "Market" } ] } }, { "name": "keeper", "signer": true }, { "name": "keeper_usdc_account", "docs": [ "Keeper's USDC source account (holds the net yield)" ], "writable": true }, { "name": "collateral_vault", "docs": [ "The market's collateral vault: the yield funds this market's CR. Same slot", "as the former `clp_vault`, so the wire layout is unchanged." ], "writable": true }, { "name": "token_program", "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" } ], "args": [ { "name": "yield_amount", "type": "u64" } ] }, { "name": "initialize_market", "docs": [ "Initialize a new synthetic asset market (admin only: the signer must be", "this program's upgrade authority)." ], "discriminator": [ 35, 35, 189, 193, 155, 48, 170, 203 ], "accounts": [ { "name": "market", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116 ] }, { "kind": "arg", "path": "params.asset_symbol" } ] } }, { "name": "authority", "writable": true, "signer": true }, { "name": "long_mint" }, { "name": "short_mint" }, { "name": "collateral_mint" }, { "name": "collateral_vault", "writable": true }, { "name": "oracle" }, { "name": "system_program", "address": "11111111111111111111111111111111" }, { "name": "token_program", "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" }, { "name": "rent", "address": "SysvarRent111111111111111111111111111111111" }, { "name": "program", "docs": [ "Admin gate: the signer must be this program's upgrade authority, so nobody", "else can squat a future symbol's Market PDA and become its `authority`.", "Appended LAST so pre-existing account indices stay stable for hand-built", "encoders." ], "address": "5MBjhNUUguLTPNR5WG6YBUUw7vUcxQ14ARw3NsS3rKu4" }, { "name": "program_data" } ], "args": [ { "name": "params", "type": { "defined": { "name": "InitMarketParams" } } } ] }, { "name": "keeper_burn_single", "docs": [ "Keeper-authorized single-side BURN. Removes one side from the", "keeper's wallet WITHOUT paying out collateral from the vault.", "", "Purpose: residual cleanup for arb cycles where a `keeper_mint_single`", "produced tokens that didn't fully fill on the DEX. The current", "`keeper_redeem_single` path pays the keeper out at *current* NAV,", "which (a) drains the vault when NAV has drifted upward since mint", "and (b) hides the inventory cost as silent vault drift instead of", "an explicit keeper-side P&L line.", "", "Burning the residual instead:", "- vault keeps the original mint-time deposit (solvency-safe)", "- total_l/s_supply decrements (asymmetry no worse than at mint)", "- keeper team eats the cost of unsold inventory (visible in P&L)", "", "Does NOT decrement `total_collateral` — that field tracks cUSDC,", "and no cUSDC is leaving the vault. Per-token collateralization", "strictly improves: same numerator, smaller denominator (one fewer", "token outstanding)." ], "discriminator": [ 133, 161, 250, 121, 74, 124, 245, 201 ], "accounts": [ { "name": "market", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116 ] }, { "kind": "account", "path": "market.asset_symbol", "account": "Market" } ] } }, { "name": "keeper", "writable": true, "signer": true }, { "name": "keeper_long_account", "writable": true }, { "name": "keeper_short_account", "writable": true }, { "name": "long_mint", "writable": true }, { "name": "short_mint", "writable": true }, { "name": "token_program", "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" } ], "args": [ { "name": "is_long", "type": "bool" }, { "name": "token_amount", "type": "u64" } ] }, { "name": "keeper_mint_single", "docs": [ "Keeper-authorized single-side mint. Deposits collateral, mints ONLY one", "side (L or S). No fees, no worst-case discount, no dev tax — the keeper", "is the protocol's own arber and is trusted to:", "1. Sign with `market.keeper_authority`", "2. Always close any single-side position within the same arb cycle", "(mint L_only → sell L → cUSDC) so net inventory is zero between ticks", "", "Uses the base TWAP price (or oracle in Normal). The keeper paying full", "NAV for one side preserves overall solvency: collateral_vault grows by", "exactly the NAV value of the new tokens. Where paired-mint required", "matching supplies (L_supply == S_supply) for invariant convenience, the", "per-token NAV-collateralization here gives us the same \"claim ≤", "collateral\" guarantee at every NAV(t) — supplies just drift, which is", "fine for transient keeper inventory." ], "discriminator": [ 79, 92, 124, 120, 251, 35, 64, 243 ], "accounts": [ { "name": "market", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116 ] }, { "kind": "account", "path": "market.asset_symbol", "account": "Market" } ] } }, { "name": "keeper", "writable": true, "signer": true }, { "name": "keeper_collateral", "writable": true }, { "name": "keeper_long_account", "writable": true }, { "name": "keeper_short_account", "writable": true }, { "name": "long_mint", "writable": true }, { "name": "short_mint", "writable": true }, { "name": "collateral_vault", "writable": true }, { "name": "oracle" }, { "name": "token_program", "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" }, { "name": "collateral_authority", "optional": true } ], "args": [ { "name": "is_long", "type": "bool" }, { "name": "collateral_amount", "type": "u64" } ] }, { "name": "keeper_redeem_single", "docs": [ "Keeper-authorized single-side redeem. Burns one side (L or S), returns", "collateral at NAV. No fees, no worst-case adjustment." ], "discriminator": [ 163, 83, 214, 118, 39, 26, 65, 196 ], "accounts": [ { "name": "market", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116 ] }, { "kind": "account", "path": "market.asset_symbol", "account": "Market" } ] } }, { "name": "keeper", "writable": true, "signer": true }, { "name": "keeper_collateral", "writable": true }, { "name": "keeper_long_account", "writable": true }, { "name": "keeper_short_account", "writable": true }, { "name": "long_mint", "writable": true }, { "name": "short_mint", "writable": true }, { "name": "collateral_vault", "writable": true }, { "name": "oracle" }, { "name": "token_program", "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" }, { "name": "collateral_authority", "optional": true } ], "args": [ { "name": "is_long", "type": "bool" }, { "name": "token_amount", "type": "u64" } ] }, { "name": "mark_yield_impairment", "docs": [ "Write down an impaired yield deployment (admin/governance only; audit M2).", "", "`recall_collateral_from_yield` only ever decrements `deployed_to_yield` by", "what physically returns, and never touches `total_collateral`. So if a", "lending venue freezes or loses principal, `total_collateral` (the solvency", "source of truth the CR/haircut math reads) keeps reporting phantom", "backing: the CR check returns \"fully collateralized\", early redeemers exit", "at par, and stragglers eat 100% of the loss (hidden insolvency).", "", "This instruction realizes the loss by decrementing BOTH `deployed_to_yield`", "(the funds are gone from the venue) AND `total_collateral` (real backing", "shrank). The pro-rata `solvency_haircut_gross` then measures true CR and", "SOCIALIZES the loss uniformly across all remaining holders. Gated on the", "admin `authority` (not the keeper): writing down collateral is a governance", "action, and this can only REDUCE reported backing (never inflate it), so a", "mistaken call is conservative, never a drain." ], "discriminator": [ 69, 208, 171, 186, 90, 225, 9, 194 ], "accounts": [ { "name": "market", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116 ] }, { "kind": "account", "path": "market.asset_symbol", "account": "Market" } ] } }, { "name": "authority", "signer": true, "relations": [ "market" ] }, { "name": "market_advance", "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116, 95, 97, 100, 118, 97, 110, 99, 101 ] }, { "kind": "account", "path": "market" } ] } } ], "args": [ { "name": "amount", "type": "u64" } ] }, { "name": "mint_paired", "docs": [ "Mint paired L + S tokens by depositing collateral", "This is the ONLY way to create new tokens - always mints both L and S", "Invariant: L_value + S_value = collateral_amount (always)", "Uses TWAP for pricing in non-Normal risk states for stability" ], "discriminator": [ 230, 60, 17, 115, 108, 123, 216, 82 ], "accounts": [ { "name": "market", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116 ] }, { "kind": "account", "path": "market.asset_symbol", "account": "Market" } ] } }, { "name": "user", "writable": true, "signer": true }, { "name": "user_collateral", "writable": true }, { "name": "user_long_account", "writable": true }, { "name": "user_short_account", "writable": true }, { "name": "long_mint", "writable": true }, { "name": "short_mint", "writable": true }, { "name": "collateral_vault", "writable": true }, { "name": "dev_token_account", "writable": true }, { "name": "oracle" }, { "name": "token_program", "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" } ], "args": [ { "name": "collateral_amount", "type": "u64" } ] }, { "name": "permissionless_burn", "docs": [ "Permissionless single-side burn — anyone can call to burn L or S", "tokens from their own ATA, reducing `total_l_supply` /", "`total_s_supply` accordingly. NO collateral payout.", "", "Used for:", "1. Voluntary forfeiture (e.g. admin burning recovered tokens to", "reduce supply asymmetry).", "2. CLP-program CPI: `clp_burn_excess` calls this with the", "CLP-PDA as the source-account owner / signer (via", "`invoke_signed` with the CLP PDA seeds), letting the CLP", "retire its own L/S inventory after a zombie-pool drain.", "", "SAFETY: this MUST never burn collateral. Accounts struct binds", "`long_mint` and `short_mint` to `market.long_mint` /", "`market.short_mint`, and the `source_account.mint` is validated", "against the appropriate side mint at runtime. The collateral_mint", "is never reachable via this code path." ], "discriminator": [ 183, 158, 219, 39, 41, 51, 56, 254 ], "accounts": [ { "name": "market", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116 ] }, { "kind": "account", "path": "market.asset_symbol", "account": "Market" } ] } }, { "name": "authority", "docs": [ "Owner of `source_account`. SPL Token enforces signer == owner on", "the burn CPI, so a malicious caller cannot burn someone else's tokens." ], "signer": true }, { "name": "source_account", "docs": [ "Token account whose tokens are being burned. Must be owned by", "`authority` and hold the L or S mint matching `is_long`." ], "writable": true }, { "name": "long_mint", "writable": true }, { "name": "short_mint", "writable": true }, { "name": "token_program", "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" } ], "args": [ { "name": "is_long", "type": "bool" }, { "name": "amount", "type": "u64" } ] }, { "name": "realloc_market", "docs": [ "Grow a Market account to the current struct size. MUST be run for every", "live market immediately after any deploy that adds fields — until it is,", "the account is too short to deserialize and EVERY other instruction on", "that market fails.", "", "Validated by hand because the account is deliberately untyped (see", "`ReallocMarket`): owner, discriminator, then `authority`, which is the", "first field and therefore at a fixed offset that no field addition can", "move. Idempotent — an already-grown account is left alone." ], "discriminator": [ 175, 105, 121, 69, 55, 187, 47, 47 ], "accounts": [ { "name": "market", "docs": [ "at a fixed offset). It CANNOT be `Account<'info, Market>`: Anchor", "deserializes a typed account inside `try_accounts`, before any `realloc`", "constraint runs, so an account that is too SMALL for the current struct", "fails to deserialize and can never reach the very instruction that would", "grow it. Typing this account is what would make the migration", "impossible." ], "writable": true }, { "name": "authority", "writable": true, "signer": true }, { "name": "system_program", "address": "11111111111111111111111111111111" } ], "args": [] }, { "name": "reanchor_gamma", "docs": [ "Renew the γ charging budget by folding the accumulated decay into the", "short anchor. Zero-arg and authority-gated.", "", "`initial_s_price ← floor(initial_s_price · γ / 1e9)`, then `γ ← 1.0`.", "Short NAV is `(initial_l · initial_s / P) · γ`, so moving γ into the", "anchor and resetting it leaves every holder's claim IDENTICAL at every", "price. Nobody is refunded and nothing is taken — burned budget stays", "burned. What changes is that charging can continue: σ² funding never", "terminates, so without renewal a persistently volatile market pins at", "GAMMA_FLOOR and simply stops charging while the exposure carries on.", "After this, the floor is a per-EPOCH fault bound rather than a lifetime", "ceiling, which is what it was always meant to be.", "", "Deliberately NOT routed through `set_s_gamma_index`: that path's ratchet", "rejects a raise by design, and a two-transaction fold would leave a live", "on-chain window where the market is mispriced between the two writes.", "", "The epoch bump is what protects that window here — any decay post", "computed against the old epoch fails its CAS instead of re-charging the", "whole folded epoch." ], "discriminator": [ 186, 190, 91, 96, 38, 163, 228, 41 ], "accounts": [ { "name": "market", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116 ] }, { "kind": "account", "path": "market.asset_symbol", "account": "Market" } ] } }, { "name": "authority", "signer": true, "relations": [ "market" ] } ], "args": [] }, { "name": "rebalance_collateral", "docs": [ "Keeper-authorized CROSS-MARKET collateral move (the rebalance EXECUTION): transfer", "up to `amount` cUSDC from `from_market`'s collateral vault directly to `to_market`'s —", "moving EXCESS from an over-collateralized market to fund an under-collateralized one", "FASTER, instead of waiting for fresh capital. The move is CLAMPED to what the source", "can spare: collateral above its OWN dynamic target at the stored price (the planner's", "\"never drain below own CR\" constraint, on-chain), capped by its liquid collateral.", "The keeper plans at its own price, so a request a hair over that amount moves the", "safe amount instead of reverting; only a source with nothing to spare fails. Both", "markets must share the keeper authority. NAV = the source's keeper-posted TWAP", "(freshness-gated). Mirror amounts come from collateral_rebalancer::plan_rebalance." ], "discriminator": [ 224, 133, 94, 208, 31, 130, 159, 41 ], "accounts": [ { "name": "from_market", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116 ] }, { "kind": "account", "path": "from_market.asset_symbol", "account": "Market" } ] } }, { "name": "to_market", "docs": [ "Must differ from `from_market`: both copies are written back on exit and the", "destination's (credited) copy lands last, so a self-move would mint ledger." ], "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116 ] }, { "kind": "account", "path": "to_market.asset_symbol", "account": "Market" } ] } }, { "name": "from_vault", "writable": true }, { "name": "to_vault", "writable": true }, { "name": "keeper", "docs": [ "Shared keeper authority — must be both markets' keeper_authority." ], "signer": true }, { "name": "token_program", "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" } ], "args": [ { "name": "amount", "type": "u64" } ] }, { "name": "recall_collateral_from_yield", "docs": [ "Recall collateral previously deployed to a lending protocol (keeper only).", "", "The keeper first withdraws from Kamino/MarginFi (returning principal to", "keeper's ATA), then calls this instruction in the same transaction to", "move the funds back into the collateral vault and update accounting." ], "discriminator": [ 132, 105, 243, 82, 73, 200, 201, 32 ], "accounts": [ { "name": "market", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116 ] }, { "kind": "account", "path": "market.asset_symbol", "account": "Market" } ] } }, { "name": "keeper", "signer": true }, { "name": "collateral_vault", "docs": [ "Collateral vault (destination for recalled funds)" ], "writable": true }, { "name": "keeper_usdc_account", "docs": [ "Keeper's USDC account (source — keeper has withdrawn from lending protocol)" ], "writable": true }, { "name": "token_program", "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" } ], "args": [ { "name": "amount", "type": "u64" }, { "name": "_protocol", "type": "u8" } ] }, { "name": "receive_advance", "docs": [ "Take a liquidity advance into the collateral vault. `market.authority`", "signs (`has_one`) and so does the `funder` who owns the lender account,", "which is the GlobalClp PDA when the CLP's `advance_to_market` calls", "this. The cash is NOT credited to `total_collateral`: CR and the", "haircut never see it, and only `settle_redemption` and `repay_advance`", "can spend it. Capped at `max_advance_bps` of `total_collateral`." ], "discriminator": [ 180, 88, 38, 111, 92, 250, 249, 142 ], "accounts": [ { "name": "market", "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116 ] }, { "kind": "account", "path": "market.asset_symbol", "account": "Market" } ] } }, { "name": "authority", "signer": true, "relations": [ "market" ] }, { "name": "funder", "docs": [ "Owner of the lender account; the GlobalClp PDA signing through CPI." ], "signer": true }, { "name": "market_advance", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116, 95, 97, 100, 118, 97, 110, 99, 101 ] }, { "kind": "account", "path": "market" } ] } }, { "name": "collateral_vault", "writable": true }, { "name": "funder_collateral", "writable": true }, { "name": "token_program", "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" } ], "args": [ { "name": "amount", "type": "u64" } ] }, { "name": "redeem_paired", "docs": [ "Redeem paired L + S tokens to withdraw collateral", "User must provide both L and S tokens to redeem", "The combined value of L + S = collateral returned", "Uses TWAP for pricing in non-Normal risk states for stability", "`l_amount` and `s_amount` are the most of each leg to burn: the", "redemption burns the largest value-balanced pair inside them at the", "worst-case redeem NAVs, and the rest of the larger leg stays in the", "wallet (sell it through the trading path). Audit MR-2: a lopsided", "paired redeem was an instant one-leg sale at the stored price. The", "market's CLP redeeming its own inventory (`vault_redeem_pairs`) burns", "exactly what it asks.", "A balanced burn moves the market's net exposure by less than $1, so the", "exposure accounts of `exposure::check_redemption` (the market's CLP", "account, then the pool long and short synth vaults and the CLP's long", "and short token accounts) are no longer needed; the check stays as a guard." ], "discriminator": [ 224, 17, 233, 194, 94, 147, 63, 66 ], "accounts": [ { "name": "market", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116 ] }, { "kind": "account", "path": "market.asset_symbol", "account": "Market" } ] } }, { "name": "user", "writable": true, "signer": true }, { "name": "user_collateral", "writable": true }, { "name": "user_long_account", "writable": true }, { "name": "user_short_account", "writable": true }, { "name": "long_mint", "writable": true }, { "name": "short_mint", "writable": true }, { "name": "collateral_vault", "writable": true }, { "name": "dev_token_account", "writable": true }, { "name": "oracle" }, { "name": "token_program", "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" }, { "name": "collateral_authority", "optional": true } ], "args": [ { "name": "l_amount", "type": "u64" }, { "name": "s_amount", "type": "u64" } ] }, { "name": "redeem_single_for_vault", "docs": [ "CLP-authorized single-side redeem from the CLP vault. Mirror of", "`keeper_redeem_single` but:", "- source ATAs are CLP-PDA-owned (the L/S inventory the keeper holds", "for market-making, not the keeper-wallet ATAs);", "- destination cUSDC is `clp_vault` (the per-market working-capital", "ATA), not the keeper's USDC ATA;", "- signer is the CLP PDA (validated by `seeds = [b\"clp\", market]`", "under the canonical CLP program ID), entered via CPI from the", "CLP program's `vault_redeem_single` wrapper.", "", "Solvency: identical buffer impact as paired redeem. Each L/S token", "claims `L_NAV` / `S_NAV` USDC independently — burning N S tokens", "drops total_claims by N×S_NAV and pays out N×S_NAV from", "collateral_vault, so `buffer = collateral - total_claims` is", "preserved exactly. See the discussion in the rebalancer design doc;", "the over-collateralization buffer that exists pre-call still exists", "post-call. We additionally floor at CR ≥ 100% (same as", "`keeper_redeem_single`) — refuse to make an underwater vault worse." ], "discriminator": [ 23, 183, 92, 24, 64, 17, 138, 177 ], "accounts": [ { "name": "market", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116 ] }, { "kind": "account", "path": "market.asset_symbol", "account": "Market" } ] } }, { "name": "clp_pda", "docs": [ "CLP PDA, signing via CPI with seeds [b\"clp\", market.key()].", "Identity validated in the ix body — the body recomputes", "`find_program_address([b\"clp\", market], )` and", "rejects any other key. The `Signer<'info>` type enforces that", "the runtime saw a signature." ], "signer": true }, { "name": "clp_vault", "docs": [ "CLP's USDC ATA — destination for the redemption payout. Owner", "must be the CLP PDA (validated by Anchor against `clp_pda.key()`)." ], "writable": true }, { "name": "clp_long_account", "docs": [ "CLP's L-token ATA — burn source when `is_long=true`." ], "writable": true }, { "name": "clp_short_account", "docs": [ "CLP's S-token ATA — burn source when `is_long=false`." ], "writable": true }, { "name": "long_mint", "writable": true }, { "name": "short_mint", "writable": true }, { "name": "collateral_vault", "writable": true }, { "name": "oracle" }, { "name": "token_program", "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" }, { "name": "collateral_authority", "optional": true } ], "args": [ { "name": "is_long", "type": "bool" }, { "name": "token_amount", "type": "u64" } ] }, { "name": "repay_advance", "docs": [ "Repay the advance from the vault to its lender (market.authority or", "keeper). Never more than is outstanding, and the vault keeps the", "market's own liquid share (`redemption::repay_allowed`), so a repay can", "only return the advance's own cash. The keeper calls it when the", "market's own recall lands, before that cash is lent again." ], "discriminator": [ 247, 119, 157, 136, 70, 66, 200, 20 ], "accounts": [ { "name": "market", "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116 ] }, { "kind": "account", "path": "market.asset_symbol", "account": "Market" } ] } }, { "name": "signer", "docs": [ "market.authority or market.keeper_authority. Safe for the keeper: the", "money can only go back to the recorded lender." ], "signer": true }, { "name": "market_advance", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116, 95, 97, 100, 118, 97, 110, 99, 101 ] }, { "kind": "account", "path": "market" } ] } }, { "name": "collateral_vault", "writable": true }, { "name": "lender", "writable": true }, { "name": "token_program", "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" } ], "args": [ { "name": "amount", "type": "u64" } ] }, { "name": "request_redemption", "docs": [ "Queue a paired redemption the vault cannot pay now. The L and S move", "into escrow token accounts owned by the request PDA; the keeper pays", "the request (in parts if need be) with `settle_redemption`, and the", "owner can `cancel_redemption` the unpaid rest at any time. Same active,", "Stress, price-freshness and $10-minimum checks as `redeem_paired`.", "Like `redeem_paired`, the amounts are maxima: only the largest", "value-balanced pair inside them goes into escrow (audit MR-2), and the", "rest stays with the owner. Settles burn the escrow pro rata, so the", "request stays balanced. Remaining accounts as for `redeem_paired`." ], "discriminator": [ 14, 62, 182, 237, 59, 79, 149, 22 ], "accounts": [ { "name": "market", "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116 ] }, { "kind": "account", "path": "market.asset_symbol", "account": "Market" } ] } }, { "name": "owner", "writable": true, "signer": true }, { "name": "request", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 114, 101, 100, 101, 109, 112, 116, 105, 111, 110 ] }, { "kind": "account", "path": "market" }, { "kind": "account", "path": "owner" } ] } }, { "name": "escrow_l", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 114, 101, 100, 101, 109, 112, 116, 105, 111, 110, 95, 101, 115, 99, 114, 111, 119 ] }, { "kind": "account", "path": "request" }, { "kind": "account", "path": "long_mint" } ] } }, { "name": "escrow_s", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 114, 101, 100, 101, 109, 112, 116, 105, 111, 110, 95, 101, 115, 99, 114, 111, 119 ] }, { "kind": "account", "path": "request" }, { "kind": "account", "path": "short_mint" } ] } }, { "name": "owner_long_account", "writable": true }, { "name": "owner_short_account", "writable": true }, { "name": "long_mint" }, { "name": "short_mint" }, { "name": "oracle" }, { "name": "token_program", "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" }, { "name": "system_program", "address": "11111111111111111111111111111111" } ], "args": [ { "name": "params", "type": { "defined": { "name": "RedemptionAmounts" } } } ] }, { "name": "set_buffer_target", "docs": [ "Keeper posts the DYNAMIC overcollateralization buffer (bps over parity) for this", "market: the per-market solvency target.", "Sized off σ-regime + live inventory (keeper vol_model::dynamic_buffer). Clamped on-chain", "to [MIN_BUFFER_BPS, MAX_BUFFER_BPS] so a bad write can't drop the target below the", "solvency floor or balloon it absurdly. Called only when the target moves meaningfully", "(the buffer drifts slowly), so it's off the hot TWAP path." ], "discriminator": [ 223, 244, 64, 159, 67, 221, 54, 29 ], "accounts": [ { "name": "market", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116 ] }, { "kind": "account", "path": "market.asset_symbol", "account": "Market" } ] } }, { "name": "keeper", "writable": true, "signer": true } ], "args": [ { "name": "buffer_target_bps", "type": "u16" } ] }, { "name": "set_s_gamma_index", "docs": [ "Keeper posts the short-leg volatility-decay scalar γ (1e9 = 1.0). It may", "only ever RATCHET DOWN — raising it would retroactively restore short", "claims the protocol already banked as surplus, so an increase is", "rejected. A genuine reset to 1.0 (a deliberate re-anchor settlement) is", "an authority action and intentionally NOT reachable from this keeper path.", "", "Every abnormal write is REJECTED and logged rather than quietly reshaped.", "The old code clamped its argument into range, so a single hot-key tx", "asking for zero silently became a write to the floor — a −50% mark on", "every short, indistinguishable in the logs from an ordinary post. The", "bounds are now:", "", "- range: the argument must already be within `[GAMMA_FLOOR, GAMMA_ONE]`,", "- ratchet: it may not exceed the current γ,", "- per-tx: at most `GAMMA_MAX_STEP_1E9` of decay in one write,", "- per-day: at most `GAMMA_MAX_DAY_DECAY_1E9` in any 24h bucket,", "- epoch: `expected_epoch` must match, so a post computed before a", "re-anchor cannot land after it and re-charge the folded epoch.", "", "Caps bound a fault's blast radius; they cannot catch a slow bleed of", "individually-valid posts (which is exactly how OIL burned). Telemetry is", "load-bearing for that class — `gamma_last_write_ts` exists so an auditor", "can alarm on writer silence too.", "", "Arguments are wrapped in ONE struct deliberately: the v1.45 build", "toolchain miscompiles per-argument borsh offsets on multi-arg", "instructions (it read a fee from inside a pubkey), and a single struct", "is the shape that survives it." ], "discriminator": [ 128, 218, 78, 111, 14, 253, 37, 241 ], "accounts": [ { "name": "market", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116 ] }, { "kind": "account", "path": "market.asset_symbol", "account": "Market" } ] } }, { "name": "keeper", "writable": true, "signer": true } ], "args": [ { "name": "params", "type": { "defined": { "name": "SetGammaParams" } } } ] }, { "name": "settle_redemption", "docs": [ "Pay the largest part of a request the vault's cash covers now (keeper", "only), up to `max_l_amount` of L with the matching pro-rata S. Prices,", "haircuts and charges fee + dev tax exactly like `redeem_paired`", "(`redemption::quote_at_navs`), burns that part from escrow and pays the", "owner. Unlike the instant path it may spend the treasury advance's cash", "(that is what the advance is for), but never more than the vault holds.", "When the request is fully paid and `owner` is passed, the escrows and", "the request close and their rent goes back to the owner; without", "`owner` an empty request waits for the owner's `cancel_redemption`." ], "discriminator": [ 21, 217, 64, 236, 36, 148, 2, 161 ], "accounts": [ { "name": "market", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116 ] }, { "kind": "account", "path": "market.asset_symbol", "account": "Market" } ] }, "relations": [ "request" ] }, { "name": "keeper", "docs": [ "The keeper. Same signer as `recall_collateral_from_yield`, so a recall", "and the settle it pays for share one transaction." ], "signer": true }, { "name": "request", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 114, 101, 100, 101, 109, 112, 116, 105, 111, 110 ] }, { "kind": "account", "path": "market" }, { "kind": "account", "path": "request.owner", "account": "RedemptionRequest" } ] } }, { "name": "escrow_l", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 114, 101, 100, 101, 109, 112, 116, 105, 111, 110, 95, 101, 115, 99, 114, 111, 119 ] }, { "kind": "account", "path": "request" }, { "kind": "account", "path": "market.long_mint", "account": "Market" } ] } }, { "name": "escrow_s", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 114, 101, 100, 101, 109, 112, 116, 105, 111, 110, 95, 101, 115, 99, 114, 111, 119 ] }, { "kind": "account", "path": "request" }, { "kind": "account", "path": "market.short_mint", "account": "Market" } ] } }, { "name": "long_mint", "writable": true }, { "name": "short_mint", "writable": true }, { "name": "collateral_vault", "writable": true }, { "name": "owner_collateral", "docs": [ "Where the owner is paid: any cUSDC account the request owner owns." ], "writable": true }, { "name": "dev_token_account", "writable": true }, { "name": "oracle" }, { "name": "token_program", "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" }, { "name": "owner", "docs": [ "The request owner, receiving the rent when the last part closes the", "request. Optional so the settle still fits beside a large venue recall;", "must equal `request.owner` when present." ], "writable": true, "optional": true } ], "args": [ { "name": "params", "type": { "defined": { "name": "SettleRedemptionParams" } } } ] }, { "name": "update_collateral_vault", "docs": [ "Update collateral vault configuration (admin only)" ], "discriminator": [ 31, 184, 228, 88, 56, 253, 32, 206 ], "accounts": [ { "name": "market", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116 ] }, { "kind": "account", "path": "market.asset_symbol", "account": "Market" } ] } }, { "name": "authority", "signer": true, "relations": [ "market" ] } ], "args": [ { "name": "collateral_mint", "type": "pubkey" }, { "name": "is_active", "type": { "option": "bool" } }, { "name": "weight_bps", "type": { "option": "u16" } } ] }, { "name": "update_fee_recipient", "docs": [ "Update the fee recipient for a market (admin only).", "Set to the CLP vault PDA to route protocol fees to the LP vault." ], "discriminator": [ 249, 0, 198, 35, 183, 123, 57, 188 ], "accounts": [ { "name": "market", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116 ] }, { "kind": "account", "path": "market.asset_symbol", "account": "Market" } ] } }, { "name": "authority", "signer": true, "relations": [ "market" ] } ], "args": [ { "name": "new_recipient", "type": "pubkey" } ] }, { "name": "update_keeper_authority", "docs": [ "Update the keeper authority for an existing market (admin only)." ], "discriminator": [ 21, 157, 181, 31, 82, 153, 235, 112 ], "accounts": [ { "name": "market", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116 ] }, { "kind": "account", "path": "market.asset_symbol", "account": "Market" } ] } }, { "name": "authority", "signer": true, "relations": [ "market" ] } ], "args": [ { "name": "new_keeper_authority", "type": "pubkey" } ] }, { "name": "update_market", "docs": [ "Update market parameters (admin only)" ], "discriminator": [ 153, 39, 2, 197, 179, 50, 199, 217 ], "accounts": [ { "name": "market", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116 ] }, { "kind": "account", "path": "market.asset_symbol", "account": "Market" } ] } }, { "name": "authority", "signer": true, "relations": [ "market" ] } ], "args": [ { "name": "mint_fee_bps", "type": { "option": "u16" } }, { "name": "redeem_fee_bps", "type": { "option": "u16" } }, { "name": "is_active", "type": { "option": "bool" } }, { "name": "dev_tax_pct", "type": { "option": "u8" } } ] }, { "name": "update_market_oracle", "docs": [ "Update the oracle account/type for an existing market (admin only)." ], "discriminator": [ 195, 200, 114, 92, 227, 5, 15, 119 ], "accounts": [ { "name": "market", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116 ] }, { "kind": "account", "path": "market.asset_symbol", "account": "Market" } ] } }, { "name": "authority", "signer": true, "relations": [ "market" ] }, { "name": "oracle" } ], "args": [ { "name": "oracle_type", "type": { "defined": { "name": "OracleType" } } } ] }, { "name": "update_risk_state", "docs": [ "Update risk state and TWAP from oracle (keeper only)", "This should be called regularly by keepers after updating oracle observations" ], "discriminator": [ 71, 227, 24, 202, 12, 22, 17, 96 ], "accounts": [ { "name": "market", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116 ] }, { "kind": "account", "path": "market.asset_symbol", "account": "Market" } ] } }, { "name": "keeper", "writable": true, "signer": true } ], "args": [ { "name": "new_risk_state", "type": { "defined": { "name": "RiskState" } } }, { "name": "user_twap_price", "type": "u64" }, { "name": "oracle_confidence", "type": "u64" } ] }, { "name": "update_risk_state_v2", "docs": [ "Timestamped keeper price. Revalidated at execution so a transaction built", "before a split cannot land afterward with a pre-split raw print." ], "discriminator": [ 222, 108, 59, 2, 231, 242, 224, 55 ], "accounts": [ { "name": "market", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116 ] }, { "kind": "account", "path": "market.asset_symbol", "account": "Market" } ] } }, { "name": "keeper", "writable": true, "signer": true } ], "args": [ { "name": "new_risk_state", "type": { "defined": { "name": "RiskState" } } }, { "name": "user_twap_price", "type": "u64" }, { "name": "oracle_confidence", "type": "u64" }, { "name": "source_publish_time", "type": "i64" } ] }, { "name": "withdraw_excess_to_clp", "docs": [ "Withdraw EXCESS collateral from a market's `collateral_vault` to", "the per-market CLP vault. Inverse of `donate_to_vault` — used to", "rebalance idle equity from over-collateralized markets back to", "the CLP, where it can be redeployed as bin-book liquidity, paid", "out via `admin_withdraw`, etc.", "", "Admin-gated (signer == market.authority).", "", "SAFETY: enforces a minimum-collateralization floor at withdrawal", "time. The post-withdrawal `total_collateral` must remain at or", "above `liability_at_NAV × market.target_ratio_bps() / 10_000`, so the", "vault stays at or above its own solvency target and the 100% line.", "", "If the live ratio is uncomputable (fresh market, zero supply), no", "withdrawal is allowed — there's no liability denominator and no", "need to drain anyway." ], "discriminator": [ 208, 14, 44, 170, 239, 210, 182, 152 ], "accounts": [ { "name": "market", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116 ] }, { "kind": "account", "path": "market.asset_symbol", "account": "Market" } ] } }, { "name": "authority", "signer": true, "relations": [ "market" ] }, { "name": "collateral_vault", "docs": [ "Market's collateral vault — source of the drain. Owned by the", "Market PDA which signs the SPL transfer via PDA seeds." ], "writable": true }, { "name": "clp_vault", "docs": [ "CLP vault — destination ATA. Must be the canonical CLP vault for", "this market (ATA owned by the CLP PDA derived from the market).", "We don't deserialize the CLP account here — just enforce that", "the destination's owner is the expected CLP PDA via constraint." ], "writable": true }, { "name": "clp_pda", "docs": [ "CLP PDA — used as the seed/owner anchor for `clp_vault`. We don't", "dereference it (could be uninitialized as far as this ix cares),", "but we validate its derivation matches the canonical CLP PDA for", "this market via the seeds constraint." ], "pda": { "seeds": [ { "kind": "const", "value": [ 99, 108, 112 ] }, { "kind": "account", "path": "market" } ], "program": { "kind": "account", "path": "clp_program_id" } } }, { "name": "clp_program_id", "docs": [ "scope `clp_pda`'s seed derivation." ] }, { "name": "token_program", "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" }, { "name": "collateral_authority", "optional": true } ], "args": [ { "name": "amount", "type": "u64" } ] }, { "name": "write_off_advance", "docs": [ "Absorb a venue loss into the treasury's advance first (authority only).", "The treasury is first-loss capital, so a loss is charged to the", "outstanding advance before any holder: `deployed_to_yield` (the lost", "principal) and `outstanding` (the treasury's claim) both drop by", "`amount`, `total_collateral` is untouched and no cash moves, so slack is", "unchanged. A loss beyond the advance goes through `mark_yield_impairment`,", "which refuses while anything is still outstanding." ], "discriminator": [ 178, 230, 117, 10, 235, 4, 61, 71 ], "accounts": [ { "name": "market", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116 ] }, { "kind": "account", "path": "market.asset_symbol", "account": "Market" } ] } }, { "name": "authority", "signer": true, "relations": [ "market" ] }, { "name": "market_advance", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ 109, 97, 114, 107, 101, 116, 95, 97, 100, 118, 97, 110, 99, 101 ] }, { "kind": "account", "path": "market" } ] } } ], "args": [ { "name": "amount", "type": "u64" } ] } ], "accounts": [ { "name": "Market", "discriminator": [ 219, 190, 213, 55, 0, 227, 198, 154 ] }, { "name": "MarketAdvance", "discriminator": [ 0, 31, 66, 40, 250, 93, 245, 228 ] }, { "name": "RedemptionRequest", "discriminator": [ 117, 157, 214, 214, 64, 160, 31, 58 ] } ], "events": [ { "name": "AdvanceReceived", "discriminator": [ 12, 235, 11, 44, 176, 44, 202, 187 ] }, { "name": "AdvanceRepaid", "discriminator": [ 185, 191, 136, 90, 224, 95, 1, 197 ] }, { "name": "AdvanceWrittenOff", "discriminator": [ 31, 187, 14, 87, 255, 94, 150, 227 ] }, { "name": "CollateralFunded", "discriminator": [ 176, 29, 180, 247, 39, 194, 77, 114 ] }, { "name": "CorporateActionApplied", "discriminator": [ 181, 230, 160, 46, 185, 15, 69, 140 ] }, { "name": "GammaReanchored", "discriminator": [ 60, 72, 238, 158, 65, 167, 161, 57 ] }, { "name": "MarketAdvanceConfigured", "discriminator": [ 138, 69, 68, 118, 122, 47, 83, 112 ] }, { "name": "PairedActionExecuted", "discriminator": [ 7, 147, 225, 204, 240, 52, 131, 212 ] }, { "name": "RedemptionCancelled", "discriminator": [ 22, 106, 118, 26, 83, 110, 71, 174 ] }, { "name": "RedemptionRequested", "discriminator": [ 245, 155, 98, 131, 210, 25, 137, 146 ] }, { "name": "RedemptionSettled", "discriminator": [ 75, 9, 197, 96, 249, 61, 27, 245 ] } ], "errors": [ { "code": 6000, "name": "MarketNotActive", "msg": "Market is not active" }, { "code": 6001, "name": "InvalidAmount", "msg": "Invalid amount" }, { "code": 6002, "name": "InsufficientCollateral", "msg": "Insufficient collateral in vault" }, { "code": 6003, "name": "InvalidOracle", "msg": "Invalid oracle account" }, { "code": 6004, "name": "UnsupportedOracleType", "msg": "Unsupported oracle type" }, { "code": 6005, "name": "OraclePriceUnavailable", "msg": "Oracle price unavailable" }, { "code": 6006, "name": "MathOverflow", "msg": "Math overflow" }, { "code": 6007, "name": "SymbolTooLong", "msg": "Asset symbol too long" }, { "code": 6008, "name": "FeeTooHigh", "msg": "Fee too high (max 10%)" }, { "code": 6009, "name": "MintNotAllowedInStress", "msg": "Minting not allowed during Stress mode" }, { "code": 6010, "name": "RedeemNotAllowedInStress", "msg": "Redeeming not allowed during Stress mode" }, { "code": 6011, "name": "ExceedsStressMintCap", "msg": "Amount exceeds stress mode mint cap" }, { "code": 6012, "name": "TwapNotAvailable", "msg": "TWAP price not available - keeper has not updated" }, { "code": 6013, "name": "AlreadyEnabled", "msg": "Multi-collateral mode already enabled" }, { "code": 6014, "name": "MultiCollateralNotEnabled", "msg": "Multi-collateral mode not enabled" }, { "code": 6015, "name": "MaxCollateralTypesExceeded", "msg": "Maximum number of collateral types exceeded" }, { "code": 6016, "name": "InvalidWeight", "msg": "Invalid weight - must be between 1 and 10000" }, { "code": 6017, "name": "CollateralAlreadyExists", "msg": "Collateral type already exists" }, { "code": 6018, "name": "CollateralNotFound", "msg": "Collateral type not found" }, { "code": 6019, "name": "BelowMinimum", "msg": "Amount below minimum ($10)" }, { "code": 6020, "name": "UnauthorizedKeeper", "msg": "Unauthorized keeper" }, { "code": 6021, "name": "Unauthorized", "msg": "Unauthorized: not the market authority" }, { "code": 6022, "name": "InsufficientLiquidCollateral", "msg": "Insufficient liquid collateral; recall yield deployment first" }, { "code": 6023, "name": "ExceedsYieldCeiling", "msg": "Deployment would exceed yield ceiling" }, { "code": 6024, "name": "YieldManagementDisabled", "msg": "Collateral yield management is disabled for this market" }, { "code": 6025, "name": "RecallExceedsDeployed", "msg": "Recall amount exceeds deployed_to_yield balance" }, { "code": 6026, "name": "SingleSideMintStressFloor", "msg": "Single-side mint would leave the vault under-collateralized under an adverse NAV shock" }, { "code": 6027, "name": "GammaMustRatchetDown", "msg": "s_gamma_index may only ratchet down; raising the short decay scalar is rejected" }, { "code": 6028, "name": "GammaOutOfRange", "msg": "s_gamma_index is outside [GAMMA_FLOOR, GAMMA_ONE]; out-of-range writes are rejected, not clamped" }, { "code": 6029, "name": "GammaStepTooLarge", "msg": "unused (γ per-transaction rate cap removed)" }, { "code": 6030, "name": "GammaDailyCapExceeded", "msg": "unused (γ per-day rate cap removed)" }, { "code": 6031, "name": "GammaEpochMismatch", "msg": "γ epoch mismatch: this post was computed against a different epoch (a re-anchor landed in between)" }, { "code": 6032, "name": "InvalidMarketAccount", "msg": "Account is not a Market owned by this program (bad owner, discriminator, or length)" }, { "code": 6033, "name": "ReanchorNoDecay", "msg": "Nothing to re-anchor: γ is already 1.0 (or unset)" }, { "code": 6034, "name": "ReanchorTooSoon", "msg": "Re-anchor is inside the minimum interval since the last one" }, { "code": 6035, "name": "ReanchorPrecisionFloor", "msg": "Re-anchor would leave the short anchor without enough precision to price against" }, { "code": 6036, "name": "ReanchorNotValueConserving", "msg": "Re-anchor failed its value-conservation invariant and was rejected" }, { "code": 6037, "name": "ReanchorBadState", "msg": "Market is in a degenerate state (zero anchor) and cannot be re-anchored" }, { "code": 6038, "name": "MarketNotEmpty", "msg": "Cannot close a market that still has outstanding supply or collateral" }, { "code": 6039, "name": "CorporateActionBadRatio", "msg": "Corporate-action ratio has a zero term" }, { "code": 6040, "name": "CorporateActionNoOp", "msg": "Corporate-action ratio is 1:1; nothing to apply" }, { "code": 6041, "name": "CorporateActionRatioOutOfRange", "msg": "Corporate-action ratio is implausibly large (fat-finger guard)" }, { "code": 6042, "name": "CorporateActionPrecisionExhausted", "msg": "Cumulative corporate-action ratio would exceed its precision budget (cash dividends are deliberately out of scope)" }, { "code": 6043, "name": "PriceAdjustOverflow", "msg": "Oracle price could not be mapped into genesis share units (corporate-action adjustment overflowed)" }, { "code": 6044, "name": "CorporateActionEffectiveTooFarAhead", "msg": "Corporate-action effective_ts is implausibly far ahead; check the unit (seconds, not milliseconds)" }, { "code": 6045, "name": "CorporateActionPendingExists", "msg": "A future corporate action is already pending; wait until it takes effect" }, { "code": 6046, "name": "UnauthorizedInitializer", "msg": "Market initialization requires the program upgrade authority" }, { "code": 6047, "name": "InvalidProgramData", "msg": "Market initialization requires this program's ProgramData account" }, { "code": 6048, "name": "UnifiedVaultRetired", "msg": "The unified vault is retired; migrate_to_unified_vault is disabled" }, { "code": 6049, "name": "NotOnUnifiedVault", "msg": "Market collateral is not held in the unified vault" }, { "code": 6050, "name": "MixedVaultRebalance", "msg": "Cannot rebalance between the unified vault and a per-market vault; exit the unified vault first" }, { "code": 6051, "name": "UnauthorizedSweep", "msg": "Sweeping the unified vault requires the program upgrade authority" }, { "code": 6052, "name": "SweepExceedsSurplus", "msg": "Sweep would take collateral still attributed to a market on the unified vault" }, { "code": 6053, "name": "NothingToSettle", "msg": "No part of this redemption request fits in the vault's cash now" }, { "code": 6054, "name": "AdvanceCapExceeded", "msg": "Advance would exceed this market's advance cap" }, { "code": 6055, "name": "AdvanceRepayExceedsOutstanding", "msg": "Repayment exceeds the outstanding advance" }, { "code": 6056, "name": "AdvanceWouldTakeOwnLiquidity", "msg": "Repayment would take the market's own liquid collateral" }, { "code": 6057, "name": "AdvanceLenderLocked", "msg": "The advance lender can change only while nothing is outstanding" }, { "code": 6058, "name": "AdvanceOutstanding", "msg": "A treasury advance is outstanding: write it off or repay it first" }, { "code": 6059, "name": "InvalidAdvanceLender", "msg": "The advance lender must be the CLP treasury vault (GlobalClp's cUSDC account)" }, { "code": 6060, "name": "ExposureCapExceeded", "msg": "This would push the market's net exposure past its cap" }, { "code": 6061, "name": "ExposureAccountMismatch", "msg": "An exposure account is not the market's CLP, pool synth vault or CLP token account" }, { "code": 6062, "name": "ExposureAccountsMissing", "msg": "A lopsided redemption must pass the exposure accounts: CLP, pool vaults, CLP token accounts" } ], "types": [ { "name": "AdvanceReceived", "type": { "kind": "struct", "fields": [ { "name": "market", "type": "pubkey" }, { "name": "amount", "type": "u64" }, { "name": "outstanding", "type": "u64" }, { "name": "cap", "type": "u64" }, { "name": "ts", "type": "i64" } ] } }, { "name": "AdvanceRepaid", "type": { "kind": "struct", "fields": [ { "name": "market", "type": "pubkey" }, { "name": "amount", "type": "u64" }, { "name": "outstanding", "type": "u64" }, { "name": "ts", "type": "i64" } ] } }, { "name": "AdvanceWrittenOff", "type": { "kind": "struct", "fields": [ { "name": "market", "type": "pubkey" }, { "name": "amount", "type": "u64" }, { "name": "outstanding", "type": "u64" }, { "name": "deployed_to_yield", "type": "u64" }, { "name": "ts", "type": "i64" } ] } }, { "name": "CollateralFunded", "docs": [ "Emitted when the authority tops up a market's collateral." ], "type": { "kind": "struct", "fields": [ { "name": "market", "type": "pubkey" }, { "name": "amount", "type": "u64" }, { "name": "total_collateral", "type": "u64" }, { "name": "ts", "type": "i64" } ] } }, { "name": "CollateralType", "docs": [ "Collateral type identifier" ], "type": { "kind": "enum", "variants": [ { "name": "USDC" }, { "name": "USDT" }, { "name": "PYUSD" }, { "name": "USDe" }, { "name": "Other" } ] } }, { "name": "CollateralVault", "docs": [ "Individual collateral vault for a specific stablecoin", "Each stablecoin has its own vault for blast-radius containment" ], "type": { "kind": "struct", "fields": [ { "name": "mint", "docs": [ "Mint address of this collateral token" ], "type": "pubkey" }, { "name": "vault", "docs": [ "Vault token account address" ], "type": "pubkey" }, { "name": "collateral_type", "docs": [ "Type of collateral (for provenance)" ], "type": { "defined": { "name": "CollateralType" } } }, { "name": "total_deposited", "docs": [ "Total amount deposited in this vault" ], "type": "u64" }, { "name": "is_active", "docs": [ "Whether this vault is active for deposits" ], "type": "bool" }, { "name": "weight_bps", "docs": [ "Weight for collateral (100 = 1:1, 95 = 0.95:1 for riskier stables)" ], "type": "u16" } ] } }, { "name": "ConfigureAdvanceParams", "type": { "kind": "struct", "fields": [ { "name": "max_advance_bps", "type": "u16" } ] } }, { "name": "ConfigureRiskFeesParams", "docs": [ "`configure_risk_fees` arguments, in their wire order. One struct, not 5 separate", "arguments: the v1.45 SBPF-v2 toolchain garbles narrow arguments passed this", "late (configure_swap dropped max_confidence_bps and collateral_floor_bps).", "Same bytes on the wire, so existing callers are unaffected." ], "type": { "kind": "struct", "fields": [ { "name": "proxy_fee_multiplier", "type": { "option": "u16" } }, { "name": "stress_fee_multiplier", "type": { "option": "u16" } }, { "name": "stress_mint_cap", "type": { "option": "u64" } }, { "name": "allow_mint_in_stress", "type": { "option": "bool" } }, { "name": "allow_redeem_in_stress", "type": { "option": "bool" } } ] } }, { "name": "CorporateActionApplied", "docs": [ "Emitted on every corporate action. The on-chain record of a units change —", "the thing an auditor needs to reconcile a synth's price series against the", "underlying's unadjusted one." ], "type": { "kind": "struct", "fields": [ { "name": "market", "type": "pubkey" }, { "name": "ratio_num", "type": "u64" }, { "name": "ratio_den", "type": "u64" }, { "name": "old_price_adjust_num", "type": "u64" }, { "name": "old_price_adjust_den", "type": "u64" }, { "name": "new_price_adjust_num", "type": "u64" }, { "name": "new_price_adjust_den", "type": "u64" }, { "name": "effective_ts", "docs": [ "When the new pair becomes live. Equals `ts` for an immediate", "application, the ex-date open for an armed one." ], "type": "i64" }, { "name": "armed", "docs": [ "True if this was armed ahead of its ex-date rather than applied now." ], "type": "bool" }, { "name": "price_at_apply", "docs": [ "The quoted price at the moment of application, which this instruction", "does not modify. Present so the event alone shows the action was", "price-neutral." ], "type": "u64" }, { "name": "ts", "type": "i64" } ] } }, { "name": "CorporateActionParams", "docs": [ "Arguments for `apply_corporate_action`, in ONE struct — same reason as", "`SetGammaParams`: the v1.45 build toolchain miscompiles per-argument borsh", "offsets on multi-arg instructions, and a single struct is the shape that", "survives it. Wire format is identical." ], "type": { "kind": "struct", "fields": [ { "name": "ratio_num", "docs": [ "`new_shares` side of the action ratio. A 2-for-1 split is `num = 2`." ], "type": "u64" }, { "name": "ratio_den", "docs": [ "`old_shares` side. A 1-for-10 reverse split is `num = 1, den = 10`." ], "type": "u64" }, { "name": "effective_ts", "docs": [ "Unix ts from which the ratio applies — set it to the ex-date OPEN, the", "first instant a venue quotes the post-action price.", "", "`0`, or any value at or before now, applies immediately: the recovery", "path when an action was missed and the market has already halted.", "A future value ARMS it, leaving pre-ex prints read exactly as they are", "today. Arming without this gate is worse than doing nothing — the", "adjustment would multiply a still-unsplit price and the 25% move guard", "would reject every push from the moment of arming until the ex-date." ], "type": "i64" } ] } }, { "name": "GammaReanchored", "docs": [ "Emitted on every re-anchor. Deployment, not first invocation, is the", "disclosure trigger — this is the on-chain record of an epoch boundary." ], "type": { "kind": "struct", "fields": [ { "name": "market", "type": "pubkey" }, { "name": "epoch", "type": "u32" }, { "name": "folded_gamma", "type": "u64" }, { "name": "old_initial_s_price", "type": "u64" }, { "name": "new_initial_s_price", "type": "u64" }, { "name": "genesis_s_price", "type": "u64" }, { "name": "reanchor_count", "type": "u32" }, { "name": "ts", "type": "i64" } ] } }, { "name": "InitMarketParams", "docs": [ "Args for `initialize_market`, passed as a single struct so the borsh", "deserialize is ONE unit. The v1.45 SBF toolchain miscompiles the per-arg", "field-offset assignment when these are 7 separate scalar args (it reads", "`mint_fee_bps` from inside the keeper pubkey). The wire format is byte-for-byte", "identical to the old 7-arg form, so off-chain callers are unaffected." ], "type": { "kind": "struct", "fields": [ { "name": "asset_symbol", "type": "string" }, { "name": "oracle_type", "type": { "defined": { "name": "OracleType" } } }, { "name": "initial_l_price", "type": "u64" }, { "name": "initial_s_price", "type": "u64" }, { "name": "mint_fee_bps", "type": "u16" }, { "name": "redeem_fee_bps", "type": "u16" }, { "name": "keeper_authority", "type": "pubkey" } ] } }, { "name": "Market", "type": { "kind": "struct", "fields": [ { "name": "authority", "type": "pubkey" }, { "name": "fee_recipient", "type": "pubkey" }, { "name": "asset_symbol", "type": "string" }, { "name": "oracle_address", "type": "pubkey" }, { "name": "oracle_type", "type": { "defined": { "name": "OracleType" } } }, { "name": "long_mint", "type": "pubkey" }, { "name": "short_mint", "type": "pubkey" }, { "name": "collateral_mint", "docs": [ "Primary collateral mint (legacy single-collateral mode)" ], "type": "pubkey" }, { "name": "collateral_vault", "docs": [ "Primary collateral vault (legacy)" ], "type": "pubkey" }, { "name": "multi_collateral_enabled", "docs": [ "Whether multi-collateral mode is enabled" ], "type": "bool" }, { "name": "collateral_vault_count", "docs": [ "Number of active collateral vaults" ], "type": "u8" }, { "name": "collateral_vaults", "docs": [ "Collateral vaults for multi-stable support" ], "type": { "vec": { "defined": { "name": "CollateralVault" } } } }, { "name": "initial_l_price", "docs": [ "Initial Long token price (used for Short NAV calculation)" ], "type": "u64" }, { "name": "initial_s_price", "docs": [ "Initial Short token price" ], "type": "u64" }, { "name": "mint_fee_bps", "docs": [ "Mint fee in basis points (e.g., 10 = 0.1%)" ], "type": "u16" }, { "name": "redeem_fee_bps", "docs": [ "Redeem fee in basis points" ], "type": "u16" }, { "name": "total_l_supply", "docs": [ "Total supply of Long tokens. Paired mint/redeem keeps this equal to", "`total_s_supply`; single-side keeper mint/redeem (`keeper_mint_single`,", "see lib.rs) intentionally moves only one side, so the two supplies can", "diverge, giving a first-order (directional) delta the γ decay does NOT charge." ], "type": "u64" }, { "name": "total_s_supply", "docs": [ "Total supply of Short tokens. Equal to `total_l_supply` under paired", "mint/redeem, but single-side keeper mint/redeem deliberately lets it", "diverge (see `total_l_supply` above)." ], "type": "u64" }, { "name": "total_collateral", "docs": [ "Total collateral locked (sum across all vaults)" ], "type": "u64" }, { "name": "is_active", "type": "bool" }, { "name": "bump", "type": "u8" }, { "name": "risk_state", "docs": [ "Current risk state (updated by keepers from oracle)" ], "type": { "defined": { "name": "RiskState" } } }, { "name": "risk_state_updated_at", "docs": [ "Last time risk state was updated" ], "type": "i64" }, { "name": "risk_fee_config", "docs": [ "Risk-based fee configuration" ], "type": { "defined": { "name": "RiskFeeConfig" } } }, { "name": "user_twap_price", "docs": [ "TWAP price for user quoting (updated by keepers)" ], "type": "u64" }, { "name": "twap_updated_at", "docs": [ "Last TWAP update time" ], "type": "i64" }, { "name": "worst_case_config", "docs": [ "Configuration for worst-case quoting" ], "type": { "defined": { "name": "WorstCaseQuotingConfig" } } }, { "name": "oracle_confidence", "docs": [ "Oracle confidence interval (updated by keepers)" ], "type": "u64" }, { "name": "keeper_authority", "docs": [ "Whitelisted keeper authority that is allowed to update risk state" ], "type": "pubkey" }, { "name": "dev_tax_pct", "docs": [ "Dev tax percentage (updated by keeper based on CLP TVL tiers)" ], "type": "u8" }, { "name": "yield_ceiling_bps", "docs": [ "Maximum fraction of total_collateral deployable to yield protocols (basis points).", "Default: 6000 (60%). Remaining 40% stays liquid to cover redemptions." ], "type": "u16" }, { "name": "deployed_to_yield", "docs": [ "Amount of collateral currently deployed to external lending protocols.", "Invariant: deployed_to_yield <= total_collateral * yield_ceiling_bps / 10_000" ], "type": "u64" }, { "name": "total_yield_harvested", "docs": [ "Cumulative yield harvested to CLP vault (never decrements, informational)." ], "type": "u64" }, { "name": "yield_enabled", "docs": [ "Whether collateral yield deployment is enabled for this market." ], "type": "bool" }, { "name": "buffer_target_bps", "docs": [ "Keeper-posted overcollateralization buffer (bps OVER parity), the dynamic", "solvency target. Target ratio = 10_000 + buffer_target_bps, clamped to", "[MIN_BUFFER_BPS, MAX_BUFFER_BPS]. 0 (legacy/unset) is treated as the default", "200 (102%) by `target_ratio_bps()`, so old accounts behave as before until the", "keeper posts a value. Sized from σ-regime + live inventory (vol_model::dynamic_buffer)." ], "type": "u16" }, { "name": "s_gamma_index", "docs": [ "Keeper-posted decay scalar on the SHORT NAV, in 1e9 fixed point", "(1_000_000_000 = 1.0 = no decay). The effective short NAV is", "`(K / l_nav) · s_gamma_index / 1e9`. It only ever ratchets DOWN, by the", "realized variance the short pair accrues, so holding the short across a", "choppy path costs the decay, which banks as collateral surplus (the", "long leg is never touched). `0` (legacy/unset) is read as 1e9 by", "`short_gamma_index()`, so old accounts behave exactly as before until", "the keeper posts a value. NOT a perp funding rate; there is no periodic", "cash transfer; it is a structural mark on the short token's value, so the", "1:1 paired round-trip and buy-and-hold mechanics are unchanged at a fixed γ." ], "type": "u64" }, { "name": "gamma_day_start_ts", "docs": [ "Unix ts the current γ day-bucket opened. 0 = no bucket yet." ], "type": "i64" }, { "name": "gamma_day_decay_1e9", "docs": [ "γ index units (1e9) decayed inside the current day-bucket. TELEMETRY", "ONLY: tracked so an auditor can see the day's total, never enforced." ], "type": "u64" }, { "name": "gamma_last_write_ts", "docs": [ "Unix ts of the last accepted γ write. Lets an auditor alarm on writer", "SILENCE, the failure mode no cap can catch, because it looks like calm." ], "type": "i64" }, { "name": "gamma_epoch", "docs": [ "Bumped by a re-anchor. Carried in `SetGammaParams` as a CAS so a decay", "post computed against a pre-re-anchor γ can never land after the fold", "and re-charge the whole epoch." ], "type": "u32" }, { "name": "reanchor_count", "docs": [ "How many re-anchors this market has seen. 0 = never." ], "type": "u32" }, { "name": "genesis_s_price", "docs": [ "`initial_s_price` as of genesis, before any re-anchor folded γ into it.", "Backfilled lazily on the first re-anchor; 0 = never re-anchored, so the", "live `initial_s_price` IS the genesis value." ], "type": "u64" }, { "name": "last_reanchor_ts", "docs": [ "Unix ts of the last re-anchor. 0 = never." ], "type": "i64" }, { "name": "short_payoff_cap_c_1e9", "docs": [ "Reserved for the capped short payoff `S = γ·min(K/P, C·K/P₀)` (1e9", "fixed). The instruction ships in upgrade #2; the FIELD lands here so", "that upgrade is instructions-only and needs no second realloc.", "0 = unset = uncapped, i.e. exactly today's behavior." ], "type": "u64" }, { "name": "price_adjust_num", "type": "u64" }, { "name": "price_adjust_den", "docs": [ "Denominator of the cumulative corporate-action ratio. See", "`price_adjust_num`. 0 = unset = identity." ], "type": "u64" }, { "name": "price_adjust_pending_num", "docs": [ "A corporate action ARMED AHEAD of its ex-date: the cumulative pair that", "becomes live at `price_adjust_effective_ts`. Until then the current", "`price_adjust_num/den` keeps applying.", "", "This exists because arming a ratio early is otherwise actively harmful,", "not merely useless. The adjustment multiplies the NEXT raw print, and", "before the ex-date that print is still PRE-split, so an early 2:1 would", "double the stored price, the 25% move guard would reject every push, and", "the market would halt from the moment of arming until the split actually", "happened. Gating on a timestamp is what makes \"schedule it weeks ahead\"", "a true statement instead of a longer outage." ], "type": "u64" }, { "name": "price_adjust_pending_den", "docs": [ "Denominator of the pending pair. See `price_adjust_pending_num`." ], "type": "u64" }, { "name": "price_adjust_effective_ts", "docs": [ "Unix ts from which the pending pair applies. 0 = nothing pending.", "", "Set it to the ex-date OPEN, the first instant a venue quotes the", "post-action price. Misalignment is bounded and self-correcting for", "ratios above ~1.333: a print on the wrong side of the boundary is", "REJECTED by the 25% guard, not absorbed, so an early or late `ts` costs", "rejected pushes rather than a mispriced book. Below ~1.333 nothing", "rejects it and the alignment is the only control." ], "type": "i64" }, { "name": "price_adjust_last_effective_ts", "docs": [ "Most recent activated units boundary, retained after promotion and rescheduling." ], "type": "i64" } ] } }, { "name": "MarketAdvance", "docs": [ "The treasury's reversible liquidity advance to one market (r58 lever 3).", "", "PDA seeds: `[b\"market_advance\", market]`. The advance's cash sits in the", "market's collateral vault but is NOT `total_collateral`: CR and the haircut", "never count it, and every pre-existing outflow is gated on the market's own", "liquid share, so only `settle_redemption` and `repay_advance` spend it.", "Invariant: `vault + deployed_to_yield = total_collateral + outstanding + slack`." ], "type": { "kind": "struct", "fields": [ { "name": "market", "type": "pubkey" }, { "name": "lender", "docs": [ "The only token account an advance may come from and be repaid to", "(the CLP global vault). Changeable only while nothing is outstanding." ], "type": "pubkey" }, { "name": "max_advance_bps", "docs": [ "Cap: `outstanding ≤ max_advance_bps × total_collateral / 10_000`.", "0 = advances off. r58's 2,500 (0.25×) is a TEST value, not a proposal." ], "type": "u16" }, { "name": "outstanding", "type": "u64" }, { "name": "total_advanced", "type": "u64" }, { "name": "total_repaid", "type": "u64" }, { "name": "total_written_off", "docs": [ "Venue losses absorbed by the treasury through `write_off_advance`." ], "type": "u64" }, { "name": "last_advance_at", "type": "i64" }, { "name": "last_repay_at", "type": "i64" }, { "name": "bump", "type": "u8" } ] } }, { "name": "MarketAdvanceConfigured", "type": { "kind": "struct", "fields": [ { "name": "market", "type": "pubkey" }, { "name": "lender", "type": "pubkey" }, { "name": "max_advance_bps", "type": "u16" } ] } }, { "name": "OracleType", "type": { "kind": "enum", "variants": [ { "name": "Pyth" }, { "name": "Switchboard" }, { "name": "Continuum" } ] } }, { "name": "PairedActionExecuted", "type": { "kind": "struct", "fields": [ { "name": "user", "type": "pubkey" }, { "name": "market", "type": "pubkey" }, { "name": "collateral_mint", "type": "pubkey" }, { "name": "long_mint", "type": "pubkey" }, { "name": "short_mint", "type": "pubkey" }, { "name": "action", "docs": [ "0 = paired mint; 1 = paired redeem." ], "type": "u8" }, { "name": "is_keeper", "type": "bool" }, { "name": "collateral_amount", "docs": [ "Actual collateral paid by / returned to the user." ], "type": "u64" }, { "name": "gross_collateral_amount", "docs": [ "Mint input / redeem payout before the explicit fee." ], "type": "u64" }, { "name": "long_amount", "type": "u64" }, { "name": "short_amount", "type": "u64" }, { "name": "fee_amount", "type": "u64" }, { "name": "dev_tax", "type": "u64" }, { "name": "long_decimals", "type": "u8" }, { "name": "short_decimals", "type": "u8" } ] } }, { "name": "RedemptionAmounts", "docs": [ "`request_redemption` arguments, in ONE struct (the v1.45 toolchain", "miscompiles per-argument borsh offsets on multi-arg instructions)." ], "type": { "kind": "struct", "fields": [ { "name": "l_amount", "type": "u64" }, { "name": "s_amount", "type": "u64" } ] } }, { "name": "RedemptionCancelled", "type": { "kind": "struct", "fields": [ { "name": "request", "type": "pubkey" }, { "name": "owner", "type": "pubkey" }, { "name": "market", "type": "pubkey" }, { "name": "l_returned", "type": "u64" }, { "name": "s_returned", "type": "u64" }, { "name": "ts", "type": "i64" } ] } }, { "name": "RedemptionRequest", "docs": [ "A paired redemption waiting for the keeper to pay it (r58 lever 1 + 2).", "", "PDA seeds: `[b\"redemption\", market, owner]`, so one open request per", "(market, owner). The escrowed L and S sit in two token accounts owned by", "this PDA (`[b\"redemption_escrow\", request, mint]`); their balances always", "equal `l_remaining` / `s_remaining`. The tokens stay in supply until a", "settle burns them, so a waiting request changes no CR or haircut.", "", "Lives in its own account, never in `Market` (Anchor deserializes before", "realloc; see `market_space_tests`)." ], "type": { "kind": "struct", "fields": [ { "name": "owner", "type": "pubkey" }, { "name": "market", "type": "pubkey" }, { "name": "long_mint", "type": "pubkey" }, { "name": "short_mint", "type": "pubkey" }, { "name": "l_requested", "type": "u64" }, { "name": "s_requested", "type": "u64" }, { "name": "l_remaining", "type": "u64" }, { "name": "s_remaining", "type": "u64" }, { "name": "gross_paid", "docs": [ "Running totals over all fills (cUSDC atoms)." ], "type": "u64" }, { "name": "net_paid", "type": "u64" }, { "name": "fee_paid", "type": "u64" }, { "name": "dev_tax_paid", "type": "u64" }, { "name": "fills", "type": "u32" }, { "name": "created_at", "type": "i64" }, { "name": "last_fill_at", "type": "i64" }, { "name": "bump", "type": "u8" }, { "name": "escrow_l_bump", "type": "u8" }, { "name": "escrow_s_bump", "type": "u8" } ] } }, { "name": "RedemptionRequested", "type": { "kind": "struct", "fields": [ { "name": "request", "type": "pubkey" }, { "name": "owner", "type": "pubkey" }, { "name": "market", "type": "pubkey" }, { "name": "l_amount", "type": "u64" }, { "name": "s_amount", "type": "u64" }, { "name": "ts", "type": "i64" } ] } }, { "name": "RedemptionSettled", "type": { "kind": "struct", "fields": [ { "name": "request", "type": "pubkey" }, { "name": "owner", "type": "pubkey" }, { "name": "market", "type": "pubkey" }, { "name": "l_amount", "type": "u64" }, { "name": "s_amount", "type": "u64" }, { "name": "gross", "type": "u64" }, { "name": "net", "type": "u64" }, { "name": "fee", "type": "u64" }, { "name": "dev_tax", "type": "u64" }, { "name": "l_remaining", "type": "u64" }, { "name": "s_remaining", "type": "u64" }, { "name": "ts", "type": "i64" } ] } }, { "name": "RiskFeeConfig", "docs": [ "Configuration for risk-based fee adjustments" ], "type": { "kind": "struct", "fields": [ { "name": "proxy_fee_multiplier", "docs": [ "Fee multiplier for Proxy Mode (100 = 1x, 200 = 2x)" ], "type": "u16" }, { "name": "stress_fee_multiplier", "docs": [ "Fee multiplier for Stress mode (100 = 1x, 300 = 3x)", "Also the starting point for Recovery Dutch auction (decays to 1.0x over 1 hour)" ], "type": "u16" }, { "name": "stress_mint_cap", "docs": [ "Mint cap per transaction in Stress mode (0 = disabled)" ], "type": "u64" }, { "name": "allow_mint_in_stress", "docs": [ "Whether to allow new mints in Stress mode" ], "type": "bool" }, { "name": "allow_redeem_in_stress", "docs": [ "Whether to allow redeems in Stress mode" ], "type": "bool" } ] } }, { "name": "RiskState", "docs": [ "Risk state for graduated oracle gating (mirrors oracle program)" ], "type": { "kind": "enum", "variants": [ { "name": "Normal" }, { "name": "ProxyMode" }, { "name": "Stress" }, { "name": "Recovery" } ] } }, { "name": "SetGammaParams", "docs": [ "Arguments for `set_s_gamma_index`, in ONE struct.", "", "Not two loose arguments: the v1.45 build toolchain miscompiles per-argument", "borsh offsets on multi-arg instructions (it once read a fee out of the middle", "of a pubkey), and a single struct is the shape that survives it. The wire", "format is identical either way, so this costs nothing." ], "type": { "kind": "struct", "fields": [ { "name": "s_gamma_index", "docs": [ "The new γ index (1e9). Must already be in `[GAMMA_FLOOR, GAMMA_ONE]` —", "out-of-range is rejected, never clamped." ], "type": "u64" }, { "name": "expected_epoch", "docs": [ "The `gamma_epoch` this post was computed against. A compare-and-swap:", "the keeper snapshots γ at the start of a cycle and posts later, so", "without this a re-anchor landing in that window would let a stale post", "re-charge the entire folded epoch, and the ratchet would accept it." ], "type": "u32" } ] } }, { "name": "SettleRedemptionParams", "type": { "kind": "struct", "fields": [ { "name": "max_l_amount", "docs": [ "Most L to settle in this call (`u64::MAX` = all that fits). The", "program shrinks it to what the vault's cash covers." ], "type": "u64" } ] } }, { "name": "WorstCaseQuotingConfig", "docs": [ "Configuration for worst-case quoting", "Protects protocol from informed traders exploiting confidence interval edges" ], "type": { "kind": "struct", "fields": [ { "name": "enabled", "docs": [ "Whether worst-case quoting is enabled" ], "type": "bool" }, { "name": "normal_confidence_multiplier", "docs": [ "Confidence multiplier in Normal state (100 = 1x, 150 = 1.5x)" ], "type": "u16" }, { "name": "proxy_confidence_multiplier", "docs": [ "Confidence multiplier in Proxy state" ], "type": "u16" }, { "name": "stress_confidence_multiplier", "docs": [ "Confidence multiplier in Stress state (also the starting point for Recovery Dutch auction)" ], "type": "u16" } ] } } ] }