Contract 3bd05dfa2bf65299d359e86a4672a45900e8c5768d9f056ad8da5ccd779bcd12

← Back to Index 📥 Download WASM

Meta

binver 0.1.0
cliver 25.1.0#a048a57a75762458b487052e0021ea704a926bee
rssdkver 25.1.1#94c2a3b3a5ded6b9cf9cef0c207bf8804f3eb294
rsver 1.95.0
source_repo github:upshift-protocol/stellar-upshift-vault-contracts

Instances

  • CB74BAM2R7NNQJY2FCQA6J5UVLMSP44HQJNOCR33EQGZ2BKNFR4PJTL4

Interface

fn mint(
    env: soroban_sdk::Env,
    shares: i128,
    receiver: soroban_sdk::Address,
    from: soroban_sdk::Address,
    operator: soroban_sdk::Address,
) -> i128

Returns the name for this token.

Arguments

  • e - Access to Soroban environment.
fn name(env: soroban_sdk::Env) -> soroban_sdk::String
fn pause(env: soroban_sdk::Env, admin: soroban_sdk::Address)
fn redeem(
    env: soroban_sdk::Env,
    shares: i128,
    receiver: soroban_sdk::Address,
    owner: soroban_sdk::Address,
    operator: soroban_sdk::Address,
) -> i128

Returns the symbol for this token.

Arguments

  • e - Access to Soroban environment.
fn symbol(env: soroban_sdk::Env) -> soroban_sdk::String
fn approve(
    env: soroban_sdk::Env,
    owner: soroban_sdk::Address,
    spender: soroban_sdk::Address,
    amount: i128,
    live_until_ledger: u32,
)

Returns the amount of tokens held by account.

Arguments

  • e - Access to the Soroban environment.
  • account - The address for which the balance is being queried.
fn balance(env: soroban_sdk::Env, account: soroban_sdk::Address) -> i128
fn deposit(
    env: soroban_sdk::Env,
    assets: i128,
    receiver: soroban_sdk::Address,
    from: soroban_sdk::Address,
    operator: soroban_sdk::Address,
) -> i128
fn unpause(env: soroban_sdk::Env, admin: soroban_sdk::Address)
fn upgrade(
    env: soroban_sdk::Env,
    new_wasm_hash: soroban_sdk::BytesN<32>,
    operator: soroban_sdk::Address,
)
fn decimals(env: soroban_sdk::Env) -> u32
fn max_mint(env: soroban_sdk::Env, receiver: soroban_sdk::Address) -> i128
fn transfer(
    env: soroban_sdk::Env,
    from: soroban_sdk::Address,
    to: soroban_sdk::MuxedAddress,
    amount: i128,
)
fn withdraw(
    env: soroban_sdk::Env,
    assets: i128,
    receiver: soroban_sdk::Address,
    owner: soroban_sdk::Address,
    operator: soroban_sdk::Address,
) -> i128

Returns the amount of tokens a spender is allowed to spend on behalf of an owner.

Arguments

  • e - Access to Soroban environment.
  • owner - The address holding the tokens.
  • spender - The address authorized to spend the tokens.
fn allowance(
    env: soroban_sdk::Env,
    owner: soroban_sdk::Address,
    spender: soroban_sdk::Address,
) -> i128
fn get_admin(env: soroban_sdk::Env) -> soroban_sdk::Address
fn is_paused(env: soroban_sdk::Env) -> bool
fn extend_ttl(env: soroban_sdk::Env)
fn max_redeem(env: soroban_sdk::Env, owner: soroban_sdk::Address) -> i128
fn max_deposit(env: soroban_sdk::Env, receiver: soroban_sdk::Address) -> i128

Returns the address of the underlying asset that the vault manages.

Arguments

  • e - Access to the Soroban environment.

Errors

  • [crate::vault::VaultTokenError::VaultAssetAddressNotSet] - When the vault's underlying asset address has not been initialized.
fn query_asset(env: soroban_sdk::Env) -> soroban_sdk::Address

Accept admin role. Must be called by the address previously proposed via propose_admin before the deadline expires. Clears the pending proposal.

fn accept_admin(env: soroban_sdk::Env)
fn get_operator(env: soroban_sdk::Env) -> Option
fn max_withdraw(env: soroban_sdk::Env, owner: soroban_sdk::Address) -> i128
fn preview_mint(env: soroban_sdk::Env, shares: i128) -> i128

Note: setting admin == operator concentrates governance and AUM reporting under a single key. Prefer separate keys in production.

