Deposit USDC into a vault and receive proportional shares. Returns the number of shares minted to the depositor.
fn deposit(
env: soroban_sdk::Env,
depositor: soroban_sdk::Address,
vault_id: u32,
amount: i128,
min_shares_out: i128,
) -> Result
Admin in-place upgrade (the factory finally gets a migration path, mirroring market/vault/router). A disclosed admin power.
fn upgrade(
env: soroban_sdk::Env,
new_wasm_hash: soroban_sdk::BytesN<32>,
) -> Result<(), FactoryError>
Sentinel string so off-chain tooling can probe a deployed contract for its phase tag without parsing arbitrary state.
fn version(env: soroban_sdk::Env) -> soroban_sdk::Symbol
fn get_usdc(env: soroban_sdk::Env) -> Result
Burn shares and receive USDC back. Returns the USDC paid out.
fn withdraw(
env: soroban_sdk::Env,
depositor: soroban_sdk::Address,
vault_id: u32,
shares: i128,
min_usdc_out: i128,
) -> Result
fn get_admin(env: soroban_sdk::Env) -> Result
fn get_vault(env: soroban_sdk::Env, vault_id: u32) -> Result
Rotate the admin (R-11: the multisig migration path). Both current and new admin must sign โ mirrors the vault/router pattern so a mistyped address can't brick the admin role.
fn set_admin(
env: soroban_sdk::Env,
new_admin: soroban_sdk::Address,
) -> Result<(), FactoryError>
Read a depositor's share balance for a given vault.
fn shares_of(
env: soroban_sdk::Env,
vault_id: u32,
depositor: soroban_sdk::Address,
) -> i128
fn get_market(env: soroban_sdk::Env) -> Result
One-shot initialisation. Wires the factory to the protocol's market + USDC contracts and pins an admin address that can pause the factory globally.
fn initialize(
env: soroban_sdk::Env,
admin: soroban_sdk::Address,
market: soroban_sdk::Address,
usdc: soroban_sdk::Address,
) -> Result<(), FactoryError>
Leader-only pause / unpause for their own vault. While paused, deposit() and withdraw() return FactoryError::Paused.
fn set_paused(
env: soroban_sdk::Env,
vault_id: u32,
paused: bool,
) -> Result<(), FactoryError>
Fetch the full VaultInfo struct for a given id. Errors with
VaultNotFound if the id has never been minted.
fn view_vault(env: soroban_sdk::Env, vault_id: u32) -> Result
Admin-only emergency pause. Doesn't require leader signature.
fn admin_pause(
env: soroban_sdk::Env,
vault_id: u32,
paused: bool,
) -> Result<(), FactoryError>
Total number of vaults ever created. Vault ids are dense from 0
to vault_count() - 1.
fn vault_count(env: soroban_sdk::Env) -> u32
Create a fresh vault. The caller is bound as the leader; the vault starts empty (zero deposits, zero shares, NAV = 1.0, HWM = 1.0, profit share = 10%).
fn create_vault(
env: soroban_sdk::Env,
leader: soroban_sdk::Address,
name: soroban_sdk::String,
) -> Result
Full NAV (liquid + deployed) for a vault โ the true share basis. Fail-closed (#18) if any open position can't be valued.
fn get_full_nav(env: soroban_sdk::Env, vault_id: u32) -> Result
fn get_vault_ids(env: soroban_sdk::Env) -> soroban_sdk::Vec
Admin: cap the number of vaults that can exist (0 = unlimited).
fn set_max_vaults(env: soroban_sdk::Env, max: u32) -> Result<(), FactoryError>
The vault that owns a pending order (None if unknown/reconciled).
fn get_order_vault(env: soroban_sdk::Env, order_id: u64) -> Option
Reconcile a leader order the KEEPER resolved out-of-band (execution or cancellation happen via the keeper's execute_order, not a factory call, so the factory never saw the settlement). Permissionless and idempotent โ the ownership map is dropped on success, so a second call โ #16.
fn reconcile_order(
env: soroban_sdk::Env,
vault_id: u32,
order_id: u64,
) -> Result<(), FactoryError>
Leader pulls accumulated profit share above HWM. Returns the USDC paid out (zero if NAV โค HWM).
Formula: ((NAV - HWM) ร circulating_shares รท PRECISION) ร bps รท 10_000. On success, total_usdc decreases by the payout and the new HWM is set to the post-payout NAV โ the leader can't double-claim the same gain.
fn claim_leader_fees(
env: soroban_sdk::Env,
vault_id: u32,
) -> Result
The vault that owns a position (None if not a factory position).
fn get_position_vault(env: soroban_sdk::Env, position_id: u64) -> Option
L1-30: reconcile a vault position the KEEPER closed out-of-band (a protective SL/TP/trailing fire, or a liquidation) โ proceeds landed at the factory with no factory call. Permissionless + idempotent (the PositionVault map is dropped, so a second call โ #16). Credits the EXACT recorded proceeds (market.get_closed_proceeds), never a global-surplus guess. While the stale position lingers, full_nav fail-closes (#18), so the keeper reconciles promptly to unfreeze the vault.
fn reconcile_position(
env: soroban_sdk::Env,
vault_id: u32,
position_id: u64,
) -> Result<(), FactoryError>
Leader cancels a previously placed order.
fn leader_cancel_order(
env: soroban_sdk::Env,
leader: soroban_sdk::Address,
vault_id: u32,
order_id: u64,
) -> Result<(), FactoryError>
Leader opens an isolated position using vault funds. Returns the market's position id. After the call total_usdc is resynced from the on-chain USDC balance, so the vault's accounting always matches truth.
fn leader_open_position(
env: soroban_sdk::Env,
leader: soroban_sdk::Address,
vault_id: u32,
asset: soroban_sdk::Symbol,
collateral: i128,
leverage: u32,
direction: u32,
) -> Result
L1-30: attach a stop-loss to a vault position. Protective orders lock nothing market-side (no delta); a keeper-executed fire closes the position and is reconciled via reconcile_position.
fn leader_set_stop_loss(
env: soroban_sdk::Env,
leader: soroban_sdk::Address,
vault_id: u32,
position_id: u64,
trigger_price: i128,
slippage_tolerance_bps: u32,
) -> Result
Admin: restrict who may create vaults (empty list = permissionless).
fn set_leader_allowlist(
env: soroban_sdk::Env,
leaders: soroban_sdk::Vec,
) -> Result<(), FactoryError>
Leader closes an existing isolated position. The market settles PnL into the vault's USDC balance; we resync.
fn leader_close_position(
env: soroban_sdk::Env,
leader: soroban_sdk::Address,
vault_id: u32,
position_id: u64,
) -> Result<(), FactoryError>
L1-30: attach a take-profit to a vault position (limit_price 0 = market).
fn leader_set_take_profit(
env: soroban_sdk::Env,
leader: soroban_sdk::Address,
vault_id: u32,
position_id: u64,
trigger_price: i128,
slippage_tolerance_bps: u32,
limit_price: i128,
) -> Result
L1-30: place a stop-limit ENTRY on vault funds. Prefunds like a limit order โ measured-delta + OrderVault, reconciled via reconcile_order. NOTE: TIF is GTC here (Soroban's 10-param cap leaves no room for a TIF arg; the TIF pass-through lives on leader_place_limit_order).
fn leader_place_stop_limit(
env: soroban_sdk::Env,
leader: soroban_sdk::Address,
vault_id: u32,
asset: soroban_sdk::Symbol,
collateral: i128,
leverage: u32,
direction: u32,
trigger_price: i128,
limit_price: i128,
trigger_above: bool,
slippage_tolerance_bps: u32,
) -> Result
Leader places a limit order using vault funds.
fn leader_place_limit_order(
env: soroban_sdk::Env,
leader: soroban_sdk::Address,
vault_id: u32,
asset: soroban_sdk::Symbol,
collateral: i128,
leverage: u32,
direction: u32,
trigger_price: i128,
trigger_above: bool,
slippage_tolerance_bps: u32,
time_in_force: u32,
) -> Result
L1-30: attach a trailing stop to a vault position.
fn leader_place_trailing_stop(
env: soroban_sdk::Env,
leader: soroban_sdk::Address,
vault_id: u32,
position_id: u64,
trailing_percent_bps: u32,
slippage_tolerance_bps: u32,
) -> Result