Skip to main content
A pool in this context is the medium through which users can exchange 2 different assets. In this case, these 2 assets are a pair of tokens where one is the collateral ERC20 token (aka y-axis token) and the other one is the x-axis ERC20 token. The following are the technical aspects of a pool in this product: See Pool.sol.

Overview

Assumptions

  • The pool is the original source for all x-tokens: it is assumed that the pool is the only source for originally getting x-tokens. Other markets such as constant-product AMMs can be used once the tokens are in circulation, but all tokens are originally purchased from the TBC.
  • The pool has been deployed through the factory: The factory automatically grants ownership of the pool to the deployer address. It also emits an event for the monitoring services to know when a pool has been deployed through it.

Ownership

The owner of the pool is granted initially to the deployer address. The pool uses the Ownable contract from OpenZeppelin. Therefore, transfer of ownership is always allowed to the current owner of the pool.

ALTBC Price Curve

The price curve of an ALTBC pool obeys what we call an adjustable linear token bonding curve. For an individual transaction, the price is calculated according to a linear formula. After each transaction, the line that defines the price is updated. The slope of this line changes based on the amount of x-tokens out in circulation. The effective price curve (how the price evolves over time, across many swaps) will be a concave curve that tends to stabilize the more tokens are sold.
animation of spot price
animation of y liquidity
price curve of adjustable linear TBC

Access Control

Owner

The owner of the pool contract is the only one who can execute the following privileged functions:
  • enableSwaps(bool _enable)
  • setLPFee(uint16 _fee)
  • addXSupply(uint256 _amount)
  • collectLPFees()
  • withdrawRevenue()

Protocol Fee Collector

The protocol fee collector account of the pool contract is the only one who can execute the following privileged functions:
  • setProtocolFee(uint16 _fee)
  • proposeProtocolFeeCollector()
There is a transitionary role which is the proposed protocol fee collector. This role is granted by the The protocol fee collector when calling proposeProtocolFeeCollector, and the only function that this transitionary role can call is:
  • confirmProtocolFeeCollector()
In which case, the account loses this role to now become the The protocol fee collector.

Security

The pool can be paused at any point by the owner account which means that all trading is disabled.

Revenue

As a consequence of the mathematical design, the pool will generate a small revenue per trade, independently of any fees set on the pool. The size of this revenue is correlated with the size of xMin, and grows over time with each trade. This revenue can be collected by the pool owner. Note that there may be remaining dust in the pool which will only be extracted when the pool is closed.

Artificial Price Manipulation Control

The mathematical design of this pool is such that it would be possible to artificially increase the price of an asset at no cost if we allowed x to be zero. At low values of x, it is also possible to increase the price of the asset at a potentially low cost by wash trading. To mitigate this possible price manipulation, the pool initiates with a synthetic trade. The amount of this synthetic trade is defined as xMin + w and is stored in the contract as xMax, where w is the initial xTokens added to the pool expressed in a packedFloat format.

Virtual Liquidity

This synthetic trade will cause the pool to have a virtual liquidity which is stored in the contract as wActive which is the difference between w and wInactive. This synthetic trade will also generate revenue for the pool which will be accumulated as dust in the pool.

Usage

Deployment

To deploy a pool please follow the guidelines in the factory guideline.

Initialization

After deployment, it is necessary to do the following step:
  1. Add liquidity to the pool (see Managing Liquidity). Notice that initial liquidity is only necessary for the x-token since the y-token will be provided through swaps by users. The amount of liquidity provided will be equal to the totalSupply of the token.
The pool will start operating at xMin. See explanation below note: Each pool will start with a synthetic trade in order to prevent an artificial price increase. This synthetic trade at the beginning of a fresh pool will help negate a malicious user from increasing the price of xToken in the pool. This also allows for a pool owner to extract collateral dust that accrues throughout the lifetime of the pool. see the revenue equation here

Managing Fees

LP Fees

The liquidity-provider fees are a portion of the swap that would go towards the liquidity provider as a compensation for the service provided. In this pool, there can only be one liquidity provider who is the owner of the pool, and therefore, the liquidity-provider fees can be managed only by the owner of the contract. Here are the main features of the fees of the pool:
  • Fees can be updated at any time.
  • Fees can be 0.
  • Fees are expressed in basis points.
  • Fees can be 50% - protocol fees.
  • Fees are collected in the y-token.
  • Fees are kept inside the pool.
  • Fees can be collected by the owner of the NFT token ID that defines the position of the liquidity provider.
