fn admin(env: soroban_sdk::Env) -> soroban_sdk::Address
fn pause(env: soroban_sdk::Env)
fn expiry(env: soroban_sdk::Env) -> u64
Permissionless TTL keep-alive for an LP's share entry (tofix.md #30).
Share entries are bumped on every liquidity event, so an LP who provides once and then sits through the term is never written to. Anyone may call this — it only prolongs an entry.
No-ops for an address with no position.
fn bump_lp(env: soroban_sdk::Env, lp: soroban_sdk::Address)
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
PT price in asset units (SCALAR_12). 0 = no price.
fn pt_price(env: soroban_sdk::Env) -> i128
fn pt_token(env: soroban_sdk::Env) -> soroban_sdk::Address
fn reserves(env: soroban_sdk::Env) -> (i128, i128)
fn sr_token(env: soroban_sdk::Env) -> soroban_sdk::Address
The current upgrade delay, seconds. Bounded on chain to [1h, 30d].
fn timelock(env: soroban_sdk::Env) -> u64
fn treasury(env: soroban_sdk::Env) -> soroban_sdk::Address
The live deployed WASM hash (32-byte SHA-256) — reflects the running code across upgrades, so anyone can verify what is actually deployed rather than trusting a version string.
fn code_hash(env: soroban_sdk::Env) -> soroban_sdk::BytesN<32>
fn is_paused(env: soroban_sdk::Env) -> bool
One-shot, admin-gated init.
The market discovers PT, SR and expiry from the yield contract rather than being told
them, so the three-way mismatch class that tofix.md #19 describes (a market wired to the
wrong settlement asset, draining real value for a foreign token) is not expressible here.
scalar_root — curve steepness. Larger ⇒ flatter ⇒ less price impact per trade.ln_fee_root — annualized fee, SCALAR_12. Measured trade-off at 90d/5%
(calibrate_the_fee_root), against v1's flat 30 bps which cost 0.60% / 40.5%:| root/yr | PT round trip | YT round trip | |---|---|---| | 1.00% | 0.54% | 36.6% | | 0.50% | 0.30% | 21.8% | | 0.25% | 0.17% | 13.3% ← recommended default | | 0.10% | 0.10% | 7.9% |
A YT trader feels leverage × fee, and leverage at 90d/5% is ~67x — so a root that looks
negligible to a PT trader is still material to a YT trader. Pick lower for YT-focused
markets; the shape is fixed, only the level is a dial.
initial_apy — the rate the pool shfn initialize(
env: soroban_sdk::Env,
yield_contract: soroban_sdk::Address,
scalar_root: i128,
ln_fee_root: i128,
initial_apy: i128,
treasury_fee_share_bps: u32,
)
The fee a trader of notional PT face would pay right now, in asset units — the number the
UI should show, because it is what actually scales with time to expiry.
fn fee_preview(env: soroban_sdk::Env, notional: i128) -> i128
Implied APY as a SCALAR_12 fraction. 0 = none.
fn implied_apy(env: soroban_sdk::Env) -> i128
fn ln_fee_root(env: soroban_sdk::Env) -> i128
fn lp_position(env: soroban_sdk::Env, lp: soroban_sdk::Address) -> (i128, i128, i128)
fn scalar_root(env: soroban_sdk::Env) -> i128
Accept a pending admin proposal (step 2 of 2). Callable only by the proposed address.
fn accept_admin(env: soroban_sdk::Env)
PT out for spending sr_in SR. 0 = no quote.
fn quote_buy_pt(env: soroban_sdk::Env, sr_in: i128) -> i128
SR the user pays for exactly yt_out YT. 0 = no quote.
fn quote_buy_yt(env: soroban_sdk::Env, yt_out: i128) -> i128
fn set_timelock(env: soroban_sdk::Env, secs: u64)
fn set_treasury(env: soroban_sdk::Env, treasury: soroban_sdk::Address)
fn total_shares(env: soroban_sdk::Env) -> i128
fn __constructor(
env: soroban_sdk::Env,
admin: soroban_sdk::Address,
treasury: soroban_sdk::Address,
)
Add pt_in PT and sr_in SR. The first LP sets the reserve ratio — and because the anchor
is dynamic, any ratio opens the pool at the configured rate, so a 1:1 seed is fine.
fn add_liquidity(
env: soroban_sdk::Env,
lp: soroban_sdk::Address,
pt_in: i128,
sr_in: i128,
min_shares: i128,
) -> i128
Apply a scheduled upgrade. Reverts until eta has passed.
fn apply_upgrade(env: soroban_sdk::Env)
The SR reserve valued in asset units — what the curve actually compares against PT.
fn asset_reserve(env: soroban_sdk::Env) -> i128
fn pending_admin(env: soroban_sdk::Env) -> Option
Propose a new admin (step 1 of 2). The proposed address must then call
[Self::accept_admin]; until it does, nothing changes.
fn propose_admin(env: soroban_sdk::Env, new_admin: soroban_sdk::Address)
SR out for selling pt_in PT. 0 = no quote.
fn quote_sell_pt(env: soroban_sdk::Env, pt_in: i128) -> i128
SR the seller receives for yt_in YT. 0 = no quote.
fn quote_sell_yt(env: soroban_sdk::Env, yt_in: i128) -> i128
fn cancel_upgrade(env: soroban_sdk::Env)
fn yield_contract(env: soroban_sdk::Env) -> soroban_sdk::Address
fn pending_upgrade(env: soroban_sdk::Env) -> Option
fn set_ln_fee_root(env: soroban_sdk::Env, v: i128)
Lifetime SR routed to the treasury from swap fees.
fn treasury_earned(env: soroban_sdk::Env) -> i128
Buy exactly yt_out YT. The user funds only the YT's price; the pool funds the rest of
the notional and atomically keeps the freshly minted PT.
Sequence — no callback, no flash loan:
yt_out PT" (one ordinary curve evaluation)mint_py the full notional → market holds yt_out PT and yt_out YTtransfer the YT to the user — the hook settles them, so it is clean YTmax_sr_in, not the computed cost. The user's payment is derived from the live
index, which moves every ledger. Wallets sign auth entries against simulation amounts,
so signing the computed figure fails at execution with auth: invalid_action. We pull the
user's own max_sr_in and refund the difference.Sr::exchange_rate no longer calls the
strategy. It used to, and strategy::current_rate writes its RateBound onfn buy_yt_exact_out(
env: soroban_sdk::Env,
user: soroban_sdk::Address,
yt_out: i128,
max_sr_in: i128,
deadline_ledger: u32,
) -> i128
Burn shares and return the proportional PT + SR. Open even while paused and after expiry,
so a pause can never trap LP funds.
fn remove_liquidity(
env: soroban_sdk::Env,
lp: soroban_sdk::Address,
shares: i128,
min_pt_out: i128,
min_sr_out: i128,
) -> (i128, i128)
Schedule an upgrade to wasm_hash, applyable once the timelock elapses. Returns the eta.
The pending hash is publicly readable via [Self::pending_upgrade] for the whole window.
fn schedule_upgrade(env: soroban_sdk::Env, wasm_hash: soroban_sdk::BytesN<32>) -> u64
Sell exactly yt_in YT. The pool contributes matching PT, the pair is recombined, and
the released SR is split: the pool keeps the PT's market value, the seller takes the rest.
The seller's accrued interest is settled by the YT transfer in step 1 — it is credited,
not paid, exactly like Pendle. Collect it with yield.redeem_due_interest.
Returns the SR paid to the seller.
fn sell_yt_exact_in(
env: soroban_sdk::Env,
user: soroban_sdk::Address,
yt_in: i128,
min_sr_out: i128,
deadline_ledger: u32,
) -> i128
fn last_ln_implied_rate(env: soroban_sdk::Env) -> i128
Sell exactly pt_in PT for SR.
fn swap_exact_pt_for_sr(
env: soroban_sdk::Env,
trader: soroban_sdk::Address,
pt_in: i128,
min_sr_out: i128,
deadline_ledger: u32,
) -> i128
Buy PT with exactly sr_in SR.
fn swap_exact_sr_for_pt(
env: soroban_sdk::Env,
trader: soroban_sdk::Address,
sr_in: i128,
min_pt_out: i128,
deadline_ledger: u32,
) -> i128
Withdraw a pending proposal. Current admin only.
fn cancel_admin_transfer(env: soroban_sdk::Env)
fn set_treasury_fee_share(env: soroban_sdk::Env, bps: u32)
fn treasury_fee_share_bps(env: soroban_sdk::Env) -> u32