Providing Liquidity
Introduction
When providing liquidity from a smart contract, the most important thing to keep in mind is that tokens deposited into a pool at any rate other than the current reserve ratio are vulnerable to being arbitraged. As an example, if the ratio of x:y in a pair is 10:2 (i.e. the price is 5), and someone naively adds liquidity at 5:2 (a price of 2.5), the contract will simply accept all tokens (changing the price to 3.75 and opening up the market to arbitrage), but only issue pool tokens entitling the sender to the amount of assets sent at the proper ratio, in this case 5:1. To avoid donating to arbitrageurs, it is imperative to add liquidity at the current price. Luckily, it's easy to ensure that this condition is met!
Using the Router
The easiest way to safely add liquidity to a pool is to use the router, which provides simple methods to safely add liquidity to a pool. If the liquidity is to be added to an BTC-20/BTC-20 pair, use addLiquidity.
These methods both require the caller to commit to a belief about the current price, which is encoded in the amount*Desired
parameters. Typically, it's fairly safe to assume that the current fair market price is around what the current reserve ratio is for a pair (because of arbitrage). So, if a user wants to add 1 BTCC to a pool, and the current USDT/WBTCC ratio of the pool is 200/1, it's reasonable to calculate that 200 USDT must be sent along with the BTCC, which is an implicit commitment to the price of 200 USDT/1 WBTCC. However, it's important to note that this must be calculated before the transaction is submitted. It is not safe to look up the reserve ratio from within a transaction and rely on it as a price belief, as this ratio can be cheaply manipulated to your detriment.
However, it is still possible to submit a transaction which encodes a belief about the price which ends up being wrong because of a larger change in the true market price before the transaction is confirmed. For that reason, it's necessary to pass an additional set of parameters which encode the caller's tolerance to price changes. These amount*Min
parameters should typically be set to percentages of the calculated desired price. So, at a 1% tolerance level, if our user sends a transaction with 1 BTCC and 200 USDT, amountETHMin
should be set to e.g. .99 BTCC, and amountTokenMin
should be set to 198 USDT. This means that, at worst, liquidity will be added at a rate between 198 USDT/1 BTCC and 202.02 USDT/1 BTCC (200 USDT/.99 BTCC).
Once the price calculations have been made, it's important to ensure that your contract a) controls at least as many tokens/BTCC as were passed as amount*Desired
parameters, and b) has granted approval to the router to withdraw this many tokens.
Last updated