feat(libraries): add router quoting and reserve helpers

This commit is contained in:
dualfroz committed 2026-08-26 14:28:00 +02:00
1 parent d5887a782e
commit 3c6d80aabb
1 file changed
+92
+92
View File
@@ -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);
}
}
}