library UniswapV2OracleLibrary {
    using FixedPoint for *;

    // 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);
    }

    // produces the cumulative price using counterfactuals to save gas and avoid a call to sync.
    function currentCumulativePrices(address pair, bool isToken0)
        internal
        view
        returns (uint256 priceCumulative, uint32 blockTimestamp)
    {
        blockTimestamp = currentBlockTimestamp();
        (
            uint112 reserve0,
            uint112 reserve1,
            uint32 blockTimestampLast
        ) = UniswapPair(pair).getReserves();
        if (isToken0) {
            priceCumulative = UniswapPair(pair).price0CumulativeLast();

            // if time has elapsed since the last update on the pair, mock the accumulated price values
            if (blockTimestampLast != blockTimestamp) {
                // subtraction overflow is desired
                uint32 timeElapsed = blockTimestamp - blockTimestampLast;
                // addition overflow is desired
                // counterfactual
                priceCumulative +=
                    uint256(FixedPoint.fraction(reserve1, reserve0)._x) *
                    timeElapsed;
            }
        } else {
            priceCumulative = UniswapPair(pair).price1CumulativeLast();
            // if time has elapsed since the last update on the pair, mock the accumulated price values
            if (blockTimestampLast != blockTimestamp) {
                // subtraction overflow is desired
                uint32 timeElapsed = blockTimestamp - blockTimestampLast;
                // addition overflow is desired
                // counterfactual
                priceCumulative +=
                    uint256(FixedPoint.fraction(reserve0, reserve1)._x) *
                    timeElapsed;
            }
        }
    }
}
// library with helper methods for oracles that are concerned with computing average prices
function currentBlockTimestamp() internal view returns (uint32) {
    return uint32(block.timestamp % 2**32);
}

// helper function that returns the current block timestamp within the range of uint32, i.e. [0, 2**32 - 1]