tornado-contracts/contracts/Governance/libraries/UniswapV3OracleHelper.sol
2024-03-29 21:52:45 +00:00

97 lines
4.0 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.6.12;
import { OracleLibrary } from "../Uniswap/v3-periphery/contracts/libraries/OracleLibrary.sol";
import { IUniswapV3Factory } from "../Uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol";
import { LowGasSafeMath } from "../Uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol";
interface IERC20Decimals {
function decimals() external view returns (uint8);
}
library UniswapV3OracleHelper {
using LowGasSafeMath for uint256;
IUniswapV3Factory internal constant UniswapV3Factory = IUniswapV3Factory(0x1F98431c8aD98523631AE4a59f267346ea31F984);
address internal constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
uint256 internal constant RATIO_DIVIDER = 1e18;
/**
* @notice This function should return the price of baseToken in quoteToken, as in: quote/base (WETH/TORN)
* @dev uses the Uniswap written OracleLibrary "getQuoteAtTick", does not call external libraries,
* uses decimals() for the correct power of 10
* @param baseToken token which will be denominated in quote token
* @param quoteToken token in which price will be denominated
* @param fee the uniswap pool fee, pools have different fees so this is a pool selector for our usecase
* @param period the amount of seconds we are going to look into the past for the new token price
* @return returns the price of baseToken in quoteToken
* */
function getPriceOfTokenInToken(
address baseToken,
address quoteToken,
uint24 fee,
uint32 period
) internal view returns (uint256) {
uint128 base = uint128(10)**uint128(IERC20Decimals(quoteToken).decimals());
if (baseToken == quoteToken) return base;
else
return
OracleLibrary.getQuoteAtTick(
OracleLibrary.consult(UniswapV3Factory.getPool(baseToken, quoteToken, fee), period),
base,
baseToken,
quoteToken
);
}
/**
* @notice This function should return the price of token in WETH
* @dev simply feeds WETH in to the above function
* @param token token which will be denominated in WETH
* @param fee the uniswap pool fee, pools have different fees so this is a pool selector for our usecase
* @param period the amount of seconds we are going to look into the past for the new token price
* @return returns the price of token in WETH
* */
function getPriceOfTokenInWETH(
address token,
uint24 fee,
uint32 period
) internal view returns (uint256) {
return getPriceOfTokenInToken(token, WETH, fee, period);
}
/**
* @notice This function should return the price of WETH in token
* @dev simply feeds WETH into getPriceOfTokenInToken
* @param token token which WETH will be denominated in
* @param fee the uniswap pool fee, pools have different fees so this is a pool selector for our usecase
* @param period the amount of seconds we are going to look into the past for the new token price
* @return returns the price of token in WETH
* */
function getPriceOfWETHInToken(
address token,
uint24 fee,
uint32 period
) internal view returns (uint256) {
return getPriceOfTokenInToken(WETH, token, fee, period);
}
/**
* @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
* @dev this is done as to always have good prices due to WETH-token pools mostly always having the most liquidity
* @param tokens array of tokens to get ratio for
* @param fees the uniswap pool FEES, since these are two independent tokens
* @param period the amount of seconds we are going to look into the past for the new token price
* @return returns the price of token[0] in token[1]
* */
function getPriceRatioOfTokens(
address[2] memory tokens,
uint24[2] memory fees,
uint32 period
) internal view returns (uint256) {
return
getPriceOfTokenInWETH(tokens[0], fees[0], period).mul(RATIO_DIVIDER) / getPriceOfTokenInWETH(tokens[1], fees[1], period);
}
}