// SPDX-License-Identifier: MIT pragma solidity 0.6.12; // File @boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol@v1.2.1 // License-Identifier: MIT /// @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"); } function to128(uint256 a) internal pure returns (uint128 c) { require(a <= uint128(-1), "BoringMath: uint128 Overflow"); c = uint128(a); } function to64(uint256 a) internal pure returns (uint64 c) { require(a <= uint64(-1), "BoringMath: uint64 Overflow"); c = uint64(a); } function to32(uint256 a) internal pure returns (uint32 c) { require(a <= uint32(-1), "BoringMath: uint32 Overflow"); c = uint32(a); } } /// @notice A library for performing overflow-/underflow-safe addition and subtraction on uint128. library BoringMath128 { function add(uint128 a, uint128 b) internal pure returns (uint128 c) { require((c = a + b) >= b, "BoringMath: Add Overflow"); } function sub(uint128 a, uint128 b) internal pure returns (uint128 c) { require((c = a - b) <= a, "BoringMath: Underflow"); } } /// @notice A library for performing overflow-/underflow-safe addition and subtraction on uint64. library BoringMath64 { function add(uint64 a, uint64 b) internal pure returns (uint64 c) { require((c = a + b) >= b, "BoringMath: Add Overflow"); } function sub(uint64 a, uint64 b) internal pure returns (uint64 c) { require((c = a - b) <= a, "BoringMath: Underflow"); } } /// @notice A library for performing overflow-/underflow-safe addition and subtraction on uint32. library BoringMath32 { function add(uint32 a, uint32 b) internal pure returns (uint32 c) { require((c = a + b) >= b, "BoringMath: Add Overflow"); } function sub(uint32 a, uint32 b) internal pure returns (uint32 c) { require((c = a - b) <= a, "BoringMath: Underflow"); } } // File contracts/interfaces/IOracle.sol // License-Identifier: MIT interface IOracle { /// @notice Get the latest exchange rate. /// @param data Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle. /// For example: /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256)); /// @return success if no valid (recent) rate is available, return false else true. /// @return rate The rate of the requested asset / pair / pool. function get(bytes calldata data) external returns (bool success, uint256 rate); /// @notice Check the last exchange rate without any state changes. /// @param data Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle. /// For example: /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256)); /// @return success if no valid (recent) rate is available, return false else true. /// @return rate The rate of the requested asset / pair / pool. function peek(bytes calldata data) external view returns (bool success, uint256 rate); /// @notice Check the current spot exchange rate without any state changes. For oracles like TWAP this will be different from peek(). /// @param data Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle. /// For example: /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256)); /// @return rate The rate of the requested asset / pair / pool. function peekSpot(bytes calldata data) external view returns (uint256 rate); /// @notice Returns a human readable (short) name about this oracle. /// @param data Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle. /// For example: /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256)); /// @return (string) A human readable symbol name about this oracle. function symbol(bytes calldata data) external view returns (string memory); /// @notice Returns a human readable name about this oracle. /// @param data Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle. /// For example: /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256)); /// @return (string) A human readable name about this oracle. function name(bytes calldata data) external view returns (string memory); } // File contracts/oracles/ChainlinkOracle.sol // License-Identifier: MIT // Chainlink Aggregator interface IAggregator { function latestAnswer() external view returns (int256 answer); } contract ChainlinkOracleV2 is IOracle { using BoringMath for uint256; // Keep everything in uint256 // Calculates the lastest exchange rate // Uses both divide and multiply only for tokens not supported directly by Chainlink, for example MKR/USD function _get( address multiply, address divide, uint256 decimals ) internal view returns (uint256) { uint256 price = uint256(1e36); if (multiply != address(0)) { price = price.mul(uint256(IAggregator(multiply).latestAnswer())); } else { price = price.mul(1e18); } if (divide != address(0)) { price = price / uint256(IAggregator(divide).latestAnswer()); } return price / decimals; } function getDataParameter( address multiply, address divide, uint256 decimals ) public pure returns (bytes memory) { return abi.encode(multiply, divide, decimals); } // Get the latest exchange rate /// @inheritdoc IOracle function get(bytes calldata data) public override returns (bool, uint256) { (address multiply, address divide, uint256 decimals) = abi.decode(data, (address, address, uint256)); return (true, _get(multiply, divide, decimals)); } // Check the last exchange rate without any state changes /// @inheritdoc IOracle function peek(bytes calldata data) public view override returns (bool, uint256) { (address multiply, address divide, uint256 decimals) = abi.decode(data, (address, address, uint256)); return (true, _get(multiply, divide, decimals)); } // Check the current spot exchange rate without any state changes /// @inheritdoc IOracle function peekSpot(bytes calldata data) external view override returns (uint256 rate) { (, rate) = peek(data); } /// @inheritdoc IOracle function name(bytes calldata) public view override returns (string memory) { return "Chainlink"; } /// @inheritdoc IOracle function symbol(bytes calldata) public view override returns (string memory) { return "LINK"; } }