fn set_operator(
    env: soroban_sdk::Env,
    admin: soroban_sdk::Address,
    new_operator: soroban_sdk::Address,
)
fn total_assets(env: soroban_sdk::Env) -> i128

Returns the total amount of tokens in circulation.

Arguments

  • e - Access to the Soroban environment.
fn total_supply(env: soroban_sdk::Env) -> i128
fn __constructor(
    env: soroban_sdk::Env,
    name: soroban_sdk::String,
    symbol: soroban_sdk::String,
    asset: soroban_sdk::Address,
    decimals_offset: u32,
    admin: soroban_sdk::Address,
)

Propose a new admin. The pending admin must call accept_admin before deadline (ledger timestamp) to complete the transfer. Revokes any previous pending proposal.

fn propose_admin(
    env: soroban_sdk::Env,
    admin: soroban_sdk::Address,
    new_admin: soroban_sdk::Address,
    deadline: u64,
)
fn transfer_from(
    env: soroban_sdk::Env,
    spender: soroban_sdk::Address,
    from: soroban_sdk::Address,
    to: soroban_sdk::Address,
    amount: i128,
)

Register a new subaccount with the vault.

Requires admin authorization and a non-paused vault. For Strategy subaccounts, performs interface validation: zero-amount smoke-tests (deposit, withdraw), calls get_balance() (rejecting negative values), and verifies the strategy's asset matches the vault's via get_asset(). Wallet subaccounts skip all checks. Capped at MAX_SUBACCOUNTS entries.

fn add_subaccount(
    env: soroban_sdk::Env,
    admin: soroban_sdk::Address,
    subaccount: soroban_sdk::Address,
    subaccount_type: SubaccountType,
)
fn preview_redeem(env: soroban_sdk::Env, shares: i128) -> i128
fn set_aum_limits(
    env: soroban_sdk::Env,
    admin: soroban_sdk::Address,
    increase_bps: u32,
    decrease_bps: u32,
)

Returns the list of currently whitelisted subaccount addresses.

fn get_subaccounts(env: soroban_sdk::Env) -> soroban_sdk::Vec
fn preview_deposit(env: soroban_sdk::Env, assets: i128) -> i128
fn preview_withdraw(env: soroban_sdk::Env, assets: i128) -> i128
fn convert_to_assets(env: soroban_sdk::Env, shares: i128) -> i128
fn convert_to_shares(env: soroban_sdk::Env, assets: i128) -> i128
fn get_pending_admin(env: soroban_sdk::Env) -> Option

Removes a subaccount from the vault's whitelist. Whitelist-and- tracker cleanup only — does NOT adjust deployed_assets.

For Wallet subaccounts with non-zero attributed value, use remove_wallet_and_reconcile: it does the aggregate write-down and the removal atomically under dual auth, closing the pricing window of the two-step sequence (update_deployed_assets + remove_subaccount) where NAV is wrong between transactions. remove_subaccount rejects Wallet subaccounts whose WalletNetDeployed tracker is non-zero (WalletTrackerNotZero) to prevent that exact window being opened by mistake.

Remaining use cases for remove_subaccount:

  • Strategy removal (balances tracked live via get_balance()).
  • Wallet cleanup after a full pull via withdraw_from_subaccount has zeroed the tracker.
  • Emergency decommissioning where the operator key is unavailable: the admin must first rotate the operator (via set_operator) and then go through remove_wallet_and_reconcile or update_wallet_deployed to zero the
fn remove_subaccount(
    env: soroban_sdk::Env,
    admin: soroban_sdk::Address,
    subaccount: soroban_sdk::Address,
)
fn get_deployed_assets(env: soroban_sdk::Env) -> i128

Returns the type of a registered subaccount (Strategy or Wallet).

Panics with SubaccountNotWhitelisted if the address is not in the current whitelist. Defaults to Strategy for subaccounts registered before this field was introduced (backward compatibility).

fn get_subaccount_type(
    env: soroban_sdk::Env,
    subaccount: soroban_sdk::Address,
) -> SubaccountType

Cancel a pending admin transfer proposal. Only the current admin can cancel.

fn cancel_admin_proposal(env: soroban_sdk::Env, admin: soroban_sdk::Address)

Transfer amount of the underlying token from the vault to subaccount.

For Strategy subaccounts, notifies the strategy via IStrategy::deposit after the transfer. The strategy's balance is captured live by IStrategy::get_balance() in total_assets, so deployed_assets is NOT incremented. Wallet subaccounts receive the tokens directly with no further notification; their balance is not queried on-chain, so deployed_assets IS incremented. No AUM rate limit is applied — subaccount transfers don't change total_assets.

