Stake AQUA tokens and automatically mint BLUB tokens for staking.
This function performs the following operations:
user - The address of the user staking tokensamount - The amount of AQUA tokens to stakeduration_periods - The number of period units to lock tokens (multiplied by period_unit_minutes)Ok(()) - SuccessErr(Error::InvalidInput) if amount is <= 0Err(Error::ReentrancyDetected) if a reentrant call is detectedErr(Error::InsufficientBalance) if user doesn't have enough AQUARequires authorization from the user address.
fn lock(
env: soroban_sdk::Env,
user: soroban_sdk::Address,
amount: i128,
duration_periods: u64,
) -> 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.
user - The address of the user staking BLUBamount - The amount of BLUB tokens to stakeduration_periods - The number of period units to lock tokensOk(()) - SuccessErr(Error::InvalidInput) if amount is <= 0Err(Error::ReentrancyDetected) if a reentrant call is detectedErr(Error::InsufficientBalance) if user doesn't have enough BLUBRequires authorization from the user address.
fn stake(
env: soroban_sdk::Env,
user: soroban_sdk::Address,
amount: i128,
duration_periods: u64,
) -> Result<(), soroban_sdk::Error>
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.
user - The address of the user unstaking tokensamount - The amount of BLUB to unstakeOk(()) on successErr(Error::InvalidInput) if amount is <= 0Err(Error::NotFound) if user has no lock entriesErr(Error::NoUnlockableAmount) if no tokens available to unstakeErr(Error::ReentrancyDetected) if a reentrant call is detectedErr(Error::InsufficientBalance) if contract doesn't have enough BLUBRequires authorization from the user address.
fn unstake(
env: soroban_sdk::Env,
user: soroban_sdk::Address,
amount: i128,
) -> Result<(), soroban_sdk::Error>
Retrieves the current contract configuration.
Ok(Config) - The contract configurationErr(Error::NotInitialized) if contract is not initializedfn get_config(env: soroban_sdk::Env) -> Result
Initializes the staking contract with required configuration.
env - The contract environmentadmin - The administrator address that will have privileged accesstreasury_address - Address where treasury fees are sentaqua_token - Contract address of the AQUA tokenblub_token - Contract address of the BLUB token (Stellar asset)liquidity_contract - Address of the AQUA/BLUB StableSwap pool contractice_contract - Address of the ICE locking contract for governanceOk(()) on successErr(Error::AlreadyInitialized) if contract is already initializedRequires 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_contract: soroban_sdk::Address,
) -> Result<(), soroban_sdk::Error>
Retrieves a user's LP position for a specific pool.
user - The address of the userpool_id - The pool identifierSome(LpPosition) if the position existsNone if no position foundfn get_user_lp(
env: soroban_sdk::Env,
user: soroban_sdk::Address,
pool_id: soroban_sdk::Bytes,
) -> Option
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.
user - The address of the user whose lock is being recordedamount - The amount of tokens lockedduration_periods - The number of period units for the locktx_hash - The transaction hash from the external lockOk(()) - SuccessErr(Error::InvalidInput) if amount is <= 0Err(Error::ReentrancyDetected) if a reentrant call is detectedRequires 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.
user - The address of the user unlocking tokensamount - The amount of tokens to unlocktx_hash - The transaction hash for trackingOk(()) - SuccessErr(Error::InvalidInput) if amount is <= 0Err(Error::ReentrancyDetected) if a reentrant call is detectedErr(Error::InsufficientBalance) if contract doesn't have enough BLUBRequires authorization from the user address.
fn record_unlock(
env: soroban_sdk::Env,
user: soroban_sdk::Address,
amount: i128,
tx_hash: soroban_sdk::Bytes,
) -> Result<(), soroban_sdk::Error>
Gets all pool IDs that a user has LP positions in.
user - The address of the userA vector of pool IDs (empty if none)
fn get_user_pools(
env: soroban_sdk::Env,
user: soroban_sdk::Address,
) -> soroban_sdk::Vec
Retrieves the global contract state.
Ok(GlobalState) - The current global state including locked amounts, supply, and reward ratesErr(Error::NotInitialized) if contract is not initializedfn get_global_state(env: soroban_sdk::Env) -> Result
Gets the number of unlock entries for a user.
user - The address of the userThe count of unlock entries (0 if none)
fn get_unlock_count(env: soroban_sdk::Env, user: soroban_sdk::Address) -> u32
Retrieves accumulated reward totals for a user.
user - The address of the userSome(UserRewardTotals) if user has rewardsNone if no rewards foundfn get_user_rewards(
env: soroban_sdk::Env,
user: soroban_sdk::Address,
) -> Option
Updates the admin for the BLUB Stellar Asset Contract (SAC).
admin - The current admin addressnew_admin - The new admin address to setOk(()) on successErr(Error::Unauthorized) if caller is not the adminRequires 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>
Retrieves a specific pending stake entry by index.
index - The index of the pending stake entrySome(PendingStake) if the entry existsNone if the entry doesn't existfn get_pending_stake(env: soroban_sdk::Env, index: u32) -> Option
Retrieves the current reserves from the AQUA/BLUB liquidity pool.
Ok((i128, i128)) - A tuple of (aqua_reserve, blub_reserve)Err(Error::InvalidInput) if the pool query failsfn get_pool_reserves(env: soroban_sdk::Env) -> Result<(i128, i128), soroban_sdk::Error>
Records an LP (Liquidity Pool) deposit for a user.
admin - The admin address authorizing this operationuser - The address of the user depositing liquiditypool_id - The unique identifier of the liquidity poolamount_a - The amount of token A depositedamount_b - The amount of token B depositedtx_hash - The transaction hash for trackingOk(()) on successErr(Error::Unauthorized) if caller is not the adminErr(Error::InvalidInput) if amounts are negativeRequires authorization from the admin address.
fn record_lp_deposit(
env: soroban_sdk::Env,
admin: 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>
Claims accumulated rewards from the liquidity pool (admin-only).
admin - The admin address authorizing this operationOk(i128) - The amount of rewards claimedErr(Error::Unauthorized) if caller is not the adminErr(Error::InvalidInput) if the claim failsRequires authorization from the admin address.
fn claim_pool_rewards(
env: soroban_sdk::Env,
admin: soroban_sdk::Address,
) -> Result
Credits a reward amount to a specific user.
admin - The admin address authorizing this operationkind - The type of reward (0 = LP rewards, 1 = locked rewards)user - The address of the user receiving the rewardpool_id - The pool identifier (if applicable)amount - The amount of reward to credittx_hash - The transaction hash for trackingOk(()) on successErr(Error::Unauthorized) if caller is not the adminErr(Error::InvalidInput) if amount is <= 0Requires authorization from the admin address.
fn credit_user_reward(
env: soroban_sdk::Env,
admin: 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>
Manually deposits accumulated POL to the AQUA-BLUB LP pool (admin-only).
admin - The admin address authorizing this operationaqua_amount - The amount of AQUA to deposit to LPblub_amount - The amount of BLUB to deposit to LPOk(()) on successErr(Error::Unauthorized) if caller is not the adminErr(Error::InvalidInput) if amounts are <= 0Err(Error::InsufficientBalance) if contract doesn't have enough tokensRequires authorization from the admin address.
fn manual_deposit_pol(
env: soroban_sdk::Env,
admin: soroban_sdk::Address,
aqua_amount: i128,
blub_amount: i128,
) -> 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.
admin - The admin address authorizing this operationreward_amount - The total amount of rewards claimedice_voting_power - The ICE voting power used to obtain these rewardsOk(()) on successErr(Error::Unauthorized) if caller is not the adminErr(Error::InvalidInput) if reward_amount is <= 0Requires authorization from the admin address.
fn record_pol_rewards(
env: soroban_sdk::Env,
admin: soroban_sdk::Address,
reward_amount: i128,
ice_voting_power: i128,
) -> Result<(), soroban_sdk::Error>
Updates the staking period unit in minutes (admin-only).
admin - The admin address authorizing this operationperiod_unit_minutes - The new period unit in minutes (must be > 0)Ok(()) on successErr(Error::Unauthorized) if caller is not the adminErr(Error::InvalidPeriod) if period_unit_minutes is 0Requires 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>
Updates the base reward rate (admin-only).
admin - The admin address authorizing this operationnew_rate - The new reward rate in basis points per period (max 1000 = 10%)Ok(()) on successErr(Error::Unauthorized) if caller is not the adminErr(Error::InvalidInput) if new_rate > 1000Requires authorization from the admin address.
fn update_reward_rate(
env: soroban_sdk::Env,
admin: soroban_sdk::Address,
new_rate: i128,
) -> Result<(), soroban_sdk::Error>
Withdraws liquidity from the pool (admin-only).
Used to manage Protocol Owned Liquidity or rebalance the pool.
admin - The admin address authorizing this operationshare_amount - The amount of LP share tokens to burnmin_aqua - Minimum AQUA to receive (slippage protection)min_blub - Minimum BLUB to receive (slippage protection)Ok((i128, i128)) - A tuple of (aqua_withdrawn, blub_withdrawn)Err(Error::Unauthorized) if caller is not the adminErr(Error::InvalidInput) if parameters are invalid or withdrawal failsRequires authorization from the admin address.
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 a specific unlock entry by index for a user.
user - The address of the userindex - The index of the unlock entrySome(UnlockEntry) if the entry existsNone if the entry doesn't existfn get_unlock_by_index(
env: soroban_sdk::Env,
user: soroban_sdk::Address,
index: u32,
) -> Option
Gets the number of lock entries for a user.
user - The address of the userThe count of lock entries (0 if none)
fn get_user_lock_count(env: soroban_sdk::Env, user: soroban_sdk::Address) -> u32
Records a BLUB restake entry for tracking purposes.
user - The address of the user restaking BLUBamount - The amount of BLUB being restakedtx_hash - The transaction hash for trackingOk(()) - SuccessErr(Error::InvalidInput) if amount is <= 0Err(Error::ReentrancyDetected) if a reentrant call is detectedRequires 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>
Updates the ICE contract address (admin-only).
admin - The admin address authorizing this operationnew_ice_contract - The new ICE contract addressOk(()) on successErr(Error::Unauthorized) if caller is not the adminRequires authorization from the admin address.
fn update_ice_contract(
env: soroban_sdk::Env,
admin: soroban_sdk::Address,
new_ice_contract: soroban_sdk::Address,
) -> Result<(), soroban_sdk::Error>
Retrieves the LP share token address from the liquidity pool.
Ok(Address) - The share token contract addressErr(Error::InvalidInput) if the pool query failsfn get_pool_share_token(
env: soroban_sdk::Env,
) -> Result
Retrieves the lock totals for a specific user.
user - The address of the userSome(LockTotals) if user has locksNone if user has no locksfn get_user_lock_totals(
env: soroban_sdk::Env,
user: soroban_sdk::Address,
) -> Option
Retrieves comprehensive staking information for a user.
user - The address of the userOk(UserStakingInfo) - Detailed staking information including:Err(Error) if calculation failsfn get_user_staking_info(
env: soroban_sdk::Env,
user: soroban_sdk::Address,
) -> Result
Calculates the total rewards for a user from both locked stakes and LP positions.
user - The address of the user to calculate rewards forOk(UserRewardTotals) - The user's reward totals including pending and accumulated rewardsErr(Error) if calculation failsThis is a view function that doesn't modify state. It calculates:
fn calculate_user_rewards(
env: soroban_sdk::Env,
user: soroban_sdk::Address,
) -> Result
Gets the number of BLUB restake entries for a user.
user - The address of the userThe count of BLUB restake entries (0 if none)
fn get_blub_restake_count(env: soroban_sdk::Env, user: soroban_sdk::Address) -> u32
Retrieves a daily POL snapshot for a specific day.
day - The day number (timestamp / 86400)Some(ProtocolOwnedLiquidity) if a snapshot exists for that dayNone if no snapshot foundfn get_daily_pol_snapshot(
env: soroban_sdk::Env,
day: u64,
) -> Option
Gets the total number of reward distributions recorded.
The count of distribution entries (0 if none)
fn get_distribution_count(env: soroban_sdk::Env) -> u32
Retrieves the virtual price of the liquidity pool.
The virtual price represents the price of an LP token in terms of underlying assets.
Ok(i128) - The virtual priceErr(Error::InvalidInput) if the pool query failsfn get_pool_virtual_price(env: soroban_sdk::Env) -> Result
Retrieves a specific lock entry by index for a user.
user - The address of the userindex - The index of the lock entrySome(LockEntry) if the entry existsNone if the entry doesn't existfn get_user_lock_by_index(
env: soroban_sdk::Env,
user: soroban_sdk::Address,
index: u32,
) -> Option
Processes pending stake entries in batches.
This function avoids reentrancy by processing stakes in a separate transaction.
max_count - Maximum number of pending stakes to process (capped at 10)Ok(u32) - The number of stakes actually processedErr(Error) if processing failsfn process_pending_stakes(
env: soroban_sdk::Env,
max_count: u32,
) -> Result
Retrieves the total number of pending stake entries.
The count of pending stake entries (0 if none)
fn get_pending_stake_count(env: soroban_sdk::Env) -> u32
Retrieves the pending rewards available from the liquidity pool.
Ok(i128) - The amount of pending rewardsErr(Error::InvalidInput) if the pool query failsfn get_pool_pending_rewards(env: soroban_sdk::Env) -> Result
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.
Ok((i128, i128)) - A tuple of (available_aqua, available_blub)Err(Error) if unable to retrieve statefn get_available_pol_balance(
env: soroban_sdk::Env,
) -> Result<(i128, i128), soroban_sdk::Error>
Retrieves a specific BLUB restake entry by index for a user.
user - The address of the userindex - The index of the restake entrySome(BlubRestakeEntry) if the entry existsNone if the entry doesn't existfn get_blub_restake_by_index(
env: soroban_sdk::Env,
user: soroban_sdk::Address,
index: u32,
) -> Option
Retrieves a specific reward distribution entry by index.
index - The index of the distribution entrySome(RewardDistribution) if the entry existsNone if the entry doesn't existfn get_distribution_by_index(
env: soroban_sdk::Env,
index: u32,
) -> Option
Calculates the total POL contribution for a specific user.
Sums up all POL contributions from the user's lock entries.
user - The address of the userThe total amount of AQUA contributed to POL by this user
fn get_user_pol_contribution(env: soroban_sdk::Env, user: soroban_sdk::Address) -> i128
Test function to validate staking calculations without executing transactions.
aqua_amount - The amount of AQUA to simulate stakingOk((i128, i128, i128, i128, i128)) - A tuple containing:Err(Error::InvalidInput) if aqua_amount is <= 0fn test_staking_calculations(
env: soroban_sdk::Env,
aqua_amount: i128,
) -> Result<(i128, i128, i128, i128, i128), soroban_sdk::Error>
Updates the liquidity pool contract address (admin-only).
admin - The admin address authorizing this operationnew_liquidity_contract - The new liquidity pool contract addressOk(()) on successErr(Error::Unauthorized) if caller is not the adminRequires 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>
Records a reward distribution event.
admin - The admin address authorizing this operationkind - 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 distributeddistributed_amount - The amount distributed to userstreasury_amount - The amount sent to treasurytx_hash - The transaction hash for trackingOk(u32) - The index of the distribution recordErr(Error::Unauthorized) if caller is not the adminErr(Error::InvalidInput) if amounts are negativeRequires authorization from the admin address.
fn record_reward_distribution(
env: soroban_sdk::Env,
admin: 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
Retrieves the Protocol Owned Liquidity (POL) state.
The current POL state including AQUA/BLUB contributions and LP positions
fn get_protocol_owned_liquidity(env: soroban_sdk::Env) -> ProtocolOwnedLiquidity