Initialise the AMM. Called exactly once by the Factory; later
calls revert with [Error::AlreadyInitialized].
Inputs:
pt — PT token SAC.yt — YT token SAC (recorded for symmetry; not traded in v1).underlying — underlying SAC the pool quotes against.oracle — Strate Oracle for TWAP observations.maturity — Unix seconds. Must satisfy maturity > now + MIN_TOTAL_DURATION_SECONDS + MARKET_LOCK_WINDOW_SECONDS.scalar_root — curve scalar in WAD. Pendle's scalarRoot;
controls how aggressive the rate response is. Typical: 1e18 to
1e19.fee_bps — initial swap fee in basis points; <= MAX_FEE_BPS.admin — pause/unpause and fee adjustment authority.fn __constructor(
env: soroban_sdk::Env,
pt: soroban_sdk::Address,
yt: soroban_sdk::Address,
underlying: soroban_sdk::Address,
oracle: soroban_sdk::Address,
maturity: u64,
scalar_root: i128,
fee_bps: u32,
admin: soroban_sdk::Address,
)
Add liquidity. Pre-maturity only.
First call (empty pool): caller chooses any pt_in, under_in;
LP shares = sqrt(pt_in * under_in) - MINIMUM_LIQUIDITY and
MINIMUM_LIQUIDITY is permanently locked at the zero address.
Subsequent calls: shares = `min(pt_in / x_pt, under_in / x_under)
Slippage guard: reverts if lp_minted < min_lp_out.
fn add_liquidity(
env: soroban_sdk::Env,
provider: soroban_sdk::Address,
pt_in: i128,
under_in: i128,
min_lp_out: i128,
) -> i128
Remove liquidity proportionally. Available regardless of the AMM near-maturity lock — withdraw is pure share math, not a swap, so the asymptote does not apply. Pre-maturity only (post- maturity withdrawal is via the YieldStripping redemption path).
fn remove_liquidity(
env: soroban_sdk::Env,
provider: soroban_sdk::Address,
lp_in: i128,
min_pt_out: i128,
min_under_out: i128,
) -> (i128, i128)
Swap exact PT for underlying. Locked inside the near-maturity window. Reverts on slippage.
fn swap_exact_pt_for_sy(
env: soroban_sdk::Env,
trader: soroban_sdk::Address,
pt_in: i128,
min_sy_out: i128,
) -> i128
Swap exact underlying for PT.
Note: the IAmm trait's swap_sy_for_exact_pt semantics are
"trader specifies PT they want, AMM quotes max SY in". Pendle
V1's solver for the inverse path requires Newton iteration —
out of scope for v1. We implement the simpler, equally-useful
swap_exact_sy_for_pt here and keep the same selector name for
trait compatibility but treat pt_out as sy_in semantically.
TODO(post-v1): add swap_sy_for_exact_pt proper with Newton
solver once it is needed by the front-end. For now, callers
asking for an exact-PT-out can rely on quote → adjust → submit.
fn swap_sy_for_exact_pt(
env: soroban_sdk::Env,
trader: soroban_sdk::Address,
sy_in: i128,
min_pt_out: i128,
) -> i128
Current implied APY of the PT price (WAD).
fn implied_rate(env: soroban_sdk::Env) -> i128
Current implied APY (alias for the spec name).
fn get_implied_apy(env: soroban_sdk::Env) -> i128
Current PT spot price in underlying (WAD).
fn get_pt_price(env: soroban_sdk::Env) -> i128
Read the LP balance of an address.
fn lp_balance(env: soroban_sdk::Env, who: soroban_sdk::Address) -> i128
Read total LP supply.
fn total_lp(env: soroban_sdk::Env) -> i128
Read current reserves.
fn reserves(env: soroban_sdk::Env) -> (i128, i128)
Read the config (returns the address tuple — admin tooling / indexers consume this).
fn config(env: soroban_sdk::Env) -> AmmConfig
Permissionless: update the TWAP cumulative. Anyone may call. Costs the caller a small fee; useful for keepers that want to keep the oracle fresh during quiet periods.
fn update_observation(env: soroban_sdk::Env)
Pause the AMM. Stops swaps and add_liquidity. Remove-liquidity is also paused so the admin can freeze the market state for inspection; the emergency LP exit lives in YieldStripping per ADR-005.
fn pause(env: soroban_sdk::Env)
Unpause.
fn unpause(env: soroban_sdk::Env)
Adjust swap fee. Bounded to MAX_FEE_BPS. (Per spec there is no
explicit timelock here — the Factory's admin schedule is
expected to enforce that out-of-band. Bounding the max prevents
any single setter call from being catastrophic.)
fn set_fee_bps(env: soroban_sdk::Env, new_fee_bps: u32)