yield-contract/contracts/logics/exchangeRate/priceFeed.sol
2020-09-12 04:33:29 +05:30

147 lines
4.7 KiB
Solidity

pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;
interface ChainLinkInterface {
function latestAnswer() external view returns (int256);
function decimals() external view returns (uint256);
}
interface IndexInterface {
function master() external view returns (address);
}
interface TokenInterface {
function decimals() external view returns (uint);
}
import { DSMath } from "../../libs/safeMath.sol";
contract Basic is DSMath {
address public constant instaIndex = 0x2971AdFa57b20E5a416aE5a708A8655A9c74f723;
address public constant ethAddr = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
modifier isChief {
require(
IndexInterface(instaIndex).master() == msg.sender, "not-Chief");
_;
}
event LogAddChainLinkMapping(
address tokenSymbol,
address chainlinkFeed
);
event LogRemoveChainLinkMapping(
address tokenSymbol,
address chainlinkFeed
);
struct FeedData {
address feedAddress;
uint multiplier;
}
mapping (address => FeedData) public chainLinkMapping;
function convertPrice(uint price, uint multiplier) internal pure returns (uint) {
return price * (10 ** multiplier);
}
function _addChainLinkMapping(
address token,
address chainlinkFeed
) internal {
require(token != address(0), "token-not-vaild");
require(chainlinkFeed != address(0), "chainlinkFeed-not-vaild");
require(chainLinkMapping[token].feedAddress == address(0), "chainlinkFeed-already-added");
uint tokenDec = token == ethAddr ? 18 : TokenInterface(token).decimals();
uint feedDec = ChainLinkInterface(chainlinkFeed).decimals();
chainLinkMapping[token].feedAddress = chainlinkFeed;
chainLinkMapping[token].multiplier = sub(36, add(tokenDec, feedDec));
emit LogAddChainLinkMapping(token, chainlinkFeed);
}
function _removeChainLinkMapping(address token) internal {
require(token != address(0), "token-not-vaild");
require(chainLinkMapping[token].feedAddress != address(0), "chainlinkFeed-not-added-yet");
emit LogRemoveChainLinkMapping(token, chainLinkMapping[token].feedAddress);
delete chainLinkMapping[token];
}
function addChainLinkMapping(
address[] memory tokens,
address[] memory chainlinkFeeds
) public isChief {
require(tokens.length == chainlinkFeeds.length, "lenght-not-same");
for (uint i = 0; i < tokens.length; i++) {
_addChainLinkMapping(tokens[i], chainlinkFeeds[i]);
}
}
function removeChainLinkMapping(address[] memory tokens) public isChief {
for (uint i = 0; i < tokens.length; i++) {
_removeChainLinkMapping(tokens[i]);
}
}
}
contract Resolver is Basic {
function getPrices(address[] memory tokens)
public
view
returns (
uint[] memory tokensPriceInETH
) {
tokensPriceInETH = new uint[](tokens.length);
for (uint i = 0; i < tokens.length; i++) {
if (tokens[i] != ethAddr) {
FeedData memory feedData = chainLinkMapping[tokens[i]];
ChainLinkInterface feedContract = ChainLinkInterface(feedData.feedAddress);
require(address(feedContract) != address(0), "price-not-found");
tokensPriceInETH[i] = convertPrice(uint(feedContract.latestAnswer()), feedData.multiplier);
} else {
tokensPriceInETH[i] = 10 ** 18;
}
}
}
function getPrice(address token)
public
view
returns (
uint tokenPriceInETH
) {
if (token != ethAddr) {
FeedData memory tokenFeedData = chainLinkMapping[token];
ChainLinkInterface tokenFeed = ChainLinkInterface(tokenFeedData.feedAddress);
require(address(tokenFeed) != address(0), "price-not-found");
tokenPriceInETH = convertPrice(uint(tokenFeed.latestAnswer()), tokenFeedData.multiplier);
} else {
tokenPriceInETH = 10 ** 18;
}
}
function getEthPrice()
public
view
returns (
uint ethPriceInUsd
) {
FeedData memory ethFeedData = chainLinkMapping[ethAddr];
ChainLinkInterface ethFeed = ChainLinkInterface(ethFeedData.feedAddress);
ethPriceInUsd = convertPrice(uint(ethFeed.latestAnswer()), ethFeedData.multiplier);
}
}
contract ChainLinkPriceFeed is Resolver {
constructor (address[] memory tokens, address[] memory chainlinkFeeds) public {
require(tokens.length == chainlinkFeeds.length, "Lenght-not-same");
for (uint i = 0; i < tokens.length; i++) {
_addChainLinkMapping(tokens[i], chainlinkFeeds[i]);
}
}
}