Contract b97f7deed3ed7d8e86f84ac89dd7d0b7b6ca348a0d60dc4eacb8c73fec772da1

← Back to Index 📥 Download WASM

Meta

rssdkver 21.7.7#5da789c50b18a4c2be53394138212fed56f0dfc4
rsver 1.86.0

Instances

  • CC72BEVVKHQ57PB5FCKAZYRXCSR6DOQSTN46QR7RZMMM64YWNRPDS24S

Interface

Initializes the staking contract with required configuration.

Arguments

  • env - The contract environment
  • admin - The administrator address that will have privileged access
  • treasury_address - Address where treasury fees are sent
  • aqua_token - Contract address of the AQUA token
  • blub_token - Contract address of the BLUB token (Stellar asset)
  • liquidity_contract - Address of the AQUA/BLUB StableSwap pool contract
  • ice_contract - Address of the ICE locking contract for governance

Returns

  • Ok(()) on success
  • Err(Error::AlreadyInitialized) if contract is already initialized

Authorization

Requires authorization from the admin address.

fn initialize(
    env: soroban_sdk::Env,
    admin: soroban_sdk::Address,
    treasury_address: soroban_sdk::Address,
    aqua_token: soroban_sdk::Address,
    blub_token: soroban_sdk::Address,
    liquidity_contract: soroban_sdk::Address,
    ice_tokens: IceTokens,
    vault_treasury: soroban_sdk::Address,
    vault_fee_bps: u32,
) -> Result<(), soroban_sdk::Error>

Retrieves the current contract configuration.

Returns

  • Ok(Config) - The contract configuration
  • Err(Error::NotInitialized) if contract is not initialized
fn get_config(env: soroban_sdk::Env) -> Result

Updates the admin for the BLUB Stellar Asset Contract (SAC).

Arguments

  • admin - The current admin address
  • new_admin - The new admin address to set

Returns

  • Ok(()) on success
  • Err(Error::Unauthorized) if caller is not the admin

Authorization

Requires authorization from the current admin address.

fn update_sac_admin(
    env: soroban_sdk::Env,
    admin: soroban_sdk::Address,
    new_admin: soroban_sdk::Address,
) -> Result<(), soroban_sdk::Error>

Stake AQUA tokens and automatically mint BLUB tokens for staking.

This function performs the following operations:

  • Transfers AQUA from user to contract
  • Mints 1.1x BLUB tokens (110% of AQUA amount)
  • Sends 90% of AQUA to ICE contract for governance
  • Keeps 10% AQUA for Protocol Owned Liquidity (POL)
  • Stakes the equivalent 1x BLUB for rewards
  • Automatically deposits 0.1x BLUB + 10% AQUA to LP pool

Arguments

  • user - The address of the user staking tokens
  • amount - The amount of AQUA tokens to stake
  • duration_periods - The number of period units to lock tokens (multiplied by period_unit_minutes)

Returns

  • Ok(()) - Success
  • Err(Error::InvalidInput) if amount is <= 0
  • Err(Error::ReentrancyDetected) if a reentrant call is detected
  • Err(Error::InsufficientBalance) if user doesn't have enough AQUA

Authorization

Requires authorization from the user address.

State Changes

  • Creates a new lock entry for the user
  • Updates global state with new locked amounts
  • Updates POL contribu
fn lock(
    env: soroban_sdk::Env,
    user: soroban_sdk::Address,
    amount: i128,
    duration_periods: u64,
) -> Result<(), soroban_sdk::Error>

Records a lock entry for tracking purposes without performing token transfers.

This function only records metadata about a lock that occurred elsewhere. Useful for tracking locks that happened on a different chain or contract.

Arguments

  • user - The address of the user whose lock is being recorded
  • amount - The amount of tokens locked
  • duration_periods - The number of period units for the lock
  • tx_hash - The transaction hash from the external lock

Returns

  • Ok(()) - Success
  • Err(Error::InvalidInput) if amount is <= 0
  • Err(Error::ReentrancyDetected) if a reentrant call is detected

Authorization

Requires authorization from the user address.

fn record_lock(
    env: soroban_sdk::Env,
    user: soroban_sdk::Address,
    amount: i128,
    duration_periods: u64,
    tx_hash: soroban_sdk::Bytes,
) -> Result<(), soroban_sdk::Error>

Records an unlock event and transfers locked BLUB plus rewards to the user.

Arguments

  • user - The address of the user unlocking tokens
  • amount - The amount of tokens to unlock
  • tx_hash - The transaction hash for tracking

Returns

  • Ok(()) - Success
  • Err(Error::InvalidInput) if amount is <= 0
  • Err(Error::ReentrancyDetected) if a reentrant call is detected
  • Err(Error::InsufficientBalance) if contract doesn't have enough BLUB

Authorization

Requires authorization from the user address.

State Changes

  • Creates a new unlock entry
  • Updates user lock totals
  • Updates global state
  • Transfers BLUB tokens and accumulated rewards to user
