Contract 58ca04ba61cdd5b393228ff135de8976c8f2c0841e7dd8e3ec21b8383d652c3e

← Back to Index 📥 Download WASM

Meta

cliver 25.2.0#28484880988199233a7e8e87c97cb12dac323cb3
rssdkver 25.3.0#dcbea44513feb7734af6b6c4aced2c4a7a2715d0
rsver 1.94.0

Instances

  • CB7R2RMTDXJBZUNI55ISXCRBFRP77IJMO7UKQIYBSJH5KNTDQT6HWSLG

Interface

fn pair(env: soroban_sdk::Env) -> soroban_sdk::Address
fn asset(env: soroban_sdk::Env) -> soroban_sdk::Address
fn pause(
    env: soroban_sdk::Env,
    caller: soroban_sdk::Address,
) -> Result<(), StrategyError>

Fair price (num, den) of one OTHER raw unit in USDC raw units used by balance_of. Defaults to (1, 1).

fn price(env: soroban_sdk::Env) -> (i128, i128)
fn vault(env: soroban_sdk::Env) -> soroban_sdk::Address
fn router(env: soroban_sdk::Env) -> soroban_sdk::Address

Single-sided zap-in: USDC → LP.

Steps:

  1. Read live pool reserves
  2. Compute optimal swap split (zap::optimal_swap_amount)
  3. Swap swap_in USDC → OTHER, slippage-guarded
  4. add_liquidity(USDC_remaining, OTHER_received), slippage-guarded
  5. Update tracked_balance += amount

Vault MUST pre-transfer amount USDC to this contract before calling. Any LP minted plus any USDC/OTHER dust stays in the strategy and is reflected in balance_of.

fn deposit(
    env: soroban_sdk::Env,
    caller: soroban_sdk::Address,
    amount: i128,
) -> Result<(), StrategyError>
fn factory(env: soroban_sdk::Env) -> soroban_sdk::Address
fn unpause(
    env: soroban_sdk::Env,
    caller: soroban_sdk::Address,
) -> Result<(), StrategyError>

Withdraw amount USDC by burning the proportional fraction of LP.

Steps:

  1. Compute LP fraction = amount / current_lp_value_usdc
  2. remove_liquidity to receive USDC + OTHER
  3. Swap OTHER → USDC, slippage-guarded
  4. Transfer total USDC out to caller (vault)
  5. Update tracked_balance

Caps to actual position value if amount exceeds it. Returns the actual USDC delivered.

fn withdraw(
    env: soroban_sdk::Env,
    caller: soroban_sdk::Address,
    amount: i128,
) -> Result
fn is_paused(env: soroban_sdk::Env) -> bool

Set the external price of one OTHER raw unit in USDC raw units, as the rational num / den. Required for non-1:1 pairs (e.g. USDC/EURC must be set to the EUR/USD rate); a 1:1 equal-decimal peg can leave the (1, 1) default. Both components are bounded to [1, MAX_PRICE_COMPONENT] so a misconfiguration cannot overflow balance_of's fair-LP math.

fn set_price(
    env: soroban_sdk::Env,
    caller: soroban_sdk::Address,
    num: i128,
    den: i128,
) -> Result<(), StrategyError>
fn set_vault(
    env: soroban_sdk::Env,
    caller: soroban_sdk::Address,
    new_vault: soroban_sdk::Address,
) -> Result<(), StrategyError>

Manipulation-resistant USDC value of the strategy's holdings.

The LP position is valued with the fair-LP formula 2 * (lp / total_lp) * sqrt(reserve_usdc * reserve_other * price). The product reserve_usdc * reserve_other is the constant-product invariant, which an in-block swap leaves unchanged — so a flash-swap that moves the reserves cannot move this value (see tezoro_common::fair_lp_value_usdc). The external price comes from storage::get_price(), never from spot reserves. This deliberately replaces the previous spot swap-back valuation, which read live reserves and was manipulable.

