Skip to main content

Veax smart contract

This document describes the smart contract for Veax and includes methods and structures for managing the DEX, such as creating and interacting with liquidity pools, swapping tokens, and managing fees.

Methods

#[init]
pub fn new(
owner_id: AccountId,
protocol_fee_fraction: BasisPoints,
fee_rates: dex::latest::RawFeeLevelsArray<BasisPoints>,
) -> Self
  • owner_id: This account is allowed to call 'admin' functions of the DEX, such as withdrawal of protocol fee or changing protocol fee fraction. Normally, this must be the governance SC.

  • protocol_fee_fraction: Fraction of the total fee that goes to the DEX. The rest of the fee is distributed among the liquidity providers. Specified in units of 1/FEE_DIVISOR. For example, if FEE_DIVISOR is 10000, and one wants 13% of the total fee to go to the DEX, one must set protocol_fee_fraction = 0.13*10000 = 1300. In such case, if a swap is performed on a level with—for example, 0.2% total fee rate—and the total amount paid by the trader is 10,0000 tokens, then the total charged fee is 2,000 tokens, out of which 260 tokens go to the DEX, and the rest 1,740 tokens are distributed among the LPs.

  • fee_rates: Total fee rates on each level, including protocol and LP fees. Specified in units of 1/FEE_DIVISOR. For example, if FEE_DIVISOR is 10,000, and one wants to set fee rates to 0.01%, 0.02%, 0.04%, 0.08%, 0.16%, 0.32%, 0.64%, 1.28%, on levels 0-7 correspondingly, then one must set fee_rates = [1, 2, 4, 8, 16, 32, 64, 128]


pub fn metadata(&self) -> ContractMetadata

pub fn get_deposits(&self, account_id: &AccountId) -> HashMap<AccountId, U128>

Returns balances of the deposits for a given user outside of any pools. Returns an empty list if no tokens are deposited.