fn record_unlock(
    env: soroban_sdk::Env,
    user: soroban_sdk::Address,
    amount: i128,
    tx_hash: soroban_sdk::Bytes,
) -> Result<(), soroban_sdk::Error>

Restake BLUB tokens to earn more BLUB rewards.

Allows users to stake their BLUB tokens (obtained from previous stakes or rewards) to earn additional BLUB rewards.

Arguments

  • user - The address of the user staking BLUB
  • amount - The amount of BLUB tokens to stake
  • duration_periods - The number of period units to lock tokens

Returns

  • Ok(()) - Success
  • Err(Error::InvalidInput) if amount is <= 0
  • Err(Error::ReentrancyDetected) if a reentrant call is detected
  • Err(Error::InsufficientBalance) if user doesn't have enough BLUB

Authorization

Requires authorization from the user address.

State Changes

  • Creates a new BLUB lock entry
  • Updates lock totals
  • Updates global state:
  • Transfers BLUB from user to contract
fn stake(
    env: soroban_sdk::Env,
    user: soroban_sdk::Address,
    amount: i128,
    duration_periods: u64,
) -> Result<(), soroban_sdk::Error>

Records a BLUB restake entry for tracking purposes.

Arguments

  • user - The address of the user restaking BLUB
  • amount - The amount of BLUB being restaked
  • tx_hash - The transaction hash for tracking

Returns

  • Ok(()) - Success
  • Err(Error::InvalidInput) if amount is <= 0
  • Err(Error::ReentrancyDetected) if a reentrant call is detected

Authorization

Requires authorization from the user address.

fn record_blub_restake(
    env: soroban_sdk::Env,
    user: soroban_sdk::Address,
    amount: i128,
    tx_hash: soroban_sdk::Bytes,
) -> Result<(), soroban_sdk::Error>

Records an LP (Liquidity Pool) deposit for a user.

Arguments

  • admin - The admin address authorizing this operation
  • user - The address of the user depositing liquidity
  • pool_id - The unique identifier of the liquidity pool
  • amount_a - The amount of token A deposited
  • amount_b - The amount of token B deposited
  • tx_hash - The transaction hash for tracking

Returns

  • Ok(()) on success
  • Err(Error::Unauthorized) if caller is not the admin
  • Err(Error::InvalidInput) if amounts are negative

Authorization

Requires authorization from the admin address.

State Changes

  • Updates or creates LP position for user
  • Updates global LP staked amount
  • Calculates and credits any pending LP rewards
fn record_lp_deposit(
    env: soroban_sdk::Env,
    manager: soroban_sdk::Address,
    user: soroban_sdk::Address,
    pool_id: soroban_sdk::Bytes,
    amount_a: i128,
    amount_b: i128,
    tx_hash: soroban_sdk::Bytes,
) -> Result<(), soroban_sdk::Error>

Calculates the total rewards for a user from both locked stakes and LP positions.

Arguments

  • user - The address of the user to calculate rewards for

Returns

  • Ok(UserRewardTotals) - The user's reward totals including pending and accumulated rewards
  • Err(Error) if calculation fails

Note

This is a view function that doesn't modify state. It calculates:

  • Pending rewards from locked stakes (based on time elapsed and multipliers)
  • Pending rewards from LP positions (based on global reward rates)
fn calculate_user_rewards(
    env: soroban_sdk::Env,
    user: soroban_sdk::Address,
) -> Result

Records a reward distribution event.

Arguments

  • admin - The admin address authorizing this operation
  • kind - The type of reward distribution (0 = LP rewards, 1 = locked rewards)
  • pool_id - The pool identifier (if applicable)
  • total_reward - The total amount of rewards distributed
  • distributed_amount - The amount distributed to users
  • treasury_amount - The amount sent to treasury
  • tx_hash - The transaction hash for tracking

Returns

  • Ok(u32) - The index of the distribution record
  • Err(Error::Unauthorized) if caller is not the admin
  • Err(Error::InvalidInput) if amounts are negative

Authorization

Requires authorization from the admin address.

State Changes

  • Updates global reward rates for future calculations
  • Creates a new distribution record
  • Emits batch reward calculation event
fn record_reward_distribution(
    env: soroban_sdk::Env,
    manager: soroban_sdk::Address,
    kind: u32,
    pool_id: soroban_sdk::Bytes,
    total_reward: i128,
    distributed_amount: i128,
    treasury_amount: i128,
    tx_hash: soroban_sdk::Bytes,
) -> Result

Credits a reward amount to a specific user.

Arguments

  • admin - The admin address authorizing this operation
  • kind - The type of reward (0 = LP rewards, 1 = locked rewards)
  • user - The address of the user receiving the reward
  • pool_id - The pool identifier (if applicable)
  • amount - The amount of reward to credit
  • tx_hash - The transaction hash for tracking

Returns

  • Ok(()) on success
  • Err(Error::Unauthorized) if caller is not the admin
  • Err(Error::InvalidInput) if amount is <= 0

Authorization

Requires authorization from the admin address.

State Changes

  • Updates user's reward totals based on reward kind
