ORACLE
67 removals
Words removed | 261 |
Total words | 343 |
Words removed (%) | 76.09 |
82 lines
39 additions
Words added | 122 |
Total words | 204 |
Words added (%) | 59.80 |
61 lines
contract Oracle is Epoch {
contract Oracle is Operator {
using FixedPoint for *;
using SafeMath for uint256;
using SafeMath for uint256;
/* ========== STATE VARIABLES ========== */
// uniswap
address public token0;
address public token0;
address public token1;
address public token1;
IUniswapV2Pair public pair;
IPool public pair;
// oracle
uint32 public blockTimestampLast;
uint256 public price0CumulativeLast;
uint256 public price1CumulativeLast;
FixedPoint.uq112x112 public price0Average;
FixedPoint.uq112x112 public price1Average;
/* ========== CONSTRUCTOR ========== */
constructor(
constructor(IPool _pair) public {
IUniswapV2Pair _pair,
uint256 _period,
uint256 _startTime
) public Epoch(_period, _startTime, 0) {
pair = _pair;
pair = _pair;
token0 = pair.token0();
token0 = pair.token0();
token1 = pair.token1();
token1 = pair.token1();
price0CumulativeLast = pair.price0CumulativeLast(); // fetch the current accumulated price value (1 / 0)
uint256 reserve0;
price1CumulativeLast = pair.price1CumulativeLast(); // fetch the current accumulated price value (0 / 1)
uint256 reserve1;
uint112 reserve0;
(reserve0, reserve1, ) = pair.getReserves();
uint112 reserve1;
require(reserve0 != 0 && reserve1 != 0, "Oracle: No reserves");
(reserve0, reserve1, blockTimestampLast) = pair.getReserves();
require(reserve0 != 0 && reserve1 != 0, "Oracle: NO_RESERVES"); // ensure that there's liquidity in the pair
}
}
/* ========== MUTABLE FUNCTIONS ========== */
function update() external {
pair.sync();
/** @dev Updates 1-day EMA price from Uniswap. */
function update() external checkEpoch {
(uint256 price0Cumulative, uint256 price1Cumulative, uint32 blockTimestamp) = UniswapV2OracleLibrary.currentCumulativePrices(address(pair));
uint32 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired
if (timeElapsed == 0) {
// prevent divided by zero
return;
}
// overflow is desired, casting never truncates
// cumulative price is in (uq112x112 price * seconds) units so we simply wrap it after division by time elapsed
price0Average = FixedPoint.uq112x112(uint224((price0Cumulative - price0CumulativeLast) / timeElapsed));
price1Average = FixedPoint.uq112x112(uint224((price1Cumulative - price1CumulativeLast) / timeElapsed));
price0CumulativeLast = price0Cumulative;
price1CumulativeLast = price1Cumulative;
blockTimestampLast = blockTimestamp;
emit Updated(price0Cumulative, price1Cumulative);
}
}
// note this will always return 0 before update has been called successfully for the first time.
function consult(
function consult(address _token, uint256 _amountIn) external view returns (uint144 amountOut) {
address _token,
uint256 _amountIn
) external view returns (uint256 amountOut) {
if (_token == token0) {
if (_token == token0) {
amountOut = price0Average.mul(_amountIn).decode144();
amountOut = _quote(_token, _amountIn, 12);
} else {
} else {
require(_token == token1, "Oracle: INVALID_TOKEN");
require(_token == token1, "Oracle: Invalid token");
amountOut = price1Average.mul(_amountIn).decode144();
amountOut = _quote(_token, _amountIn, 12);
}
}
}
}
function twap(address _token, uint256 _amountIn) external view returns (uint144 _amountOut) {
function twap(
(uint256 price0Cumulative, uint256 price1Cumulative, uint32 blockTimestamp) = UniswapV2OracleLibrary.currentCumulativePrices(address(pair));
address _token,
uint32 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired
uint256 _amountIn
) external view returns (uint256 amountOut) {
if (_token == token0) {
if (_token == token0) {
_amountOut = FixedPoint.uq112x112(uint224((price0Cumulative - price0CumulativeLast) / timeElapsed)).mul(_amountIn).decode144();
amountOut = _quote(_token, _amountIn, 2);
} else if (_token == token1) {
} else {
_amountOut = FixedPoint.uq112x112(uint224((price1Cumulative - price1CumulativeLast) / timeElapsed)).mul(_amountIn).decode144();
require(_token == token1, "Oracle: Invalid token");
amountOut = _quote(_token, _amountIn, 2);
}
}
}
}
event Updated(uint256 price0CumulativeLast, uint256 price1CumulativeLast);
// Note the window parameter is removed as its always 1 (30min), granularity at 12 for example is (12 * 30min) = 6 hours
function _quote(
address tokenIn,
uint256 amountIn,
uint256 granularity // number of observations to query
) internal view returns (uint256 amountOut) {
uint256 observationLength = IPool(pair).observationLength();
require(
granularity <= observationLength,
"Oracle: Not enough observations"
);
uint256 price = IPool(pair).quote(tokenIn, amountIn, granularity);
amountOut = price;
}
}
}