pub fn get_deposit(&self, account_id: &AccountId, token_id: &AccountId) -> U128 {

Returns the balance of the deposit for a given user outside of any pools.


pub fn get_verified_tokens(&self) -> Vec<AccountId>

Get ordered allowed tokens list.


pub fn get_user_tokens(&self, account_id: &AccountId) -> Vec<AccountId>

Get specific user tokens.


pub fn get_pool_info(&self, tokens: Pair<TokenId>) -> Option<PoolInfo>

pub fn get_user_storage_state(&self, account_id: &AccountId) -> Option<RefStorageState>

Get a user's storage deposit and needed in the account of the current version


pub fn get_version(&self) -> VersionInfo

#[payable]
pub fn register_tokens(&mut self, token_ids: &Vec<AccountId>)

Registers a given token in the user's account deposit. Fails if not enough balance on this account to cover storage.


#[payable]
pub fn unregister_tokens(&mut self, token_ids: &Vec<AccountId>)

Unregister a given token from a user's account deposit. Panics if the balance of any given token is not zero.


pub fn token_register_of(&self, account_id: &AccountId, token_id: &AccountId) -> bool

#[payable]
pub fn withdraw(
&mut self,
token_id: AccountId,
amount: U128,
unregister: Option<bool>,
) -> Promise

Withdraws a given token from the deposits of a given user. A zero amount means to withdraw all in the user's inner account. Optional unregister tries to remove the record of this token from AccountDeposit for the given user. Unregister fails if the left-over balance is not zero.


#[private]
pub fn exchange_callback_post_withdraw(
&mut self,
token_id: &AccountId,
sender_id: &AccountId,
amount: U128,
)

pub fn get_owner(&self) -> AccountId

Get the owner of this account.


#[payable]
pub fn extend_verified_tokens(&mut self, tokens: Vec<TokenId>)

Extend verified tokens with new tokens. Only can be called by an owner.


#[payable]
pub fn remove_verified_tokens(&mut self, tokens: Vec<TokenId>)

Remove a verified token. Only can be called by an owner.


#[payable]
pub fn extend_guard_accounts(&mut self, accounts: Vec<AccountId>)

Extend guard accounts with new accounts. Only can be called by an owner.


#[payable]
pub fn remove_guard_accounts(&mut self, accounts: Vec<AccountId>)

Remove guard accounts. Only can be called by an owner.


#[payable]
pub fn suspend_payable_api(&mut self)

Suspend payable API calls. It can be done by an owner or by guards.


#[payable]
pub fn resume_payable_api(&mut self)

Resume payable API calls. It can be done by an owner or by guards.


#[payable]
pub fn set_protocol_fee_fraction(&mut self, protocol_fee_fraction: BasisPoints)

Fraction of the fee which goes to the DEX out of the total fee charged in swaps. In units of 1/FEE_DIVISOR.


#[payable]
pub fn withdraw_owner_token(&mut self, token_id: AccountId, amount: U128) -> Promise

Withdraw an owner's inner account token to the owner's wallet. The owner's inner account must be prepared in advance.


#[payable]
pub fn execute_actions(&mut self, actions: &Vec<Action>) -> ActionResult

Executes a generic set of actions.


#[payable]
pub fn swap_exact_in(
&mut self,
tokens: &Vec<AccountId>,
amount_in: U128,
min_amount_out: U128,
) -> AmountInOut

Execute a set of swap actions between pools.


#[payable]
pub fn swap_exact_out(
&mut self,
tokens: &Vec<AccountId>,
amount_out: U128,
max_amount_in: U128,
) -> AmountInOut

#[payable]
pub fn open_position(
&mut self,
token_a: &AccountId,
token_b: &AccountId,
fee_rate: dex::BasisPoints,
position: PositionInit,
) -> (U64, U128, U128, f64)

Open a new position—for example, deposit tokens in the pool as a liquidity provider. Tokens must be deposited in the ratio of the current spot price on the current fee level. As the actual spot price may slip, the caller has to specify the ranges of token_a and token_b amounts to be deposited.

  • token_a: the first token in the pool; tokens may be in arbitrary order.
  • token_b: the second token in the pool; tokens may be in arbitrary order.
  • fee: fee rate in units of 1/FEE_DIVISOR.
  • position: currently, only FullRangePosition is supported, that is the range of token amounts to be deposited. [TODO: provide example JSON.]

The attached NEAR must be enough to cover the added storage. If a pool doesn't exist, it is implicitly created. In such case, more attached NEAR is required. As a pool can never be deleted, the NEAR deposited for pool storage can not be withdrawn.

Returns:

  • position_id
  • An amount of token_a
  • An amount of token b
  • Accounted liquidity

:::Note

The actual accounted position's liquidity may be smaller sqrt(amount_a, amount_b).

:::


#[payable]
pub fn close_position(&mut self, position_id: U64)

#[payable]
pub fn withdraw_fee(&mut self, position_id: U64) -> Pair<U128>

pub fn get_position_info(&self, position_id: U64) -> PositionInfo

Structures

pub struct AmountInOut {
pub amount_in: U128,
pub amount_out: U128,
}
pub enum ActionResult {
None,
/// Amount of token was received.
Amount(U128),
}
pub struct ContractMetadata {
/// Account that is allowed to change DEX configuration and withdraw protocol fee.
/// Normally it is the account with the governance smart contract.
pub owner: AccountId,

/// Number of existing pools.
pub pool_count: u64,

/// Fraction of fee which goes to DEX.
pub protocol_fee_fraction: BasisPoints,

/// Fee rate scaled up by fee_divisor.
pub fee_rates: dex::latest::RawFeeLevelsArray<BasisPoints>,

/// Scale factor for the fee rates and protocol fee fraction.
pub fee_divisor: BasisPoints,
}
pub struct RefStorageState {
pub deposit: U128,
pub usage: U128,
}
pub struct PositionInit {
pub amount_ranges: (MinMax, MinMax),
pub ticks_range: (Option<i32>, Option<i32>),
}
pub struct MinMax {
pub min: U128,
pub max: U128,
}
pub struct PositionInfo {
pub tokens_ids: [TokenId; 2],
pub balance: [U128; 2],
pub range_ticks: [Option<u32>; 2], // TODO: Replace u32 with `Tick` when concentrated-liquidity is merged.
#[serde(with = "super::utils::serde_as_str")]
pub liquidity_share: f64,
pub reward_since_last_withdraw: [U128; 2],
pub reward_since_creation: [U128; 2],
#[serde(with = "super::utils::serde_as_str")]
pub init_sqrt_price: f64,
}
pub struct PoolInfo {
/// Total amounts of tokens in the pool: sum of all positions and collected fees (LP and protocol).
pub total_reserves: (U128, U128),

/// Total amount of tokens locked in the pool (in positions)
pub position_reserves: (U128, U128),

/// Square root of the spot price on each of the fee levels, scaled by 2**64.
/// The value is approximate, as interlally a different representation is used.
/// If level is empty hence the price is undefined, the returned value is zero.
pub sqrt_spot_prices: dex::latest::RawFeeLevelsArray<U128>,

/// Liquidity on each of the fee levels.
/// The value is approximate, as interlally a different representation is used.
pub liquidities: dex::latest::RawFeeLevelsArray<U128>,

/// Fee rate scaled up by fee_divisor.
pub fee_rates: dex::latest::RawFeeLevelsArray<BasisPoints>, // TODO: consider removing, as it is global to DEX

/// Scale factor for the fee levels.
pub fee_divisor: BasisPoints,
}