fn credit_user_reward(
    env: soroban_sdk::Env,
    manager: soroban_sdk::Address,
    kind: u32,
    user: soroban_sdk::Address,
    pool_id: soroban_sdk::Bytes,
    amount: i128,
    tx_hash: soroban_sdk::Bytes,
) -> Result<(), soroban_sdk::Error>

Records POL (Protocol Owned Liquidity) rewards claimed from AQUA-BLUB pair voting.

The rewards are split: 70% distributed to users, 30% to treasury.

Arguments

  • admin - The admin address authorizing this operation
  • reward_amount - The total amount of rewards claimed
  • ice_voting_power - The ICE voting power used to obtain these rewards

Returns

  • Ok(()) on success
  • Err(Error::Unauthorized) if caller is not the admin
  • Err(Error::InvalidInput) if reward_amount is <= 0

Authorization

Requires authorization from the admin address.

State Changes

  • Updates POL state with new reward totals
  • Creates a daily POL snapshot
  • Emits POL rewards claimed event
fn record_pol_rewards(
    env: soroban_sdk::Env,
    manager: soroban_sdk::Address,
    reward_amount: i128,
    ice_voting_power: i128,
) -> Result<(), soroban_sdk::Error>

Retrieves the global contract state.

Returns

  • Ok(GlobalState) - The current global state including locked amounts, supply, and reward rates
  • Err(Error::NotInitialized) if contract is not initialized
fn get_global_state(env: soroban_sdk::Env) -> Result

Retrieves the lock totals for a specific user.

Arguments

  • user - The address of the user

Returns

  • Some(LockTotals) if user has locks
  • None if user has no locks
fn get_user_lock_totals(
    env: soroban_sdk::Env,
    user: soroban_sdk::Address,
) -> Option

Gets the number of lock entries for a user.

Arguments

  • user - The address of the user

Returns

The count of lock entries (0 if none)

fn get_user_lock_count(env: soroban_sdk::Env, user: soroban_sdk::Address) -> u32

Retrieves a specific lock entry by index for a user.

Arguments

  • user - The address of the user
  • index - The index of the lock entry

Returns

  • Some(LockEntry) if the entry exists
  • None if the entry doesn't exist
fn get_user_lock_by_index(
    env: soroban_sdk::Env,
    user: soroban_sdk::Address,
    index: u32,
) -> Option

Gets all pool IDs that a user has LP positions in.

Arguments

  • user - The address of the user

Returns

A vector of pool IDs (empty if none)

fn get_user_pools(
    env: soroban_sdk::Env,
    user: soroban_sdk::Address,
) -> soroban_sdk::Vec

Retrieves a user's LP position for a specific pool.

Arguments

  • user - The address of the user
  • pool_id - The pool identifier

Returns

  • Some(LpPosition) if the position exists
  • None if no position found
fn get_user_lp(
    env: soroban_sdk::Env,
    user: soroban_sdk::Address,
    pool_id: soroban_sdk::Bytes,
) -> Option

Retrieves accumulated reward totals for a user.

Arguments

  • user - The address of the user

Returns

  • Some(UserRewardTotals) if user has rewards
  • None if no rewards found
fn get_user_rewards(
    env: soroban_sdk::Env,
    user: soroban_sdk::Address,
) -> Option

Gets the number of unlock entries for a user.

Arguments

  • user - The address of the user

Returns

The count of unlock entries (0 if none)

fn get_unlock_count(env: soroban_sdk::Env, user: soroban_sdk::Address) -> u32

Retrieves a specific unlock entry by index for a user.

Arguments

  • user - The address of the user
  • index - The index of the unlock entry

Returns

  • Some(UnlockEntry) if the entry exists
  • None if the entry doesn't exist
fn get_unlock_by_index(
    env: soroban_sdk::Env,
    user: soroban_sdk::Address,
    index: u32,
) -> Option

Gets the number of BLUB restake entries for a user.

Arguments

  • user - The address of the user

Returns

The count of BLUB restake entries (0 if none)

fn get_blub_restake_count(env: soroban_sdk::Env, user: soroban_sdk::Address) -> u32

Retrieves a specific BLUB restake entry by index for a user.

Arguments

  • user - The address of the user
  • index - The index of the restake entry

Returns

  • Some(BlubRestakeEntry) if the entry exists
  • None if the entry doesn't exist
fn get_blub_restake_by_index(
    env: soroban_sdk::Env,
    user: soroban_sdk::Address,
    index: u32,
) -> Option

Gets the total number of reward distributions recorded.

Returns

The count of distribution entries (0 if none)

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

Retrieves a specific reward distribution entry by index.

Arguments

  • index - The index of the distribution entry

Returns

  • Some(RewardDistribution) if the entry exists
  • None if the entry doesn't exist
fn get_distribution_by_index(
    env: soroban_sdk::Env,
    index: u32,
) -> Option

Retrieves the Protocol Owned Liquidity (POL) state.

Returns

The current POL state including AQUA/BLUB contributions and LP positions

