Slope Logo
Skip to main content

The synth-pool Contract

The synth-pool contract is the core of the SLOPE protocol. It is a StableSwap AMM designed to facilitate low-slippage trades between two pegged assets. This document provides a detailed overview of its architecture, functions, and the underlying mathematics.

Overview

The contract implements the StableSwap invariant, which is a hybrid of the constant product and constant sum formulas. This allows it to offer very low slippage for trades between assets that are expected to have a 1:1 price ratio, while still being able to handle significant price deviations.

The contract is designed to be used with two tokens, referred to as token_a and token_b. It also includes a mechanism for collecting fees, which are split between liquidity providers and the protocol administrator.

Storage

The contract uses the following storage variables:

  • /coins/{index}: Stores the AlkaneId of the two tokens in the pool.
  • /A: The amplification parameter, which controls the "flatness" of the bonding curve.
  • /fee: The fee charged on swaps, scaled by 10^10.
  • /admin_fee: The portion of the fee that is allocated to the protocol administrator, scaled by 10^10.
  • /owner: The AlkaneId of the contract owner.
  • /balances/{index}: The balance of each token in the pool.
  • /admin_balances/{index}: The balance of admin fees collected for each token.
  • /total_supply: The total supply of LP tokens.
  • /balance/{owner}: The balance of LP tokens for a given owner.

Core Mathematical Functions

The core logic of the StableSwap invariant is implemented in the math.rs file.

get_D(xp: &[U256; 2], amp: U256) -> Result<U256>

This function calculates the D invariant, which is a measure of the total value locked in the pool. It iteratively solves the following equation:

A * sum(x_i) * n**n + D = A * D * n**n + D**(n+1) / (n**n * prod(x_i))

Where:

  • A is the amplification parameter.
  • x_i is the balance of each token.
  • n is the number of tokens (2 in this case).

get_y(i: usize, j: usize, x: U256, xp: &[U256; 2], amp: U256, D: U256) -> Result<U256>

This function calculates the amount of token j that will be received when swapping x amount of token i. It solves a quadratic equation to find the new balance of token j that maintains the D invariant.

get_y_D(A: U256, i: usize, xp: &[U256; 2], D: U256) -> Result<U256>

This function is similar to get_y, but it calculates the new balance of token i given a new value for D. This is used when removing liquidity from the pool.

Functions

The contract exposes the following functions via the SynthPoolMessage enum:

InitPool (opcode 0)

Initializes the pool with the two tokens, the amplification parameter, fees, and the owner.

  • token_a: The AlkaneId of the first token.
  • token_b: The AlkaneId of the second token.
  • A: The amplification parameter.
  • fee: The swap fee, scaled by 10^10.
  • admin_fee: The admin fee, scaled by 10^10.
  • owner: The AlkaneId of the contract owner.

AddLiquidity (opcode 1)

Adds liquidity to the pool. The caller must send the two tokens to the contract. The contract will then mint LP tokens and send them to the caller.

  • min_mint_amount: The minimum amount of LP tokens that the caller is willing to receive.

RemoveLiquidity (opcode 2)

Removes liquidity from the pool in a balanced way. The caller must send LP tokens to the contract. The contract will then burn the LP tokens and send the corresponding amounts of the two underlying tokens to the caller.

  • min_amounts: The minimum amounts of each token that the caller is willing to receive.

RemoveLiquidityOneCoin (opcode 3)

Removes liquidity from the pool by withdrawing only one of the two tokens.

  • i: The index of the token to withdraw (0 or 1).
  • min_amount: The minimum amount of the token that the caller is willing to receive.

RemoveLiquidityImbalance (opcode 4)

Removes liquidity from the pool in an imbalanced way. The caller specifies the amounts of each token to withdraw.

  • amounts: The amounts of each token to withdraw.
  • max_burn_amount: The maximum amount of LP tokens that the caller is willing to burn.

Swap (opcode 5)

Swaps one token for another.

  • j: The index of the token to receive (0 or 1).
  • min_dy: The minimum amount of the token that the caller is willing to receive.

ClaimAdminFees (opcode 10)

Allows the contract owner to claim the accumulated admin fees.

GetVirtualPrice (opcode 100)

Returns the virtual price of the LP token, which is a measure of its value relative to the underlying tokens.

GetBalances (opcode 101)

Returns the balances of the two tokens in the pool.

GetA (opcode 102)

Returns the amplification parameter A.