Contract 0b3f0a36006e8335d0436689d5c052e79ce6d8c90ed4f202a944724be45b5f5b

← Back to Index 📥 Download WASM

Meta

cliver 27.0.0#5a7c5fe76530bf4248477ac812fc757146b98cc4
rssdkver 25.3.1#e50d95af029c83196dd122f0154bac3f1302394b
rsver 1.96.1

Instances

  • CDBVFJ4JAF7EPA4Y54FZKBOEU2WJV5VRJGSZP7JMZHYDQV7S7IPGBSNQ
  • CDRQJ7EYKTJV3W4BE2U4HIAWSVZB675MHTCBDGCXMKVR5VCURMNSEZ7O

Interface

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 sh
fn 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:

  1. price it as "the pool buys yt_out PT" (one ordinary curve evaluation)
  2. pull the user's SR share
  3. mint_py the full notional → market holds yt_out PT and yt_out YT
  4. transfer the YT to the user — the hook settles them, so it is clean YT

Two live-network bugs were fixed here — do not undo either (testnet 2026-08-24)

  1. Pull max_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.
  2. The index is read through a PURE view. Sr::exchange_rate no longer calls the strategy. It used to, and strategy::current_rate writes its RateBound on
fn 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

Imports

WebAssembly Text (WAT) ▶