fn get_protocol_owned_liquidity(env: soroban_sdk::Env) -> ProtocolOwnedLiquidity

Retrieves a daily POL snapshot for a specific day.

Arguments

  • day - The day number (timestamp / 86400)

Returns

  • Some(ProtocolOwnedLiquidity) if a snapshot exists for that day
  • None if no snapshot found
fn get_daily_pol_snapshot(
    env: soroban_sdk::Env,
    day: u64,
) -> Option

Calculates the total POL contribution for a specific user.

Sums up all POL contributions from the user's lock entries.

Arguments

  • user - The address of the user

Returns

The total amount of AQUA contributed to POL by this user

fn get_user_pol_contribution(env: soroban_sdk::Env, user: soroban_sdk::Address) -> i128

Retrieves the current reserves from the AQUA/BLUB liquidity pool.

Returns

  • Ok((i128, i128)) - A tuple of (aqua_reserve, blub_reserve)
  • Err(Error::InvalidInput) if the pool query fails
fn get_pool_reserves(env: soroban_sdk::Env) -> Result<(i128, i128), soroban_sdk::Error>

Retrieves the LP share token address from the liquidity pool.

Returns

  • Ok(Address) - The share token contract address
  • Err(Error::InvalidInput) if the pool query fails
fn get_pool_share_token(
    env: soroban_sdk::Env,
) -> Result

Withdraws liquidity from the pool (admin-only).

Used to manage Protocol Owned Liquidity or rebalance the pool.

Arguments

  • admin - The admin address authorizing this operation
  • share_amount - The amount of LP share tokens to burn
  • min_aqua - Minimum AQUA to receive (slippage protection)
  • min_blub - Minimum BLUB to receive (slippage protection)

Returns

  • Ok((i128, i128)) - A tuple of (aqua_withdrawn, blub_withdrawn)
  • Err(Error::Unauthorized) if caller is not the admin
  • Err(Error::InvalidInput) if parameters are invalid or withdrawal fails

Authorization

Requires authorization from the admin address.

State Changes

  • Reduces POL LP position tracking
  • Burns LP share tokens
  • Transfers withdrawn tokens to contract Withdraws LP from the POL pool. Protected by admin (multisig) — manager cannot drain LP principal.
fn withdraw_from_pool(
    env: soroban_sdk::Env,
    admin: soroban_sdk::Address,
    share_amount: i128,
    min_aqua: i128,
    min_blub: i128,
) -> Result<(i128, i128), soroban_sdk::Error>

Retrieves the virtual price of the liquidity pool.

The virtual price represents the price of an LP token in terms of underlying assets.

Returns

  • Ok(i128) - The virtual price
  • Err(Error::InvalidInput) if the pool query fails
fn get_pool_virtual_price(env: soroban_sdk::Env) -> Result

Claims accumulated rewards from the liquidity pool (admin-only).

Arguments

  • admin - The admin address authorizing this operation

Returns

  • Ok(i128) - The amount of rewards claimed
  • Err(Error::Unauthorized) if caller is not the admin
  • Err(Error::InvalidInput) if the claim fails

Authorization

Requires authorization from the admin address.

State Changes

  • Updates POL total rewards earned
  • Updates last reward claim timestamp
fn claim_pool_rewards(
    env: soroban_sdk::Env,
    manager: soroban_sdk::Address,
) -> Result

Retrieves the pending rewards available from the liquidity pool.

Returns

  • Ok(i128) - The amount of pending rewards
  • Err(Error::InvalidInput) if the pool query fails
fn get_pool_pending_rewards(env: soroban_sdk::Env) -> Result

Updates the base reward rate (admin-only).

Arguments

  • admin - The admin address authorizing this operation
  • new_rate - The new reward rate in basis points per period (max 1000 = 10%)

Returns

  • Ok(()) on success
  • Err(Error::Unauthorized) if caller is not the admin
  • Err(Error::InvalidInput) if new_rate > 1000

Authorization

Requires authorization from the admin address.

fn update_reward_rate(
    env: soroban_sdk::Env,
    admin: soroban_sdk::Address,
    new_rate: i128,
) -> Result<(), soroban_sdk::Error>

Manually deposits accumulated POL to the AQUA-BLUB LP pool (admin-only).

Arguments

  • admin - The admin address authorizing this operation
  • aqua_amount - The amount of AQUA to deposit to LP
  • blub_amount - The amount of BLUB to deposit to LP

Returns

  • Ok(()) on success
  • Err(Error::Unauthorized) if caller is not the admin
  • Err(Error::InvalidInput) if amounts are <= 0
  • Err(Error::InsufficientBalance) if contract doesn't have enough tokens

Authorization

Requires authorization from the admin address.

State Changes

  • Transfers tokens to LP pool
  • Updates POL LP position tracking
fn manual_deposit_pol(
    env: soroban_sdk::Env,
    manager: soroban_sdk::Address,
    aqua_amount: i128,
    blub_amount: i128,
) -> Result<(), soroban_sdk::Error>

Updates the liquidity pool contract address (admin-only).

