fn name(env: soroban_sdk::Env) -> soroban_sdk::String
fn admin(env: soroban_sdk::Env) -> soroban_sdk::Address
fn asset(env: soroban_sdk::Env) -> soroban_sdk::Address
Emergency circuit-breaker (admin or guardian). Freezes every risk-increasing flow — deposit, allocate, record_bridge_out — while leaving exits and unwinds open: redeem, deallocate, emergency_withdraw_strategy and record_bridge_in keep working so the system can be wound down safely. unpause() is admin-only.
fn pause(env: soroban_sdk::Env, caller: soroban_sdk::Address) -> Result<(), VaultError>
fn keeper(env: soroban_sdk::Env) -> soroban_sdk::Address
Redeem shares for assets. Allowed while paused (users can always exit).
Withdrawal waterfall: idle first, then iterate strategies pulling the
shortfall via strategy.withdraw(). Each hop is capped by the
strategy's self-reported available_liquidity() so we never request
more than the underlying yield source can actually deliver on the
current ledger (e.g. a Blend pool at 100% utilization has
balance_of > 0 but available_liquidity == 0 until repayments
arrive). This removes the user's dependency on the keeper for exits:
whatever the vault holds across idle + strategies is redeemable in a
single transaction, without a prior admin/keeper deallocation call.
Exception — cross-chain funds: a redeem whose marked NAV includes the
bridged (off-Stellar) portion can't be fully served on-chain, since the
waterfall can't pull bridged funds. The bounded-shortfall guard below
reverts such an over-large exit (rather than underpaying); that fraction
stays illiquid until a keeper record_bridge_in recalls it.
fn redeem(
env: soroban_sdk::Env,
from: soroban_sdk::Address,
shares: i128,
) -> Result
fn symbol(env: soroban_sdk::Env) -> soroban_sdk::String
fn balance(env: soroban_sdk::Env, id: soroban_sdk::Address) -> i128
fn deposit(
env: soroban_sdk::Env,
from: soroban_sdk::Address,
assets: i128,
) -> Result
fn unpause(
env: soroban_sdk::Env,
caller: soroban_sdk::Address,
) -> Result<(), VaultError>
Deploy idle funds into a strategy.
The vault pre-transfers USDC to the strategy, then calls strategy.deposit(). This avoids cross-contract auth issues.
Enforces idle buffer: after allocation, remaining idle must be
= idle_buffer_bps % of total_assets.
fn allocate(
env: soroban_sdk::Env,
keeper: soroban_sdk::Address,
strategy: soroban_sdk::Address,
amount: i128,
) -> Result<(), VaultError>
fn decimals(env: soroban_sdk::Env) -> u32
fn guardian(env: soroban_sdk::Env) -> soroban_sdk::Address
fn transfer(
env: soroban_sdk::Env,
from: soroban_sdk::Address,
to: soroban_sdk::Address,
amount: i128,
) -> Result<(), VaultError>
fn is_paused(env: soroban_sdk::Env) -> bool
Pull funds from a strategy back to the vault.
fn deallocate(
env: soroban_sdk::Env,
keeper: soroban_sdk::Address,
strategy: soroban_sdk::Address,
amount: i128,
) -> Result
fn initialize(
env: soroban_sdk::Env,
admin: soroban_sdk::Address,
asset: soroban_sdk::Address,
keeper: soroban_sdk::Address,
guardian: soroban_sdk::Address,
fee_recipient: soroban_sdk::Address,
performance_fee_bps: u32,
idle_buffer_bps: u32,
name: soroban_sdk::String,
symbol: soroban_sdk::String,
) -> Result<(), VaultError>
fn set_keeper(
env: soroban_sdk::Env,
caller: soroban_sdk::Address,
new_keeper: soroban_sdk::Address,
) -> Result<(), VaultError>
fn deposit_cap(env: soroban_sdk::Env) -> i128
fn accept_admin(
env: soroban_sdk::Env,
caller: soroban_sdk::Address,
) -> Result<(), VaultError>
fn add_strategy(
env: soroban_sdk::Env,
caller: soroban_sdk::Address,
strategy: soroban_sdk::Address,
) -> Result<(), VaultError>
Collect performance fees based on high-water mark.
Anyone can call this (typically the keeper). Fees are minted as new shares to the fee_recipient, diluting existing holders by the fee percentage of yield above the HWM.
fn collect_fees(env: soroban_sdk::Env) -> Result
fn set_guardian(
env: soroban_sdk::Env,
caller: soroban_sdk::Address,
new_guardian: soroban_sdk::Address,
) -> Result<(), VaultError>
fn total_assets(env: soroban_sdk::Env) -> i128
fn total_supply(env: soroban_sdk::Env) -> i128
fn pending_admin(env: soroban_sdk::Env) -> Option
fn propose_admin(
env: soroban_sdk::Env,
caller: soroban_sdk::Address,
new_admin: soroban_sdk::Address,
) -> Result<(), VaultError>
fn upgrade_delay(env: soroban_sdk::Env) -> u64
Cancel a scheduled upgrade.
fn cancel_upgrade(
env: soroban_sdk::Env,
caller: soroban_sdk::Address,
) -> Result<(), VaultError>
fn get_strategies(env: soroban_sdk::Env) -> soroban_sdk::Vec
fn bridge_endpoint(env: soroban_sdk::Env) -> Option
fn bridged_balance(env: soroban_sdk::Env) -> i128
Execute a previously scheduled upgrade after the delay has passed.
fn execute_upgrade(
env: soroban_sdk::Env,
caller: soroban_sdk::Address,
) -> Result<(), VaultError>
fn high_water_mark(env: soroban_sdk::Env) -> i128
fn remove_strategy(
env: soroban_sdk::Env,
caller: soroban_sdk::Address,
strategy: soroban_sdk::Address,
) -> Result<(), VaultError>
fn set_deposit_cap(
env: soroban_sdk::Env,
caller: soroban_sdk::Address,
cap: i128,
) -> Result<(), VaultError>
fn tracked_balance(env: soroban_sdk::Env, strategy: soroban_sdk::Address) -> i128
Whether deposits are currently blocked because a non-zero bridged balance is stale (keeper heartbeat overdue). Surfaced for UIs.
fn is_bridged_stale(env: soroban_sdk::Env) -> bool
Record funds bridged BACK into the vault from the cross-chain endpoint.
Authorized by the configured endpoint itself — mirroring deposit's
from.require_auth() so the inbound transfer is rooted in the caller's
authorization. Funds can therefore only arrive from the designated
source. Reduces the bridged tally by up to its current value (never
negative). Cost-basis: any surplus over the recorded principal lands as
real idle and is realized yield — it cannot be fabricated, because the
tokens must actually move. Not gated by the cross-chain pause: inflows
are a recovery path and must stay open while outflows are halted.
fn record_bridge_in(env: soroban_sdk::Env, amount: i128) -> Result<(), VaultError>
Schedule a WASM upgrade. The upgrade can only be executed after the configured delay (default 48h). This gives users time to exit if they disagree with the upgrade.
fn schedule_upgrade(
env: soroban_sdk::Env,
caller: soroban_sdk::Address,
new_wasm_hash: soroban_sdk::BytesN<32>,
) -> Result<(), VaultError>
fn bridged_timestamp(env: soroban_sdk::Env) -> u64
fn convert_to_assets(env: soroban_sdk::Env, shares: i128) -> i128
fn convert_to_shares(env: soroban_sdk::Env, assets: i128) -> i128
Re-attest that the recorded bridged balance is still valid, refreshing its timestamp WITHOUT moving any funds.
record_bridge_out/record_bridge_in are the only other writers of the
bridged timestamp, and both move tokens — so a position parked on the
remote chain (earning yield, nothing to move yet) would otherwise go
stale after bridged_max_age and block deposits. This is the keeper's
liveness proof: it cannot fabricate value (the tally is unchanged), it
only says "the cross-chain position is still there." Gated by BOTH
pause switches on purpose — during an incident we WANT the balance to go
stale (total_assets then writes it off conservatively), so a paused or
cross-chain-paused vault stops accepting heartbeats and lets staleness
kick in. That gating is the counter to the one risk this adds: a
compromised-but-active keeper could otherwise heartbeat a bridged balance
whose remote backing is gone, keeping total_assets inflated (bounded by
the real bridged-out amount, and non-extractable — redeem c
fn heartbeat_bridged(
env: soroban_sdk::Env,
keeper: soroban_sdk::Address,
) -> Result<(), VaultError>
Halt cross-chain outflows (admin or guardian). record_bridge_out reverts while paused; record_bridge_in stays open so funds can return.
fn pause_cross_chain(
env: soroban_sdk::Env,
caller: soroban_sdk::Address,
) -> Result<(), VaultError>
Record funds bridged OUT of the vault toward the cross-chain endpoint.
Moves amount from idle to the bridged tally 1:1, so total_assets()
is unchanged — a bridge-out can never inflate share price. The
destination is the admin-configured bridge endpoint, NOT a
keeper-supplied address, so the keeper cannot divert funds. The idle
buffer is enforced and the guardian cross-chain kill-switch is honored.
fn record_bridge_out(
env: soroban_sdk::Env,
keeper: soroban_sdk::Address,
amount: i128,
) -> Result<(), VaultError>
fn scheduled_upgrade(env: soroban_sdk::Env) -> Option<(soroban_sdk::BytesN<32>, u64)>
fn set_upgrade_delay(
env: soroban_sdk::Env,
caller: soroban_sdk::Address,
delay: u64,
) -> Result<(), VaultError>
fn performance_fee_bps(env: soroban_sdk::Env) -> u32
Configure the cross-chain bridge endpoint (admin only). This is the fixed destination for record_bridge_out and source for record_bridge_in — the keeper never supplies an address, so it cannot divert funds. In production this is the vault-controlled remote-strategy adapter; it should be set behind the multisig admin.
Refuses to change the endpoint while funds are still recorded as out
(bridged_balance > 0): repointing mid-flight would strand those funds
at the old endpoint (record_bridge_in pulls from the new one). Recall
everything first, then migrate.
fn set_bridge_endpoint(
env: soroban_sdk::Env,
caller: soroban_sdk::Address,
endpoint: soroban_sdk::Address,
) -> Result<(), VaultError>
fn set_bridged_max_age(
env: soroban_sdk::Env,
caller: soroban_sdk::Address,
max_age: u64,
) -> Result<(), VaultError>
Resume cross-chain outflows (admin only).
fn unpause_cross_chain(
env: soroban_sdk::Env,
caller: soroban_sdk::Address,
) -> Result<(), VaultError>
Reconcile a strategy's tracked balance to its on-chain self-reported balance.
Keeper-only, but the value comes from the strategy itself via
balance_of() — NOT from keeper input. This removes the free-form
manipulation vector the old update_tracked_balance had, where a
compromised keeper could write an arbitrary tracked balance to distort
total_assets() (and hence share price). Strategies are admin-vetted,
so trusting their balance_of() is the intended trust boundary. Use
this to fold strategy-side yield into the vault's accounting.
fn sync_tracked_balance(
env: soroban_sdk::Env,
keeper: soroban_sdk::Address,
strategy: soroban_sdk::Address,
) -> Result<(), VaultError>
fn is_cross_chain_paused(env: soroban_sdk::Env) -> bool
Reconcile a strategy's tracked balance with NO deviation bound. For
admin/guardian use when a strategy's balance legitimately moves more
than the routine keeper band allows in one step: the initial
post-allocate sync, a large realized gain/loss, or recovery after a
transient balance_of() anomaly. Value still comes from the strategy
itself, never from caller input.
fn force_sync_tracked_balance(
env: soroban_sdk::Env,
caller: soroban_sdk::Address,
strategy: soroban_sdk::Address,
) -> Result<(), VaultError>
Emergency: pull all funds from a strategy.
fn emergency_withdraw_strategy(
env: soroban_sdk::Env,
caller: soroban_sdk::Address,
strategy: soroban_sdk::Address,
) -> Result