//规定版本
pragma solidity >=0.5.0;
//导入Pair接口
import '@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol';
//导入浮点库,什么作用?
import '@uniswap/lib/contracts/libraries/FixedPoint.sol';
//一个记录着对计算平均价格的预言机提供了一些有帮助的方法的库
// library with helper methods for oracles that are concerned with computing average prices
library UniswapV2OracleLibrary {
using FixedPoint for *;
//辅助函数,返回当前区块时间,在uint32的范围内
// helper function that returns the current block timestamp within the range of uint32, i.e. [0, 2**32 - 1]
function currentBlockTimestamp() internal view returns (uint32) {
return uint32(block.timestamp % 2 ** 32);
}
//产生一个积累的价格,使用(反事实的)去节省gas以及避免同时的呼叫
// produces the cumulative price using counterfactuals to save gas and avoid a call to sync.
//提交一个交易对,返回两个代币的累计价格、当前区块时间戳
function currentCumulativePrices(
address pair
) internal view returns (uint price0Cumulative, uint price1Cumulative, uint32 blockTimestamp) {
//获取当前区块链时间戳
blockTimestamp = currentBlockTimestamp();
//获取交易对中代币的累计价格
price0Cumulative = IUniswapV2Pair(pair).price0CumulativeLast();
price1Cumulative = IUniswapV2Pair(pair).price1CumulativeLast();
//自pair最新一次更新之后,如果时间已经流过,仿制累计的价格数值
// if time has elapsed since the last update on the pair, mock the accumulated price values
//获取交易对的储备量、最新时间戳
(uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast) = IUniswapV2Pair(pair).getReserves();
//若记录的最新时间戳与当前时间戳不一致
if (blockTimestampLast != blockTimestamp) {
//基础溢出已被考虑
// subtraction overflow is desired
//经过的时间 = 当前时间 - 上次更新时间
uint32 timeElapsed = blockTimestamp - blockTimestampLast;
//加法溢出已被考虑
// addition overflow is desired
//对价格进行累计,依旧不明白为什么要累计此值
//fraction()用于提升除法精度,函数调用后返回的是一个结构体,
//需要通过._x的方式获取其存储的值,在本合约下面附上FixedPoint.sol
// counterfactual
price0Cumulative += uint(FixedPoint.fraction(reserve1, reserve0)._x) * timeElapsed;
// counterfactual
price1Cumulative += uint(FixedPoint.fraction(reserve0, reserve1)._x) * timeElapsed;
}
}
}
//以下是FixedPoint.sol
pragma solidity >=0.4.0;
// a library for handling binary fixed point numbers (https://en.wikipedia.org/wiki/Q_(number_format))
library FixedPoint {
// range: [0, 2**112 - 1]
// resolution: 1 / 2**112
struct uq112x112 {
uint224 _x;
}
// range: [0, 2**144 - 1]
// resolution: 1 / 2**112
struct uq144x112 {
uint _x;
}
uint8 private constant RESOLUTION = 112;
// encode a uint112 as a UQ112x112
function encode(uint112 x) internal pure returns (uq112x112 memory) {
return uq112x112(uint224(x) << RESOLUTION);
}
// encodes a uint144 as a UQ144x112
function encode144(uint144 x) internal pure returns (uq144x112 memory) {
return uq144x112(uint256(x) << RESOLUTION);
}
// divide a UQ112x112 by a uint112, returning a UQ112x112
function div(uq112x112 memory self, uint112 x) internal pure returns (uq112x112 memory) {
require(x != 0, 'FixedPoint: DIV_BY_ZERO');
return uq112x112(self._x / uint224(x));
}
// multiply a UQ112x112 by a uint, returning a UQ144x112
// reverts on overflow
function mul(uq112x112 memory self, uint y) internal pure returns (uq144x112 memory) {
uint z;
require(y == 0 || (z = uint(self._x) * y) / y == uint(self._x), "FixedPoint: MULTIPLICATION_OVERFLOW");
return uq144x112(z);
}
// returns a UQ112x112 which represents the ratio of the numerator to the denominator
// equivalent to encode(numerator).div(denominator)
function fraction(uint112 numerator, uint112 denominator) internal pure returns (uq112x112 memory) {
require(denominator > 0, "FixedPoint: DIV_BY_ZERO");
return uq112x112((uint224(numerator) << RESOLUTION) / denominator);
}
// decode a UQ112x112 into a uint112 by truncating after the radix point
function decode(uq112x112 memory self) internal pure returns (uint112) {
return uint112(self._x >> RESOLUTION);
}
// decode a UQ144x112 into a uint144 by truncating after the radix point
function decode144(uq144x112 memory self) internal pure returns (uint144) {
return uint144(self._x >> RESOLUTION);
}
}