Arguments

  • admin - The admin address authorizing this operation
  • new_liquidity_contract - The new liquidity pool contract address

Returns

  • Ok(()) on success
  • Err(Error::Unauthorized) if caller is not the admin

Authorization

Requires authorization from the admin address.

fn update_liquidity_contract(
    env: soroban_sdk::Env,
    admin: soroban_sdk::Address,
    new_liquidity_contract: soroban_sdk::Address,
) -> Result<(), soroban_sdk::Error>

Updates BLUB token contract address (admin-only).

Arguments

  • admin - The admin address authorizing this operation
  • new_blub_token - The new BLUB token contract address

Returns

  • Ok(()) on success
  • Err(Error::Unauthorized) if caller is not the admin

Authorization

Requires authorization from the admin address.

fn update_blub_token(
    env: soroban_sdk::Env,
    admin: soroban_sdk::Address,
    new_blub_token: soroban_sdk::Address,
) -> Result<(), soroban_sdk::Error>

Updates vault treasury address (admin-only).

fn update_vault_treasury(
    env: soroban_sdk::Env,
    admin: soroban_sdk::Address,
    new_treasury: soroban_sdk::Address,
) -> Result<(), soroban_sdk::Error>

Updates vault fee in basis points (admin-only). Max 5000 (50%).

fn update_vault_fee_bps(
    env: soroban_sdk::Env,
    admin: soroban_sdk::Address,
    new_fee_bps: u32,
) -> Result<(), soroban_sdk::Error>

Updates ICE token addresses (admin-only).

fn update_ice_tokens(
    env: soroban_sdk::Env,
    admin: soroban_sdk::Address,
    ice_token: soroban_sdk::Address,
    govern_ice_token: soroban_sdk::Address,
    upvote_ice_token: soroban_sdk::Address,
    downvote_ice_token: soroban_sdk::Address,
) -> Result<(), soroban_sdk::Error>

Upgrades the contract to a new WASM hash (admin-only).

Arguments

  • admin - The admin address authorizing this operation
  • new_wasm_hash - The hash of the new WASM to upgrade to

Authorization

Requires authorization from the admin address.

fn upgrade(
    env: soroban_sdk::Env,
    admin: soroban_sdk::Address,
    new_wasm_hash: soroban_sdk::BytesN<32>,
) -> Result<(), soroban_sdk::Error>

Migrate contract from v1.1.0 to v1.2.0

  • Adds cooldown fields to Config
  • Initializes RewardStateV2 with correct total_staked

Arguments

  • admin - Admin address for authorization

Returns

  • Ok(()) on success
  • Err(Error::AlreadyInitialized) if already v1.2.0
  • Err(Error::Unauthorized) if not admin
fn migrate_v1_2_0(
    env: soroban_sdk::Env,
    admin: soroban_sdk::Address,
) -> Result<(), soroban_sdk::Error>

Sets the manager address (admin-only).

The manager is a single-sig backend wallet (e.g. blub-issuer-v2) that handles routine backend operations: adding rewards, compounding, claiming POL rewards, etc. The admin (multisig cold wallet) retains upgrade/config/pool authority.

Authorization

Requires admin authorization (via AdminAddress key).

fn set_manager(
    env: soroban_sdk::Env,
    admin: soroban_sdk::Address,
    new_manager: soroban_sdk::Address,
) -> Result<(), soroban_sdk::Error>

Returns the current manager address, or None if not yet set.

fn get_manager_address(env: soroban_sdk::Env) -> Option

Migration from v1.2.0 to v1.4.0: sets ManagerAddress = current admin.

After this migration:

  1. Transfer admin to the new multisig cold wallet via set_admin (or re-initialize).
  2. The existing blub-issuer-v2 will continue as manager unchanged.

Authorization

Requires current admin authorization.

fn migrate_v1_4_0(
    env: soroban_sdk::Env,
    admin: soroban_sdk::Address,
) -> Result<(), soroban_sdk::Error>

Returns the current config version. Transfers admin role to a new address (e.g. multisig cold wallet).

Updates both AdminAddress (upgrade key) and Config.admin. After this call, the old admin has no special authority.

Authorization

Requires current admin authorization.

fn transfer_admin(
    env: soroban_sdk::Env,
    admin: soroban_sdk::Address,
    new_admin: soroban_sdk::Address,
) -> Result<(), soroban_sdk::Error>

For old config: returns the old version number For new config: returns encoded version (10100 = v1.1.0)

fn get_version(env: soroban_sdk::Env) -> Result

Test function to validate staking calculations without executing transactions.

Arguments

  • aqua_amount - The amount of AQUA to simulate staking

Returns

  • Ok((i128, i128, i128, i128, i128)) - A tuple containing:
  • blub_minted: Total BLUB tokens that would be minted (1.1x AQUA)
  • blub_staked: BLUB amount that would be staked (1x AQUA)
  • blub_to_lp: BLUB amount that would go to LP (0.1x AQUA)
  • pol_aqua: AQUA amount for POL (10% of AQUA)
  • ice_aqua: AQUA amount to ICE contract (90% of AQUA)
  • Err(Error::InvalidInput) if aqua_amount is <= 0