Fees can be managed through the following functions:

Protocol Fees

Protocol fees are a portion of each swap that will go towards the protocol as a compensation for its service provided. The management of the protocol fees is under complete control of the protocol and not of the owner of the pool. The following are the properties of the pool’s protocol fees:
  • Protocol fees can be updated at any time.
  • Protocol fees can be 0.
  • Protocol fees are expressed in basis points.
  • Protocol fees can be as high as 0.20%.
  • Protocol fees are collected in the y-token.
  • Protocol fees are kept inside the pool.
  • Protocol fees need a manual withdrawal by the protocol fee collector who then will receive the totality of the fees accumulated.

Protocol fee value

The protocol fee value can be set at any time only by the protocol fee collector account. The following functions are available to manage this value:

Protocol fee collector

The protocol fee collector account of the pool can be updated at any time. Only the protocol fee collector account can update this value. The following functions are available to manage this address:
Notice that the process of assigning a new protocol fee collector is a 2-step process in order to prevent human errors from setting the wrong address:
  1. The current protocol fee collector account proposes a new protocol fee collector address through the function proposeProtocolFeeCollector.
  2. The proposed protocol fee collector account then needs to call the confirmProtocolFeeCollector function to accept/confirm this role.

Revenue

Because of the mechanism to deter artificial price increase in a fresh pool, a synthetic trade is done when deploying a new pool. This new pool will start with its x at xMin. Therefore, the outstanding liquidity will always be x - xMin. This dust is accessible through the withdrawRevenue function, callable by the owner of the NFT token ID that defines the position of the liquidity provider.
note: The dust remaining in the pool as revenue will also be extracted when closing the pool

Managing Swaps

Swaps can be enabled and disabled. This functionality uses the standard Pausable contract found in projects like OpenZeppelin. To enable or disable swaps, use the following function:
The functions affected by a disabled-swap state are limited to:
  • swap()

Swaps

The main feature of the pool is that it allows swaps. Swaps are permissionless meaning that anybody can use this feature. A vital factor of a swap is price, for which there are three different functions that can be used. These functions will be explained in the following sections.

Spot price

In the context of a TBC AMM, spot price refers to the current price for buying 1 full token assuming a flat price for the whole token (no price difference between the first wei and the last wei of the purchased token).
Take into account that this is more of a theoretical price since in reality the price does change from the first wei to the last wei since this is a linear TBC, and therefore the price depends on the amount of x tokens sold by the pool (value of x). To know an exact price of a transaction, it is necessary to know exactly how much to swap. For this, use the functions of the coming section. 📝 WEI is being used to refer to the atomic unit of the ERC20 token. We find this terminology more intuitive since the decimals of ERC20 mimic the relationship between Ether and WEI but without a defined term for the atomic unit like we get for ETH

Swap simulations

The pool offers two ways of simulating a swap to know either how much is needed to get a certain amount of tokens out of the pool (the output is known and the input is requested), or to know how much is going to be obtained from a swap after a certain amount of tokens are provided to the pool (the input is known and the output is requested). This is useful since this lets the user know the actual cost of a swap, and it can also give the user a point of reference to tell the pool how to calculate the slippage of the swap (in reality, the frontend usually handles this last step). To simulate a swap, these two functions are available:
Notice that in both functions we have a lpFeeAmount and the protocolFeeAmount values which are returned alongside the amountIn/amountOut (main returned value). These values are only informational as they have already been factored in the main returned value. Therefore, there is no need to carry out any addition/subtraction to use the amountIn/amountOut in the swap function.

Slippage

Slippage is defined as an absolute deviation value between an expected outcome and the actual outcome expressed as a minimum token result from the swap. This slippage calculation is done off-chain. The slippage check is used to ensure the outcome of the swap is greater than or equal to the minimum expected. Traders can set their own slippage tolerance when initiating the swap (see next section).

Swaps

Use the following function to carry out a swap.
An important aspect to note is that the AMM expects the user to provide the amount of the token they’re selling and the expected minimum amount out. In instances where the user’s goal is to retrieve a specific amount out they can first use the ‘simSwapReversed’ function (defined above) to determine how much they’ll need to sell to the AMM to receive the desired amount.

Public Variables

The pool has many public variables that expose aspects such as the curve characterization, the pair tokens, the state of the curve, etc.:

Events

Please visit next page for Events.