1
+ // SPDX-License-Identifier: MIT
2
+
3
+ pragma solidity >= 0.5.0 ;
4
+
5
+ import '@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol ' ;
6
+
7
+ import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol " ;
8
+
9
+ library UniSushiV2Library {
10
+ using SafeMath for uint ;
11
+
12
+ // returns sorted token addresses, used to handle return values from pairs sorted in this order
13
+ function sortTokens (address tokenA , address tokenB ) internal pure returns (address token0 , address token1 ) {
14
+ require (tokenA != tokenB, 'UniswapV2Library: IDENTICAL_ADDRESSES ' );
15
+ (token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
16
+ require (token0 != address (0 ), 'UniswapV2Library: ZERO_ADDRESS ' );
17
+ }
18
+
19
+ // fetches and sorts the reserves for a pair
20
+ function getReserves (address pair , address tokenA , address tokenB ) internal view returns (uint reserveA , uint reserveB ) {
21
+ (address token0 ,) = sortTokens (tokenA, tokenB);
22
+ (uint reserve0 , uint reserve1 ,) = IUniswapV2Pair (pair).getReserves ();
23
+ (reserveA, reserveB) = tokenA == token0 ? (reserve0, reserve1) : (reserve1, reserve0);
24
+ }
25
+
26
+ // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset
27
+ function quote (uint amountA , uint reserveA , uint reserveB ) internal pure returns (uint amountB ) {
28
+ require (amountA > 0 , 'UniswapV2Library: INSUFFICIENT_AMOUNT ' );
29
+ require (reserveA > 0 && reserveB > 0 , 'UniswapV2Library: INSUFFICIENT_LIQUIDITY ' );
30
+ amountB = amountA.mul (reserveB) / reserveA;
31
+ }
32
+
33
+ // given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset
34
+ function getAmountOut (uint amountIn , uint reserveIn , uint reserveOut ) internal pure returns (uint amountOut ) {
35
+ require (amountIn > 0 , 'UniswapV2Library: INSUFFICIENT_INPUT_AMOUNT ' );
36
+ require (reserveIn > 0 && reserveOut > 0 , 'UniswapV2Library: INSUFFICIENT_LIQUIDITY ' );
37
+ uint amountInWithFee = amountIn.mul (997 );
38
+ uint numerator = amountInWithFee.mul (reserveOut);
39
+ uint denominator = reserveIn.mul (1000 ).add (amountInWithFee);
40
+ amountOut = numerator / denominator;
41
+ }
42
+
43
+ // given an output amount of an asset and pair reserves, returns a required input amount of the other asset
44
+ function getAmountIn (uint amountOut , uint reserveIn , uint reserveOut ) internal pure returns (uint amountIn ) {
45
+ require (amountOut > 0 , 'UniswapV2Library: INSUFFICIENT_OUTPUT_AMOUNT ' );
46
+ require (reserveIn > 0 && reserveOut > 0 , 'UniswapV2Library: INSUFFICIENT_LIQUIDITY ' );
47
+ uint numerator = reserveIn.mul (amountOut).mul (1000 );
48
+ uint denominator = reserveOut.sub (amountOut).mul (997 );
49
+ amountIn = (numerator / denominator).add (1 );
50
+ }
51
+
52
+ // performs chained getAmountOut calculations on any number of pairs
53
+ function getAmountsOut (address factory , uint amountIn , address [] memory path ) internal view returns (uint [] memory amounts ) {
54
+ require (path.length >= 2 , 'UniswapV2Library: INVALID_PATH ' );
55
+ amounts = new uint [](path.length );
56
+ amounts[0 ] = amountIn;
57
+ for (uint i; i < path.length - 1 ; i++ ) {
58
+ (uint reserveIn , uint reserveOut ) = getReserves (factory, path[i], path[i + 1 ]);
59
+ amounts[i + 1 ] = getAmountOut (amounts[i], reserveIn, reserveOut);
60
+ }
61
+ }
62
+
63
+ // performs chained getAmountIn calculations on any number of pairs
64
+ function getAmountsIn (address factory , uint amountOut , address [] memory path ) internal view returns (uint [] memory amounts ) {
65
+ require (path.length >= 2 , 'UniswapV2Library: INVALID_PATH ' );
66
+ amounts = new uint [](path.length );
67
+ amounts[amounts.length - 1 ] = amountOut;
68
+ for (uint i = path.length - 1 ; i > 0 ; i-- ) {
69
+ (uint reserveIn , uint reserveOut ) = getReserves (factory, path[i - 1 ], path[i]);
70
+ amounts[i - 1 ] = getAmountIn (amounts[i], reserveIn, reserveOut);
71
+ }
72
+ }
73
+ }
0 commit comments