Bootstrap (or top up) the vault's PT inventory: pull amount USDC from from, mint
amount PT (+ amount YT) into the vault via the wrapper. This is pure coupon capacity
β it creates no receipt and no liability, so it strictly raises coupon_capacity. Typically
called once by the admin/protocol at launch (and optionally to widen capacity later).
Anyone may seed (it only donates PT to the vault); we still require from to authorize the
USDC pull.
fn seed(env: soroban_sdk::Env, from: soroban_sdk::Address, amount: i128) -> u64
fn admin(env: soroban_sdk::Env) -> soroban_sdk::Address
fn pause(env: soroban_sdk::Env)
Quote the payout a amount-USDC deposit would lock in right now: returns
(payout, coupon, rate_bps). Pure read β does not check capacity (the UI shows the quote;
deposit enforces capacity). Returns a zero coupon at/after maturity.
fn quote(env: soroban_sdk::Env, amount: i128) -> (i128, i128, u32)
The vault's health snapshot for the solvency dashboard.
fn stats(env: soroban_sdk::Env) -> VaultStats
Redeem a matured receipt: at/after maturity, redeem payout PT from the vault's inventory
1:1 and pay the owner payout USDC. Closes the receipt and clears its liability.
fn redeem(env: soroban_sdk::Env, receipt_id: u64) -> i128
Deposit amount USDC and lock the current fixed rate. Mints amount PT (+amount YT) into
the vault, computes the term coupon, and β only if the vault holds enough PT to back the
full payout β issues the user a receipt for payout = amount + coupon. Returns the
receipt id.
The capacity check is what makes the fixed rate solvent by construction: the amount PT
just minted covers the principal, and the coupon PT must already exist in inventory (from
seed/harvest). If it doesn't, we revert rather than promise an unbacked return.
fn deposit(env: soroban_sdk::Env, user: soroban_sdk::Address, amount: i128) -> u64
Claim the vault's accrued YT yield across up to max_positions of its tracked positions
(starting from a stored round-robin cursor) and reinvest it as fresh PT, growing coupon
capacity. Paginated so the per-call work is bounded no matter how many positions the vault
has accumulated β repeated calls sweep the whole list a chunk at a time (mainnet-readiness #6:
an un-paginated loop over an ever-growing list would eventually exceed the tx budget and
permanently revert). Permissionless (it only ever increases backing) and allowed while
paused (it's an upkeep/outflow-side op, never an inflow of new user money). max_positions
is clamped to a sane ceiling; pass e.g. 20β50. Returns (yield_claimed_usdc, pt_added).
fn harvest(env: soroban_sdk::Env, max_positions: u32) -> (i128, i128)
fn unpause(env: soroban_sdk::Env)
Human-readable semver of the source build (informational; for verifiable identity use
[Self::code_hash]).
fn version(env: soroban_sdk::Env) -> soroban_sdk::String
fn maturity(env: soroban_sdk::Env) -> u64
fn pt_token(env: soroban_sdk::Env) -> soroban_sdk::Address
fn rate_bps(env: soroban_sdk::Env) -> u32
Set the fixed APR quoted to new deposits (existing receipts are unaffected β their payout
is locked). Bounded by the on-chain max_rate_bps ceiling set at init.
fn set_rate(env: soroban_sdk::Env, rate_bps: u32)
fn timelock(env: soroban_sdk::Env) -> u64
fn yt_token(env: soroban_sdk::Env) -> soroban_sdk::Address
The live deployed WASM hash (32-byte SHA-256) of the running code β reflects the current build even across upgrades.
fn code_hash(env: soroban_sdk::Env) -> soroban_sdk::BytesN<32>
fn is_paused(env: soroban_sdk::Env) -> bool
One-shot, admin-gated init (SCF #7). Reads the PT/YT token addresses and the maturity from
wrapper so the vault is always in lock-step with the market it sits on. The underlying
(USDC) is passed explicitly rather than read from the wrapper: it must equal the wrapper's
deposit/settlement asset, but passing it keeps the vault decoupled from any specific wrapper
ABI version (older deployed wrappers may not expose an underlying() view). All three are
SACs, so no trustlines are needed for the vault to hold balances.
admin β operational admin (sets rate, pauses, harvests; cannot move user funds).wrapper β the Spield wrapper market this vault wraps.underlying β the wrapper's USDC SAC (what users deposit and PT redeems into).rate_bps β the initial fixed APR to quote (basis points), must be β€ max_rate_bps.max_rate_bps β the hard ceiling on any future quoted rate (a guardrail).fn initialize(
env: soroban_sdk::Env,
wrapper: soroban_sdk::Address,
underlying: soroban_sdk::Address,
rate_bps: u32,
max_rate_bps: u32,
)
fn get_receipt(env: soroban_sdk::Env, receipt_id: u64) -> FixedReceipt
Accept a pending admin proposal (step 2 of 2). Must be called by the proposed admin.
fn accept_admin(env: soroban_sdk::Env)
Permissionless TTL keep-alive (mainnet-readiness #5). Extends a receipt entry's storage
TTL to comfortably exceed the vault maturity (+grace), clamped to the network max. Anyone may
call it β it only prolongs the entry, never mutates accounting β so a receipt held to maturity
can't archive before its owner redeems. No auth, no pause gate. Panics ReceiptNotFound for
an unknown id.
fn bump_receipt(env: soroban_sdk::Env, receipt_id: u64)
fn set_timelock(env: soroban_sdk::Env, secs: u64)
Atomic deploy-time constructor (no deployβinit front-run). Binds admin the moment the
vault exists; the remaining [Self::initialize] is then gated to this admin.
fn __constructor(env: soroban_sdk::Env, admin: soroban_sdk::Address)
fn apply_upgrade(env: soroban_sdk::Env)
fn pending_admin(env: soroban_sdk::Env) -> Option
Propose a new admin (step 1 of 2). Current admin authorizes; the proposed admin must then
call accept_admin to take control.
fn propose_admin(env: soroban_sdk::Env, new_admin: soroban_sdk::Address)
fn cancel_upgrade(env: soroban_sdk::Env)
fn pending_upgrade(env: soroban_sdk::Env) -> Option
Schedule a contract upgrade to wasm_hash, applyable after the timelock. Returns the eta.
fn schedule_upgrade(env: soroban_sdk::Env, wasm_hash: soroban_sdk::BytesN<32>) -> u64
Cancel a pending admin proposal. Current admin only.
fn cancel_admin_transfer(env: soroban_sdk::Env)