The process of placing a limit order starts from the LimitOrderManager contract where createLimitOrder() function is called.
/// @notice Function to create limitorder
/// @param pool pool address
/// @param tick limitorder tick
/// @param lowerOld tick below limitorder tick
/// @param upperOld tick above limitorder tick
/// @param native user wallet/vault
/// @param amountIn amount in
/// @param zeroForOne direction of limitorder
/// @return limitOrder Id
function createLimitOrder(
IConcentratedLiquidityPool pool,
int24 tick,
int24 lowerOld,
int24 upperOld,
bool native,
uint256 amountIn,
bool zeroForOne
) external payable returns (uint256) {
This function appears to be used to create a limit order on a concentrated liquidity pool. A limit order is an order to buy or sell a specific amount of an asset at a specified price or better. In this case, the order is for a specific tick value on a liquidity pool. The tick value represents the price of the asset. The lowerOld
and upperOld
parameters represent the tick values that are below and above the specified tick value, respectively. The native
parameter specifies whether the token is native or not. The amountIn
parameter represents the amount of the asset being bought or sold in the order, and the zeroForOne
parameter specifies the direction of the order (whether it is a buy or sell order). The function returns a limit order ID.
require(masterDeployer.pools(address(pool)), "INVALID_POOL");
require(amountIn != 0, "Amount:Zero");
The first require
statement is checking that the address
of the pool
parameter exists in the pools
mapping of the masterDeployer
contract. If it does not exist, the function will throw an error with the message "INVALID_POOL". The second require
statement is checking that the amountIn
parameter is not equal to zero. If it is zero, the function will throw an error with the message "Amount:Zero".
cachedPool = address(pool);
cachedMsgSender = msg.sender;
Then we store the address
of the pool
parameter in a cachedPool
variable and the msg.sender
in cachedMsgSender
variable.
(uint160 currentPoolPrice, ) = pool.getPriceAndNearestTicks();
uint160 sqrtpriceX96 = TickMath.getSqrtRatioAtTick(tick);
Here we call the getPriceAndNearestTicks()
function on the pool contract, which returns the current price of the pool.
Then we call the getSqrtRatioAtTick()
function on the TickMath
contract, passing it the tick
parameter. This function returns the sqrtpriceX96 at the given tick.
pool.createLimitOrder(tick, lowerOld, upperOld, amountIn, native, zeroForOne);
This line calls the createLimitOrder()
function on the pool contract, passing it the tick
, lowerOld
, upperOld
, amountIn
, native
, and zeroForOne
parameters.
uint256 amountOut;
if (zeroForOne) {
require(sqrtpriceX96 > currentPoolPrice, "ISO");
// amountOut = (amountIn * price) / 10**12;
// amountOut = FullMath.mulDiv(amountIn, price, 10**12);
amountOut = FullMath.mulDiv(amountIn, sqrtpriceX96, 2**96);
amountOut = FullMath.mulDiv(amountOut, sqrtpriceX96, 2**96);
} else {
require(sqrtpriceX96 < currentPoolPrice, "IBO");
// amountOut = (amountIn * 10**12) / price;
amountOut = FullMath.mulDiv(amountIn, 2**96, sqrtpriceX96);
amountOut = FullMath.mulDiv(amountOut, 2**96, sqrtpriceX96);
}
// amountOut = amountOut / 10**6;
limitOrderId++;
limitOrderToken.mint(msg.sender, limitOrderId);
Here we declare the amountOut
variable first. Then, we check the value of the zeroForOne
parameter. If it is true
, it checks that the sqrtpriceX96 is greater than the current pool price and calculates amountOut
as the product of amountIn
, sqrtpriceX96, and sqrtpriceX96, divided by 2 to the power of 96. If zeroForOne
is false
, it does the opposite: it checks that sqrtpriceX96 is less than the current pool price and calculates amountOut
as the product of amountIn
and 2 to the power of 96, divided by sqrtpriceX96 and sqrtpriceX96.