Rebalance Types
| Type | Enum | Description |
|---|---|---|
| Deposit | 0 | User deposits tokens → receives vault tokens |
| Withdraw | 1 | User burns vault tokens → receives underlying tokens |
| Vault | 2 | Keeper-initiated rebalance to restore target weights |
| VaultCustom | 3 | Custom vault rebalance |
Lifecycle
Each rebalance type follows a similar on-chain flow, but with type-specific stages: Deposit flow:| Action | Enum | Description |
|---|---|---|
not_active | 0 | Intent not yet initialized |
deposit_tokens | 1 | User is depositing tokens (deposits only) |
update_prices | 3 | Oracle prices need to be refreshed |
auction | 4 | Auction phase — keepers execute flash swaps |
Mint, redeem, and claim bounty are terminal task stages — they do not appear as separate
current_action enum values but are handled after the auction phase completes.Obtaining a Rebalance Intent Key
Many SDK methods require arebalance_intent pubkey. You can obtain it in two ways:
- Deterministic PDA — The rebalance intent address is derived from
[REBALANCE_INTENT_SEED, vault_key, owner_key]. Use this when you know both the vault and the owner. - Fetch from on-chain — Query active intents:
Deposits
Step 1: Create Deposit Intent and Deposit Tokens
contributions array specifies which tokens to deposit and how much. All amounts are raw values in the token’s smallest unit (e.g., lamports for SOL, 10^6 units for USDC). Users can contribute any tokens — they do NOT need to match the vault’s composition. The rebalance auction will swap tokens as needed.
The vault_mint parameter is the vault’s SPL token mint address (not the vault account address).
Step 2 (Optional): Deposit More Tokens
Before locking, users can add more contributions:Step 3: Lock Deposits
Locking freezes contributions and starts the rebalance process:update_prices. From here, keepers typically take over — but users can execute any of these steps themselves using the same SDK methods.
Steps 4–7: Processing
These steps are typically handled by keepers automatically, but any user can call these methods directly:- Update Prices —
updateTokenPricesTxrefreshes oracle prices. - Auctions — Three auction windows where flash swaps are executed via
flashSwapTx. - Mint —
mintTxmints vault tokens to the depositor. - Claim Bounty —
claimBountyTxdistributes rewards and closes the account.
After vault tokens are minted, any deposited tokens not consumed during minting are returned to the depositor. This happens automatically: the rebalance intent transitions to a withdrawal phase. Since the depositor’s contributed tokens are marked as “keep tokens,” the return skips the auction entirely and proceeds directly to redemption.
Withdrawals
When the vault has performance fees configured (any of host/creator/managers performance fee > 0), the withdrawal follows a deferred path:
- The vault token burn amount and fee calculations are recorded but token amounts are not immediately subtracted from the vault.
- The vault’s
active_withdrawscounter is incremented. - During the
updateTokenPricesTxstep, performance fees are calculated, token amounts are subtracted from the vault, andsupply_outstandingis adjusted.
active_managements must be 0).keep_tokens Behavior
The keep_tokens parameter controls which tokens the user receives directly without going through auctions:
- Empty (
[]) — Full rebalance flow. Keepers update prices, run 3 auction windows to swap tokens toward a single output, then redeem. This is the slowest path. - Partial (
[mint1, mint2]) — The specified tokens are sent directly to the user. The remaining tokens still go through price updates and auctions. - All vault mints — Fast withdrawal. When every token in the vault’s composition (including
active: falseslots) is passed, the protocol skips price updates and auctions entirely. The intent goes directly to the redeem stage. The user receives their proportional share of each underlying token. This still requires two transactions:sellVaultTxto create the intent, thenredeemTokensTxto transfer the tokens. The user can callredeemTokensTxthemselves — no need to wait for a keeper.
Fast Withdrawal
When every token in the vault’s composition is passed inkeep_tokens, the protocol skips price updates and auctions. The intent goes directly to the redeem stage. This is two transactions: sellVaultTx then redeemTokensTx.
The
keeper parameter in redeemTokensTx is just the signing wallet — any user can call this directly.Standard Withdrawal Flow
After creating the withdrawal intent, keepers typically process it — but users can also execute each step themselves:- Update Prices (
updateTokenPricesTx) - Auctions (
flashSwapTx) - Redeem Tokens (
redeemTokensTx) - Claim Bounty (
claimBountyTx)
Vault Rebalance (Keeper-Initiated)
Keepers can trigger a rebalance to bring the vault back to its target weights. A rebalance is only allowed when all of the following conditions are met:- Automation is enabled —
automation_settings.enabledmust betrue(configured viaeditAutomationTx). - No active rebalance — the vault must not already have a deposit, withdrawal, or rebalance in progress.
- Bounty balance — the vault must have bounty funds to pay the keeper (added via
addBountyTx). - Within the automation window — the current time must fall within the vault’s schedule automation window (
automation_starttoautomation_endwithin the cycle). See Schedule & Cycles for details. - Cooldown elapsed — enough time must have passed since the last automated rebalance (
rebalance_activation_cooldownseconds). - Threshold exceeded — at least one non-bounty token must have drifted beyond both the absolute and relative deviation thresholds. The bounty token (typically WSOL) is excluded from this check.
rebalance_activation_threshold_abs_bps— minimum deviation as a percentage of total vault value (e.g., 500 = 5%). Computed as|actual_value - target_value| / vault_tvl.rebalance_activation_threshold_rel_bps— minimum deviation relative to the token’s own target (e.g., 1000 = 10%). Computed as|actual_value - target_value| / max(actual_value, target_value).
isRebalanceRequired() utility checks all of these conditions:
editAutomationTx:
Auction System
After price updates, the rebalance enters three sequential auction stages. Each stage has a fixed duration configured in the protocol’s global config (rebalance_auction_1_timeframe, rebalance_auction_2_timeframe, rebalance_auction_3_timeframe). During each stage, keepers can execute flash swaps to move the vault toward its target weights.
Auction Pricing
The vault uses oracle confidence bands to create a Dutch-auction-style pricing curve that crosses through fair value, incentivizing timely execution:- At auction start: The vault sells tokens at
price + confidence(expensive for keepers) and buys tokens atprice - confidence(cheap for keepers). This is the widest unfavorable spread. - Over time: The spread narrows linearly toward mid-price. The price delta follows:
conf × 2 × time_elapsed / auction_duration. - At the midpoint: Both buy and sell prices converge to the oracle mid-price. The spread is zero.
- After the midpoint: The prices cross through mid-price and the vault begins offering better-than-market rates — selling below mid-price and buying above mid-price. This creates increasing profit opportunity for keepers.
- At auction end: Sell price reaches
price - confidenceand buy price reachesprice + confidence— the maximum favorable spread for keepers.
After Auctions End
Once all three auction stages complete:- Deposits: Vault tokens are minted to the depositor via
mintTx. - Withdrawals: Underlying tokens are sent to the withdrawer via
redeemTokensTx. - Vault rebalances: The rebalance completes directly.
claimBountyTx, which distributes bounty rewards to all keepers who completed tasks during the rebalance (proportional to the tasks they performed), awards a task bounty to the caller, returns unused bounty and the bounty bond to the depositor, and closes the rebalance intent account.
Flash Swaps
A flash swap is an atomic operation within a single transaction:- Flash Withdraw — Tokens are withdrawn from the vault to the keeper.
- Jupiter Swap — Keeper swaps the tokens via Jupiter (or any other DEX).
- Flash Deposit — Keeper deposits the swapped tokens back into the vault.
mint_out tokens and expects mint_in tokens back. The keeper profits from any spread between the vault’s auction price and the market price.
Flash Swap Parameters
| Parameter | Description |
|---|---|
keeper | Keeper’s public key |
vault | Vault account public key |
rebalance_intent | Rebalance intent public key (for rebalance swaps) |
intent | Intent public key (for direct swap intents) |
mint_in | Token the vault receives (keeper deposits this) |
mint_out | Token the vault gives (keeper receives this) |
amount_in | Amount of mint_in to deposit |
amount_out | Amount of mint_out to withdraw |
mode | 0 = exact_in, 1 = exact_out, 2 = IOC (immediate-or-cancel) |
jup_token_ledger_ix | Optional: Jupiter token ledger instruction |
jup_swap_ix | Optional: Jupiter swap instruction |
jup_address_lookup_table_addresses | Optional: Jupiter ALT addresses |
Swap Pairs
getSwapPairs(rebalanceIntent, vault) computes all valid swap pairs from the current auction state:
value < 0.005 are typically skipped as not worth the transaction cost.
Minting Vault Tokens
After auction windows close for a deposit rebalance:Redeeming Tokens
After auction windows close for a withdrawal rebalance:Claiming Bounty
After minting or redeeming is complete:Price Updates During Rebalance
Keepers must update oracle prices before the auction can begin:- Create and initialize Pyth VAAs
- Write and verify VAAs
- Update individual price feeds
- Update token prices in the vault + close VAA accounts
Standalone Pyth Price Update
To update Pyth prices without a rebalance context:Cancelling a Rebalance
Fetching Rebalance Intents
Checking If Rebalance Is Needed
Concurrent Operations
Deposits and withdrawals can proceed while a vault rebalance is in progress. When a deposit mints tokens or a withdrawal redeems tokens during an active vault rebalance, the vault rebalance intent’s token amounts and target amounts are automatically updated to reflect the changed vault composition. This prevents stale data in the rebalance auction. However, vault rebalances cannot run concurrently with each other (only one vault rebalance can exist at a time), and they requireactive_managements == 0 (no pending configuration changes).