feat(libraries): add router quoting and reserve helpers
This commit is contained in:
1 parent
d5887a782e
commit
3c6d80aabb
1 file changed
+92
@@ -0,0 +1,92 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity 0.8.36;
|
||||
|
||||
import {IFluxFactory} from "../interfaces/IFluxFactory.sol";
|
||||
import {IFluxPair} from "../interfaces/IFluxPair.sol";
|
||||
|
||||
/// @title Pricing and reserve helpers shared by the router.
|
||||
library FluxLibrary {
|
||||
function sortTokens(address tokenA, address tokenB) internal pure returns (address token0, address token1) {
|
||||
require(tokenA != tokenB, "FluxLibrary: IDENTICAL_ADDRESSES");
|
||||
(token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
|
||||
require(token0 != address(0), "FluxLibrary: ZERO_ADDRESS");
|
||||
}
|
||||
|
||||
function pairFor(address factory, address tokenA, address tokenB) internal view returns (address pair) {
|
||||
pair = IFluxFactory(factory).getPair(tokenA, tokenB);
|
||||
require(pair != address(0), "FluxLibrary: PAIR_NOT_FOUND");
|
||||
}
|
||||
|
||||
function getReserves(address factory, address tokenA, address tokenB)
|
||||
internal
|
||||
view
|
||||
returns (uint256 reserveA, uint256 reserveB)
|
||||
{
|
||||
(address token0,) = sortTokens(tokenA, tokenB);
|
||||
(uint112 reserve0, uint112 reserve1,) = IFluxPair(pairFor(factory, tokenA, tokenB)).getReserves();
|
||||
(reserveA, reserveB) =
|
||||
tokenA == token0 ? (uint256(reserve0), uint256(reserve1)) : (uint256(reserve1), uint256(reserve0));
|
||||
}
|
||||
|
||||
/// @notice Equal-value counterpart amount given current reserves.
|
||||
function quote(uint256 amountA, uint256 reserveA, uint256 reserveB) internal pure returns (uint256 amountB) {
|
||||
require(amountA > 0, "FluxLibrary: INSUFFICIENT_AMOUNT");
|
||||
require(reserveA > 0 && reserveB > 0, "FluxLibrary: INSUFFICIENT_LIQUIDITY");
|
||||
amountB = amountA * reserveB / reserveA;
|
||||
}
|
||||
|
||||
/// @notice Output for an exact input, 0.3% fee applied to the input.
|
||||
function getAmountOut(uint256 amountIn, uint256 reserveIn, uint256 reserveOut)
|
||||
internal
|
||||
pure
|
||||
returns (uint256 amountOut)
|
||||
{
|
||||
require(amountIn > 0, "FluxLibrary: INSUFFICIENT_INPUT_AMOUNT");
|
||||
require(reserveIn > 0 && reserveOut > 0, "FluxLibrary: INSUFFICIENT_LIQUIDITY");
|
||||
uint256 amountInWithFee = amountIn * 997;
|
||||
uint256 numerator = amountInWithFee * reserveOut;
|
||||
uint256 denominator = reserveIn * 1000 + amountInWithFee;
|
||||
amountOut = numerator / denominator;
|
||||
}
|
||||
|
||||
/// @notice Input required for an exact output, 0.3% fee applied to the input.
|
||||
function getAmountIn(uint256 amountOut, uint256 reserveIn, uint256 reserveOut)
|
||||
internal
|
||||
pure
|
||||
returns (uint256 amountIn)
|
||||
{
|
||||
require(amountOut > 0, "FluxLibrary: INSUFFICIENT_OUTPUT_AMOUNT");
|
||||
require(reserveIn > 0 && reserveOut > 0, "FluxLibrary: INSUFFICIENT_LIQUIDITY");
|
||||
uint256 numerator = reserveIn * amountOut * 1000;
|
||||
uint256 denominator = (reserveOut - amountOut) * 997;
|
||||
amountIn = numerator / denominator + 1;
|
||||
}
|
||||
|
||||
function getAmountsOut(address factory, uint256 amountIn, address[] memory path)
|
||||
internal
|
||||
view
|
||||
returns (uint256[] memory amounts)
|
||||
{
|
||||
require(path.length >= 2, "FluxLibrary: INVALID_PATH");
|
||||
amounts = new uint256[](path.length);
|
||||
amounts[0] = amountIn;
|
||||
for (uint256 i; i < path.length - 1; i++) {
|
||||
(uint256 reserveIn, uint256 reserveOut) = getReserves(factory, path[i], path[i + 1]);
|
||||
amounts[i + 1] = getAmountOut(amounts[i], reserveIn, reserveOut);
|
||||
}
|
||||
}
|
||||
|
||||
function getAmountsIn(address factory, uint256 amountOut, address[] memory path)
|
||||
internal
|
||||
view
|
||||
returns (uint256[] memory amounts)
|
||||
{
|
||||
require(path.length >= 2, "FluxLibrary: INVALID_PATH");
|
||||
amounts = new uint256[](path.length);
|
||||
amounts[amounts.length - 1] = amountOut;
|
||||
for (uint256 i = path.length - 1; i > 0; i--) {
|
||||
(uint256 reserveIn, uint256 reserveOut) = getReserves(factory, path[i - 1], path[i]);
|
||||
amounts[i - 1] = getAmountIn(amounts[i], reserveIn, reserveOut);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user