97 lines
4.0 KiB
Solidity
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);
|
|
}
|
|
}
|