Requires operator authorization, a non-paused vault, and a whitelisted subaccount.

fn deposit_to_subaccount(
    env: soroban_sdk::Env,
    operator: soroban_sdk::Address,
    subaccount: soroban_sdk::Address,
    amount: i128,
)

Sum of IStrategy::get_balance() across all Strategy-type subaccounts. Useful for operators to see how much capital is visible on-chain in strategies vs. the wallet-attributed deployed_assets.

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

Configure the cumulative AUM rate-limit window.

window_duration — length of the fixed window in seconds (min 3,600 = 1 hour, max 604,800 = 7 days). The window resets entirely on expiry (tumbling window, not sliding).

cumulative_increase_bps / cumulative_decrease_bps — maximum cumulative change (in basis points of the base_deployed snapshot taken when the window resets) allowed within a single window.

Changing limits resets the active window so the new configuration takes effect immediately with a clean cumulative state.

fn set_aum_window_limits(
    env: soroban_sdk::Env,
    admin: soroban_sdk::Address,
    window_duration: u64,
    cumulative_increase_bps: u32,
    cumulative_decrease_bps: u32,
)
fn get_aum_decrease_limit(env: soroban_sdk::Env) -> u32
fn get_aum_increase_limit(env: soroban_sdk::Env) -> u32

Aggregate-only emergency escape hatch for deployed_assets.

Deprecated for routine use after F4: strategies self-report their full position (idle + deployed) via IStrategy::get_balance(), so deployed_assets no longer has a legitimate "strategy off-chain AUM" component. The standard operator path for wallet-attributed reconciliation is update_wallet_deployed (single wallet) or update_wallet_deployed_batch (multiple wallets atomically) — both move the per-wallet tracker and the aggregate in lockstep, so the invariant Σ WalletNetDeployed == deployed_assets is preserved.

Remaining legitimate uses:

  • Recovery from a storage anomaly where the invariant has already broken and the aggregate needs a correction that cannot be attributed to specific wallets.
  • Temporary aggregate correction during a multi-step migration that will restore the invariant in a follow-up transaction.