fn test_staking_calculations(
    env: soroban_sdk::Env,
    aqua_amount: i128,
) -> Result<(i128, i128, i128, i128, i128), soroban_sdk::Error>

Retrieves the available POL balance that can be deposited to the LP pool.

Calculates available POL by subtracting currently locked/staked amounts from total balances.

Returns

  • Ok((i128, i128)) - A tuple of (available_aqua, available_blub)
  • Err(Error) if unable to retrieve state
fn get_available_pol_balance(
    env: soroban_sdk::Env,
) -> Result<(i128, i128), soroban_sdk::Error>

Processes pending stake entries in batches.

This function avoids reentrancy by processing stakes in a separate transaction.

Arguments

  • max_count - Maximum number of pending stakes to process (capped at 10)

Returns

  • Ok(u32) - The number of stakes actually processed
  • Err(Error) if processing fails
fn process_pending_stakes(
    env: soroban_sdk::Env,
    max_count: u32,
) -> Result

Retrieves the total number of pending stake entries.

Returns

The count of pending stake entries (0 if none)

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

Retrieves a specific pending stake entry by index.

Arguments

  • index - The index of the pending stake entry

Returns

  • Some(PendingStake) if the entry exists
  • None if the entry doesn't exist
fn get_pending_stake(env: soroban_sdk::Env, index: u32) -> Option

Updates the staking period unit in minutes (admin-only).

Arguments

  • admin - The admin address authorizing this operation
  • period_unit_minutes - The new period unit in minutes (must be > 0)

Returns

  • Ok(()) on success
  • Err(Error::Unauthorized) if caller is not the admin
  • Err(Error::InvalidPeriod) if period_unit_minutes is 0

Authorization

Requires authorization from the admin address.

fn update_period_unit(
    env: soroban_sdk::Env,
    admin: soroban_sdk::Address,
    period_unit_minutes: u64,
) -> Result<(), soroban_sdk::Error>

Retrieves comprehensive staking information for a user.

Arguments

  • user - The address of the user

Returns

  • Ok(UserStakingInfo) - Detailed staking information including:
  • total_staked_blub: Total BLUB currently locked/staked
  • unstaking_available: BLUB available to unstake (from unlocked positions)
  • accumulated_rewards: Total accumulated rewards
  • pending_rewards: Rewards not yet accumulated
  • total_locked_entries: Number of currently locked positions
  • total_unlocked_entries: Number of unlocked positions ready to unstake
  • Err(Error) if calculation fails
fn get_user_staking_info(
    env: soroban_sdk::Env,
    user: soroban_sdk::Address,
) -> Result

Unstakes tokens and transfers them along with accumulated rewards to the user.

Users can unstake immediately without waiting for unlock periods. This function automatically calculates and includes pending rewards.

Arguments

  • user - The address of the user unstaking tokens
  • amount - The amount of BLUB to unstake

Returns

  • Ok(()) on success
  • Err(Error::InvalidInput) if amount is <= 0
  • Err(Error::NotFound) if user has no lock entries
  • Err(Error::NoUnlockableAmount) if no tokens available to unstake
  • Err(Error::ReentrancyDetected) if a reentrant call is detected
  • Err(Error::InsufficientBalance) if contract doesn't have enough BLUB

Authorization

Requires authorization from the user address.

State Changes

  • Marks lock entries as unlocked
  • Updates user lock totals
  • Updates global state
  • Transfers BLUB and rewards to user
fn unstake(
    env: soroban_sdk::Env,
    user: soroban_sdk::Address,
    amount: i128,
) -> Result<(), soroban_sdk::Error>

Backend calls this to add BLUB rewards to the pool The rewards are distributed proportionally to all stakers based on their share

Arguments

  • admin - Admin address for authorization
  • amount - Amount of BLUB rewards to add

Authorization

Requires admin authorization

fn add_rewards(
    env: soroban_sdk::Env,
    manager: soroban_sdk::Address,
    amount: i128,
) -> Result<(), soroban_sdk::Error>

Emergency: drain incorrectly added BLUB and reset reward accumulator.

