Skip to main content

Vault Overview

The vault is an ERC-4626 tokenized vault built on OpenZeppelin Stellar Contracts (stellar-tokens::vault). It holds a single collateral token (e.g., USDC) and issues share tokens to liquidity providers. The vault acts as the counterparty to all trading positions: it absorbs losses from traders and pays out profits.

For standard ERC-4626 behavior (deposit, withdraw, mint, redeem, share price math), refer to the OpenZeppelin Stellar Tokens documentation. This page documents only Zenex-specific extensions and design decisions.

Share Price

Share price reflects the vault's total asset value relative to outstanding shares:

share_price=total_assetstotal_supply\text{share\_price} = \frac{\text{total\_assets}}{\text{total\_supply}}

Share price increases when the vault receives fees from trades or collateral from losing positions. Share price decreases when the trading contract withdraws funds to pay profitable traders.

Decimals Offset

The vault constructor accepts a decimals_offset parameter (0 through 10) that provides inflation-attack protection via the OpenZeppelin virtual shares mechanism. This adds "dead shares" to the initial supply, preventing the first depositor from manipulating the share price through donation attacks.

Interaction with Trading

Token Flow

DirectionWhenMechanism
Fees to VaultEvery trade (open/close/fill)token.transfer(trading, vault, fee_amount)
Collateral to VaultTrader losstoken.transfer(trading, vault, collateral_remainder)
Vault to TradingTrader profitstrategy_withdraw(trading, payout_amount)

The trading contract never holds vault shares. It interacts purely through strategy_withdraw and direct token transfers.

Vault Interface

The trading contract uses a minimal vault client:

pub trait VaultInterface {
fn query_asset(e: Env) -> Address;
fn total_assets(e: Env) -> i128;
fn strategy_withdraw(e: Env, strategy: Address, amount: i128);
}

total_assets() is called by the circuit breaker and ADL system to determine vault capacity. query_asset() returns the underlying collateral token address. strategy_withdraw() is the sole mechanism for the trading contract to pull funds from the vault.

Storage Layout

Instance Storage

KeyTypeDescription
LockTimeu64Global lock duration in seconds
StrategyAddressAuthorized trading contract

Persistent Storage

KeyTypeDescription
DepositLock(Address)DepositLock { timestamp: u64, shares: i128 }Per-user deposit lock tracking the most recent deposit timestamp and the number of shares locked within that window

OpenZeppelin's token library manages share balances, allowances, and metadata in its own storage namespace.