Construct.
The global index lives in YT and defaults to WAD there. The
InitialBlendRate slot is left unset; the first
sync_yield_index call latches whatever rate the Oracle
reports as the baseline. This makes the constructor
independent of Oracle liveness at deploy time.
fn __constructor(env: soroban_sdk::Env, cfg: Config)
fn config(env: soroban_sdk::Env) -> Config
Read the current global yield index, WAD-scaled. Delegates to
YT, which owns the source-of-truth value. Does not trigger
a sync — that's the role of sync_yield_index.
fn current_index(env: soroban_sdk::Env) -> i128
Read what user would receive if they called claim_yield
right now, without mutating state. Delegates to YT's
accrued_yield, which combines the persisted bucket with the
not-yet-settled delta against the cached global index.
fn pending_yield(env: soroban_sdk::Env, user: soroban_sdk::Address) -> i128
Whether the contract is paused.
fn is_paused(env: soroban_sdk::Env) -> bool
Pending unpause ETA in seconds, or 0 if no proposal is open.
fn unpause_eta(env: soroban_sdk::Env) -> u64
Deposit underlying and mint matching PT+YT to to.
Returns (pt_minted, yt_minted, index_at_mint).
CEI order:
from.require_auth, pause check, maturity check.sync_yield_index — pushes the fresh global index into YT
(C-02 fix: the snapshot YT writes for to is the post-sync
value).to locally before incrementing balance.MintEvent.fn mint(
env: soroban_sdk::Env,
from: soroban_sdk::Address,
to: soroban_sdk::Address,
amount: i128,
) -> (i128, i128, i128)
Pre-maturity: burn equal PT and YT, return underlying 1:1.
fn redeem_pair(env: soroban_sdk::Env, from: soroban_sdk::Address, amount: i128) -> i128
Post-maturity: burn PT alone, return underlying.
fn redeem_pt(env: soroban_sdk::Env, from: soroban_sdk::Address, amount: i128) -> i128
Claim accrued yield for user.
CEI order: sync the index into YT, drain YT's accrued
bucket for user (this also settles any pending delta inside
YT), then transfer the underlying. Reversing the last two
would open a TOCTOU window in which the index could advance
between drain and transfer; do not do that.
fn claim_yield(env: soroban_sdk::Env, user: soroban_sdk::Address) -> i128
Refresh the global yield index from the Oracle and push it to YT. Permissionless.
Steps:
InitialBlendRate and exit (the index in
YT stays at WAD — there is no accrual to attribute
pre-launch).new = blend_rate / initial_rate (in WAD).new >= old. Oracle that goes backward
is rejected. (YT also enforces this on push_yield_index;
we keep both checks so YS surfaces the richer error context.)(new - old) / old <= MAX_DELTA_PER_SYNC.IndexSyncEvent.fn sync_yield_index(env: soroban_sdk::Env)
Instantly pause. Blocks mint; never blocks claim/redeem.
fn pause(env: soroban_sdk::Env)
Open an unpause proposal. The actual unpause executes after
UNPAUSE_TIMELOCK_SECS. Admin-only.
fn propose_unpause(env: soroban_sdk::Env)
Execute the unpause once now >= eta.
fn execute_unpause(env: soroban_sdk::Env)