Line data Source code
1 : // SPDX-License-Identifier: MIT 2 : 3 : pragma solidity ^0.6.12; 4 : 5 : import { OracleLibrary } from "@uniswap/v3-periphery/contracts/libraries/OracleLibrary.sol"; 6 : import { IUniswapV3Factory } from "@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol"; 7 : import { LowGasSafeMath } from "@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol"; 8 : 9 : interface IERC20Decimals { 10 : function decimals() external view returns (uint8); 11 : } 12 : 13 : library UniswapV3OracleHelper { 14 : using LowGasSafeMath for uint256; 15 : 16 : IUniswapV3Factory internal constant UniswapV3Factory = IUniswapV3Factory(0x1F98431c8aD98523631AE4a59f267346ea31F984); 17 : address internal constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; 18 : uint256 internal constant RATIO_DIVIDER = 1e18; 19 : 20 : /** 21 : * @notice This function should return the price of baseToken in quoteToken, as in: quote/base (WETH/TORN) 22 : * @dev uses the Uniswap written OracleLibrary "getQuoteAtTick", does not call external libraries, 23 : * uses decimals() for the correct power of 10 24 : * @param baseToken token which will be denominated in quote token 25 : * @param quoteToken token in which price will be denominated 26 : * @param fee the uniswap pool fee, pools have different fees so this is a pool selector for our usecase 27 : * @param period the amount of seconds we are going to look into the past for the new token price 28 : * @return returns the price of baseToken in quoteToken 29 : * */ 30 : function getPriceOfTokenInToken( 31 : address baseToken, 32 : address quoteToken, 33 : uint24 fee, 34 : uint32 period 35 : ) internal view returns (uint256) { 36 0 : uint128 base = uint128(10)**uint128(IERC20Decimals(quoteToken).decimals()); 37 0 : if (baseToken == quoteToken) return base; 38 : else 39 0 : return 40 0 : OracleLibrary.getQuoteAtTick( 41 : OracleLibrary.consult(UniswapV3Factory.getPool(baseToken, quoteToken, fee), period), 42 : base, 43 : baseToken, 44 : quoteToken 45 : ); 46 : } 47 : 48 : /** 49 : * @notice This function should return the price of token in WETH 50 : * @dev simply feeds WETH in to the above function 51 : * @param token token which will be denominated in WETH 52 : * @param fee the uniswap pool fee, pools have different fees so this is a pool selector for our usecase 53 : * @param period the amount of seconds we are going to look into the past for the new token price 54 : * @return returns the price of token in WETH 55 : * */ 56 : function getPriceOfTokenInWETH( 57 : address token, 58 : uint24 fee, 59 : uint32 period 60 : ) internal view returns (uint256) { 61 0 : return getPriceOfTokenInToken(token, WETH, fee, period); 62 : } 63 : 64 : /** 65 : * @notice This function should return the price of WETH in token 66 : * @dev simply feeds WETH into getPriceOfTokenInToken 67 : * @param token token which WETH will be denominated in 68 : * @param fee the uniswap pool fee, pools have different fees so this is a pool selector for our usecase 69 : * @param period the amount of seconds we are going to look into the past for the new token price 70 : * @return returns the price of token in WETH 71 : * */ 72 : function getPriceOfWETHInToken( 73 : address token, 74 : uint24 fee, 75 : uint32 period 76 : ) internal view returns (uint256) { 77 0 : return getPriceOfTokenInToken(WETH, token, fee, period); 78 : } 79 : 80 : /** 81 : * @notice This function returns the price of token[0] in token[1], but more precisely and importantly the price ratio of the tokens in WETH 82 : * @dev this is done as to always have good prices due to WETH-token pools mostly always having the most liquidity 83 : * @param tokens array of tokens to get ratio for 84 : * @param fees the uniswap pool FEES, since these are two independent tokens 85 : * @param period the amount of seconds we are going to look into the past for the new token price 86 : * @return returns the price of token[0] in token[1] 87 : * */ 88 : function getPriceRatioOfTokens( 89 : address[2] memory tokens, 90 : uint24[2] memory fees, 91 : uint32 period 92 : ) internal view returns (uint256) { 93 0 : return 94 0 : getPriceOfTokenInWETH(tokens[0], fees[0], period).mul(RATIO_DIVIDER) / getPriceOfTokenInWETH(tokens[1], fees[1], period); 95 : } 96 : }