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