Warning: this function can break the wallet-tracker sum invariant by design. Off-chain monitoring should compare `get_

fn update_deployed_assets(
    env: soroban_sdk::Env,
    operator: soroban_sdk::Address,
    amount: i128,
)

Reconcile a single Wallet subaccount's attributed value. Atomically moves both the per-wallet tracker (to new_tracked) and the aggregate deployed_assets counter (by the same delta), so subsequent withdraw_from_subaccount calls can pull the full value without tripping the per-wallet over-pull check.

Use cases:

  • Recognising a gain (wallet appreciated): new_tracked > current.
  • Recognising a loss (wallet depreciated): new_tracked < current.
  • Recognising external dust the operator wants to recover: new_tracked = current + dust_amount, then pull.

Subject to the same AUM rate limits and pause semantics as update_deployed_assets: increases are rejected while paused; decreases remain allowed for loss recovery.

For aggregate-only reconciliation (e.g. strategy external AUM not attributable to a specific wallet) use update_deployed_assets instead.

fn update_wallet_deployed(
    env: soroban_sdk::Env,
    operator: soroban_sdk::Address,
    subaccount: soroban_sdk::Address,
    new_tracked: i128,
)

Length of the cumulative AUM rate-limit window in seconds (default: 86,400 = 24 hours).

fn get_aum_window_duration(env: soroban_sdk::Env) -> u64

Read the per-wallet net-deployed tracker for a subaccount.

Returns 0 for unregistered addresses, for Strategy subaccounts, and for Wallet subaccounts that have never been deposited to. Useful for admins verifying the result of seed_wallet_net_deployed and for monitoring dashboards.

fn get_wallet_net_deployed(
    env: soroban_sdk::Env,
    subaccount: soroban_sdk::Address,
) -> i128

Maximum cumulative AUM decrease within a window, in basis points (default: 500 = 5%).

fn get_aum_window_dec_limit(env: soroban_sdk::Env) -> u32

Maximum cumulative AUM increase within a window, in basis points (default: 1,000 = 10%).

fn get_aum_window_inc_limit(env: soroban_sdk::Env) -> u32

Per-wallet emergency escape hatch for the WalletNetDeployed tracker. Restricted to emergency storage corrections after F4: the standard operator path for gain/loss recognition and dust attribution is update_wallet_deployed (single wallet) or update_wallet_deployed_batch (multiple wallets atomically), which move the per-wallet tracker and the aggregate deployed_assets in lockstep and preserve the invariant Σ WalletNetDeployed == deployed_assets.

Remaining legitimate uses:

  • Backfilling the tracker for a wallet registered before per-wallet accounting was introduced (one-shot upgrade migration).
  • Correcting a divergence between get_deployed_assets() and get_wallet_deployed_assets() after a storage anomaly or a prior update_deployed_assets correction that left wallet attribution out of sync.

Warning: this function can break the wallet-tracker sum invariant by design. It does NOT touch the aggregate deployed_assets — use it only when the value being attributed is already recorded in

fn seed_wallet_net_deployed(
    env: soroban_sdk::Env,
    admin: soroban_sdk::Address,
    subaccount: soroban_sdk::Address,
    amount: i128,
)

Request amount of the underlying token back from subaccount.

For Strategy subaccounts, calls IStrategy::withdraw (push model). Strategy balances are queried live via get_balance(), so deployed_assets is NOT decremented.

For Wallet subaccounts, pulls tokens via transfer_from using a pre-approved SEP-41 allowance. The wallet owner (EOA or contract) must have called token.approve(wallet, vault, amount, ledger) beforehand. deployed_assets IS decremented for wallets.

Measures actual tokens received via balance-differencing. No AUM rate limit is applied — subaccount transfers don't change total_assets.

Requires operator authorization, a non-paused vault, and a whitelisted subaccount.

fn withdraw_from_subaccount(
    env: soroban_sdk::Env,
    operator: soroban_sdk::Address,
    subaccount: soroban_sdk::Address,
    amount: i128,
)

Sum of WalletNetDeployed across all Wallet-type subaccounts currently in the whitelist.

Exposes the Σ side of the F4 invariant Σ WalletNetDeployed == deployed_assets for off-chain monitoring. Under normal operation this returns the same value as get_deployed_assets(). Divergence indicates one of the documented escape hatches (update_deployed_assets or seed_wallet_net_deployed) has been used; the gap represents aggregate value not currently attributed to any wallet.

Bounded cost: the subaccount list is capped at MAX_SUBACCOUNTS (= 10), so this iterates at most ten map lookups.

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

Atomically reconcile the aggregate deployed_assets counter AND remove a Wallet subaccount in a single transaction.

Closes the pricing window between the two-step sequence:

  1. update_deployed_assets(operator, new_total)
  2. remove_subaccount(admin, wallet)

Between those transactions NAV is wrong in one direction or the other (write-down first: NAV under-reports while tokens still sit at the wallet → deposits mint too many shares; remove first: NAV over-reports against stranded value → redeems overpay). Combining both into one call eliminates the window.

Requires both admin (whitelist authority) and operator (AUM authority) to authorise — the combined function unions their permissions without granting either role unilateral access to the other's powers. When a single entity holds both keys (documented supported configuration on set_operator), the operator's require_auth is skipped to avoid Soroban's Auth, ExistingValue error that otherwise fires on a repeated auth of the same address. Su

fn remove_wallet_and_reconcile(
    env: soroban_sdk::Env,
    admin: soroban_sdk::Address,
    operator: soroban_sdk::Address,
    subaccount: soroban_sdk::Address,
    new_deployed_total: i128,
)

Reconcile multiple Wallet subaccounts atomically in a single call. Introduced as the F4 primary operator path for wallet-attributed reconciliation: replaces ad-hoc sequences of update_wallet_deployed calls with one transaction that moves the aggregate exactly once (so the AUM rate limit is applied to the net delta rather than to each intermediate step).

Each (subaccount, new_tracked) entry is validated independently (whitelisted, Wallet type, non-negative tracker). The net delta Σ(new_tracked - old_tracked) is applied to deployed_assets via the shared apply_deployed_assets_change helper, so the AUM rate limit is measured against the net (a batch with +100k on wallet A and -100k on wallet B passes even when each individual step would exceed the limit). Pause is enforced per entry: while paused, any positive entry delta panics with VaultPaused regardless of the batch's net — this matches update_wallet_deployed (where per-entry and net deltas coincide) and prevents a paused vault from accep

fn update_wallet_deployed_batch(
    env: soroban_sdk::Env,
    operator: soroban_sdk::Address,
    updates: soroban_sdk::Vec<(soroban_sdk::Address, i128)>,
)

Imports

WebAssembly Text (WAT) ▶