/** *Submitted for verification at Etherscan.io on 2021-04-14 */ // SPDX-License-Identifier: MIT pragma solidity 0.6.12; /// @notice A library for performing overflow-/underflow-safe math, /// updated with awesomeness from of DappHub (https://github.com/dapphub/ds-math). library BoringMath { function add(uint256 a, uint256 b) internal pure returns (uint256 c) { require((c = a + b) >= b, "BoringMath: Add Overflow"); } function sub(uint256 a, uint256 b) internal pure returns (uint256 c) { require((c = a - b) <= a, "BoringMath: Underflow"); } function mul(uint256 a, uint256 b) internal pure returns (uint256 c) { require(b == 0 || (c = a * b) / b == a, "BoringMath: Mul Overflow"); } } interface IAggregator { function latestAnswer() external view returns (int256 answer); } interface IUniswapV2Pair { function totalSupply() external view returns (uint256); function getReserves() external view returns ( uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast ); } /// @title LPChainlinkOracleV1 /// @author BoringCrypto /// @notice Oracle used for getting the price of an LP token paired with ETH based on an token-ETH chainlink oracle with 18 decimals /// @dev Optimized version based on https://blog.alphafinance.io/fair-lp-token-pricing/ contract LPETHChainlinkOracleV1 is IAggregator { using BoringMath for uint256; IUniswapV2Pair public immutable pair; IAggregator public immutable tokenOracle; constructor(IUniswapV2Pair pair_, IAggregator tokenOracle_) public { pair = pair_; tokenOracle = tokenOracle_; } // credit for this implementation goes to // https://github.com/abdk-consulting/abdk-libraries-solidity/blob/master/ABDKMath64x64.sol function sqrt(uint256 x) internal pure returns (uint128) { if (x == 0) return 0; uint256 xx = x; uint256 r = 1; if (xx >= 0x100000000000000000000000000000000) { xx >>= 128; r <<= 64; } if (xx >= 0x10000000000000000) { xx >>= 64; r <<= 32; } if (xx >= 0x100000000) { xx >>= 32; r <<= 16; } if (xx >= 0x10000) { xx >>= 16; r <<= 8; } if (xx >= 0x100) { xx >>= 8; r <<= 4; } if (xx >= 0x10) { xx >>= 4; r <<= 2; } if (xx >= 0x8) { r <<= 1; } r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; // Seven iterations should be enough uint256 r1 = x / r; return uint128(r < r1 ? r : r1); } // Calculates the lastest exchange rate function latestAnswer() external view override returns (int256) { (uint256 reserve0, uint256 reserve1, ) = IUniswapV2Pair(pair).getReserves(); uint256 totalSupply = pair.totalSupply(); uint256 k = reserve0.mul(reserve1); uint256 ethValue = sqrt((k / 1e18).mul(uint256(tokenOracle.latestAnswer()))); uint256 totalValue = ethValue.mul(2); return int256(totalValue.mul(1e18) / totalSupply); } }