Call this when add_rewards was accidentally called with a bad amount (e.g. the BLUB issuer's sentinel balance i64::MAX). The function:

  1. Transfers all BLUB currently held by the contract back to admin.
  2. Resets reward_per_token_stored to correct_reward_per_token.
  3. Resets total_rewards_added to correct_total_rewards_added.

Per-user states (reward_per_token_paid, rewards_earned) are NOT modified. Users who had already checkpointed against the corrupted accumulator will see 0 pending rewards until new legitimate rewards are added (safe outcome).

Authorization

Requires admin (multisig) auth.

fn admin_emergency_reset_rewards(
    env: soroban_sdk::Env,
    admin: soroban_sdk::Address,
    correct_reward_per_token: i128,
    correct_total_rewards_added: i128,
) -> Result

Accepts AQUA protocol revenue and mints equivalent BLUB as staker rewards.

The admin specifies both the AQUA amount (protocol revenue collected) and the BLUB reward amount (based on off-chain market rate lookup). The AQUA is transferred to the contract (tracked as POL), and BLUB is minted and distributed to stakers via the Synthetix reward accumulator.

Arguments

  • admin - Admin address (must match config.admin)
  • aqua_amount - Amount of AQUA to transfer from admin to contract
  • blub_reward_amount - Amount of BLUB to mint as staker rewards

Returns

  • Ok(()) on success
  • Err(Unauthorized) if caller is not admin
  • Err(InvalidInput) if either amount <= 0
  • Err(InsufficientBalance) if AQUA transfer fails
fn add_rewards_from_aqua(
    env: soroban_sdk::Env,
    manager: soroban_sdk::Address,
    aqua_amount: i128,
    blub_reward_amount: i128,
) -> Result<(), soroban_sdk::Error>

User claims their accumulated BLUB rewards Subject to claim cooldown (default 7 days)

Arguments

  • user - User address claiming rewards

Returns

  • Ok(i128) - Amount of rewards claimed
  • Err(ClaimCooldownActive) - If cooldown hasn't elapsed
  • Err(NoRewardsToClaim) - If no rewards available
fn claim_rewards(
    env: soroban_sdk::Env,
    user: soroban_sdk::Address,
) -> Result

View function: Get user's pending rewards (without claiming)

Arguments

  • user - User address to check

Returns

Amount of pending BLUB rewards

fn get_pending_rewards(env: soroban_sdk::Env, user: soroban_sdk::Address) -> i128

View function: Get comprehensive reward info for a user

Arguments

  • user - User address to check

Returns

UserRewardInfo with pending, claimed, balance, and cooldown status

fn get_user_reward_info(
    env: soroban_sdk::Env,
    user: soroban_sdk::Address,
) -> UserRewardInfo

View function: Check if a specific lock entry can be unstaked

Arguments

  • user - User address
  • lock_index - Index of the lock entry

Returns

UnstakeStatus with availability info

fn get_unstake_status(
    env: soroban_sdk::Env,
    user: soroban_sdk::Address,
    lock_index: u32,
) -> UnstakeStatus

Get the global reward state (view function)

fn get_reward_state_view(env: soroban_sdk::Env) -> RewardState

Admin: Update the unstake cooldown period

Arguments

  • admin - Admin address
  • cooldown_seconds - New cooldown in seconds
fn update_unstake_cooldown(
    env: soroban_sdk::Env,
    admin: soroban_sdk::Address,
    cooldown_seconds: u64,
) -> Result<(), soroban_sdk::Error>

Admin: Update the claim reward cooldown period

Arguments

  • admin - Admin address
  • cooldown_seconds - New cooldown in seconds
fn update_claim_cooldown(
    env: soroban_sdk::Env,
    admin: soroban_sdk::Address,
    cooldown_seconds: u64,
) -> Result<(), soroban_sdk::Error>

One-time setup to establish trustlines for all 4 ICE token types. Must be called by admin before contract can receive ICE tokens.

Authorization

Requires admin authorization

fn setup_ice_trustlines(
    env: soroban_sdk::Env,
    manager: soroban_sdk::Address,
) -> Result<(), soroban_sdk::Error>

Authorizes an ICE lock for a specific amount and duration. Backend cron will execute the actual locking on Stellar Classic.

Arguments

  • aqua_amount - Amount of AQUA to lock for ICE
  • duration_years - Lock duration (1-3 years)

Returns

Lock ID for tracking

Authorization

Requires admin authorization

fn authorize_ice_lock(
    env: soroban_sdk::Env,
    manager: soroban_sdk::Address,
    aqua_amount: i128,
    duration_years: u64,
) -> Result

Transfers authorized AQUA from contract to admin for ICE locking. Backend calls this after authorization to move AQUA to admin wallet, then creates claimable balance on Stellar Classic.

Arguments

  • lock_id - The authorization ID

Authorization

Requires admin authorization

fn transfer_authorized_aqua(
    env: soroban_sdk::Env,
    manager: soroban_sdk::Address,
    lock_id: u64,
) -> Result<(), soroban_sdk::Error>

Syncs all ICE token balances from SAC contracts. Backend calls this after ICE tokens are received.

Authorization

Requires admin authorization

fn sync_all_ice_balances(
    env: soroban_sdk::Env,
    manager: soroban_sdk::Address,
) -> Result<(), soroban_sdk::Error>

Adds a new pool to the vault (max 10 pools).

Arguments

  • pool_address - Aquarius pool contract address
  • token_a - First token in the pair
  • token_b - Second token in the pair
  • share_token - LP token address

Authorization

Requires admin authorization

fn add_pool(
    env: soroban_sdk::Env,
    manager: soroban_sdk::Address,
    pool_address: soroban_sdk::Address,
    token_a: soroban_sdk::Address,
    token_b: soroban_sdk::Address,
    share_token: soroban_sdk::Address,
) -> Result

Updates a pool's active status.

Authorization

Requires admin authorization

fn update_pool_status(
    env: soroban_sdk::Env,
    pool_id: u32,
    active: bool,
) -> Result<(), soroban_sdk::Error>

Deposits tokens to a vault pool. User deposits token_a + token_b, contract adds liquidity to Aquarius pool.

Arguments

  • user - User address
  • pool_id - Pool ID
  • desired_a - Amount of token_a to deposit
  • desired_b - Amount of token_b to deposit
  • min_shares - Minimum LP shares to receive (slippage protection)

Authorization

Requires user authorization

fn vault_deposit(
    env: soroban_sdk::Env,
    user: soroban_sdk::Address,
    pool_id: u32,
    desired_a: i128,
    desired_b: i128,
    min_shares: u128,
) -> Result<(), soroban_sdk::Error>

Single-asset vault deposit. Deposits a single token into an Aquarius pool. The AMM handles the internal swap to balance the deposit across both pool tokens.

Arguments

  • user - User address
  • pool_id - Pool ID
  • token_in - Address of the token being deposited (must be token_a or token_b of the pool)
  • amount_in - Amount of token_in to deposit (in raw units, 7 decimals)
  • min_shares - Minimum LP shares to receive (slippage protection)
fn vault_deposit_single(
    env: soroban_sdk::Env,
    user: soroban_sdk::Address,
    pool_id: u32,
    token_in: soroban_sdk::Address,
    amount_in: i128,
    min_shares: u128,
) -> Result<(), soroban_sdk::Error>

Withdraws tokens from a vault pool. User withdraws their share, contract removes liquidity from Aquarius pool.

Arguments

  • user - User address
  • pool_id - Pool ID
  • share_percent - Percentage of user's position to withdraw (0-10000 = 0-100%)
  • min_a - Minimum amount of token_a to receive (slippage protection)
  • min_b - Minimum amount of token_b to receive (slippage protection)

Authorization

Requires user authorization

fn vault_withdraw(
    env: soroban_sdk::Env,
    user: soroban_sdk::Address,
    pool_id: u32,
    share_percent: u32,
    min_a: u128,
    min_b: u128,
) -> Result<(), soroban_sdk::Error>

Claims boosted rewards from a pool and auto-compounds. 30% to treasury, 70% auto-compound back to pool. Backend cron calls this 4x daily using ICE balance for boost.

Arguments

  • pool_id - Pool ID to claim rewards from

Authorization

Requires admin authorization Claims boosted rewards from a pool, sends 30% to treasury and 70% to admin. The admin (backend) must then swap the AQUA to both pool tokens and call admin_compound_deposit to complete the compound cycle.

Returns: (total_rewards, treasury_amount, compound_amount) — all in AQUA raw units.

fn claim_and_compound(
    env: soroban_sdk::Env,
    manager: soroban_sdk::Address,
    pool_id: u32,
) -> Result<(i128, i128, i128), soroban_sdk::Error>

Deposits tokens from admin into an Aquarius pool on behalf of the contract. Called by backend after swapping AQUA into both pool tokens. This completes the compound cycle started by claim_and_compound.

Arguments

  • pool_id - Pool ID to deposit into
  • amount_a - Amount of token_a to deposit (from admin wallet)
  • amount_b - Amount of token_b to deposit (from admin wallet)
fn admin_compound_deposit(
    env: soroban_sdk::Env,
    manager: soroban_sdk::Address,
    pool_id: u32,
    amount_a: i128,
    amount_b: i128,
) -> Result

Gets pending AQUA available for ICE locking.

fn get_pending_aqua_for_ice(env: soroban_sdk::Env) -> Result

Gets all 4 ICE token balances.

fn get_all_ice_balances(
    env: soroban_sdk::Env,
) -> Result<(i128, i128, i128, i128), soroban_sdk::Error>

Gets upvoteICE balance for voting.

fn get_upvote_ice_balance(env: soroban_sdk::Env) -> Result

Gets ICE lock authorization by ID.

fn get_ice_lock_authorization(
    env: soroban_sdk::Env,
    lock_id: u64,
) -> Result

Gets pool information by ID.

fn get_pool_info(
    env: soroban_sdk::Env,
    pool_id: u32,
) -> Result

Gets user's vault position in a specific pool.

fn get_user_vault_position(
    env: soroban_sdk::Env,
    user: soroban_sdk::Address,
    pool_id: u32,
) -> Result

Gets total number of vault pools. Gets compound stats for a vault pool.

fn get_pool_compound_stats(env: soroban_sdk::Env, pool_id: u32) -> PoolCompoundStats

Gets user's compound gains for a specific pool. Returns (current_lp, deposited_lp, compound_gain_lp).

fn get_user_compound_gains(
    env: soroban_sdk::Env,
    user: soroban_sdk::Address,
    pool_id: u32,
) -> (i128, i128, i128)

Gets total number of vault pools.

fn get_pool_count(env: soroban_sdk::Env) -> Result

Imports

WebAssembly Text (WAT) ▶