Components:

  • LP position: fair-LP value above.
  • Idle OTHER dust: valued at the external price.
  • Idle USDC dust: 1:1.

Trade-off: fair value is a mid-price, so it does not subtract the swap fee/impact a real exit would realize on the OTHER half (bounded by the pool fee, ~10-30 bps on that half). The previous spot valuation netted that out but was manipulable — manipulation-resistance is the priority for a number t

fn balance_of(env: soroban_sdk::Env) -> i128

Initialize the adapter.

All on-chain references (router, factory, pair, usdc_is_token_0) are pre-resolved by the deploy script — the script queries Soroswap directly and passes verified values. Init does not make external calls; it just stores. This keeps init testable without mocking the entire Soroswap protocol and matches the trust model (admin is the deployer's multisig, expected to pass correct params). The pair's health is later validated lazily by is_healthy and at every deposit / withdraw (reserves > 0 check).

fn initialize(
    env: soroban_sdk::Env,
    admin: soroban_sdk::Address,
    vault: soroban_sdk::Address,
    asset: soroban_sdk::Address,
    other_asset: soroban_sdk::Address,
    router: soroban_sdk::Address,
    factory: soroban_sdk::Address,
    pair: soroban_sdk::Address,
    usdc_is_token_0: bool,
) -> Result<(), StrategyError>

Whether the underlying pool is healthy enough to operate against.

Currently checks reserves > 0; returning false also if reserves can't be read. A future revision will add depth thresholds and an oracle deviation check once a Stellar oracle is wired up.

fn is_healthy(env: soroban_sdk::Env) -> bool
fn other_asset(env: soroban_sdk::Env) -> soroban_sdk::Address
fn accept_admin(
    env: soroban_sdk::Env,
    caller: soroban_sdk::Address,
) -> Result<(), StrategyError>
fn propose_admin(
    env: soroban_sdk::Env,
    caller: soroban_sdk::Address,
    new_admin: soroban_sdk::Address,
) -> Result<(), StrategyError>
fn cancel_upgrade(
    env: soroban_sdk::Env,
    caller: soroban_sdk::Address,
) -> Result<(), StrategyError>
fn execute_upgrade(
    env: soroban_sdk::Env,
    caller: soroban_sdk::Address,
) -> Result<(), StrategyError>
fn tracked_balance(env: soroban_sdk::Env) -> i128
fn usdc_is_token_0(env: soroban_sdk::Env) -> bool
fn max_slippage_bps(env: soroban_sdk::Env) -> u32
fn schedule_upgrade(
    env: soroban_sdk::Env,
    caller: soroban_sdk::Address,
    new_wasm_hash: soroban_sdk::BytesN<32>,
) -> Result<(), StrategyError>
fn set_max_slippage(
    env: soroban_sdk::Env,
    caller: soroban_sdk::Address,
    bps: u32,
) -> Result<(), StrategyError>
fn set_upgrade_delay(
    env: soroban_sdk::Env,
    caller: soroban_sdk::Address,
    delay: u64,
) -> Result<(), StrategyError>

Pull all funds back to the vault.

Burns ALL LP, swaps ALL OTHER to USDC, transfers ALL USDC. Slippage guards are RELAXED here (uses 0 mins) because this is the escape hatch — taking some loss is preferable to being stuck. Callable by vault (normal) or admin (emergency).

fn emergency_withdraw(
    env: soroban_sdk::Env,
    caller: soroban_sdk::Address,
) -> Result

Liquidity available for immediate withdrawal — the realizable spot value (recoverable_usdc), trimmed by 2 stroops to absorb integer rounding in the AMM on exact-match withdraws. NOT balance_of (the fair-LP mark), which would over-state what withdraw() can deliver and could revert the vault's redeem waterfall.

fn available_liquidity(env: soroban_sdk::Env) -> i128
fn set_deadline_buffer(
    env: soroban_sdk::Env,
    caller: soroban_sdk::Address,
    seconds: u64,
) -> Result<(), StrategyError>

Imports

WebAssembly Text (WAT) ▶