dsa-resolvers-deprecated/contracts/protocols/mainnet/instapool.sol
2021-04-13 10:27:09 +05:30

366 lines
12 KiB
Solidity

pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;
interface CTokenInterface {
function underlying() external view returns (address);
}
interface TokenInterface {
function balanceOf(address) external view returns (uint);
function decimals() external view returns (uint);
}
interface OrcaleComp {
function getUnderlyingPrice(address) external view returns (uint);
}
interface ComptrollerLensInterface {
function markets(address) external view returns (bool, uint, bool);
}
interface InstaMapping {
function cTokenMapping(address) external view returns (address);
}
interface ChainLinkInterface {
function latestAnswer() external view returns (int256);
function decimals() external view returns (uint256);
}
interface AaveInterface {
function getReserveConfigurationData(address _reserve)
external
view
returns (
uint256 ltv,
uint256 liquidationThreshold,
uint256 liquidationBonus,
address interestRateStrategyAddress,
bool usageAsCollateralEnabled,
bool borrowingEnabled,
bool stableBorrowRateEnabled,
bool isActive
);
}
interface AaveProviderInterface {
function getLendingPool() external view returns (address);
function getLendingPoolCore() external view returns (address);
function getPriceOracle() external view returns (address);
}
interface AavePriceInterface {
function getAssetPrice(address _asset) external view returns (uint256);
}
interface AaveCoreInterface {
function getReserveCurrentLiquidityRate(address _reserve) external view returns (uint256);
function getReserveCurrentVariableBorrowRate(address _reserve) external view returns (uint256);
function getReserveATokenAddress(address _reserve) external view returns (address);
}
interface VatLike {
function ilks(bytes32) external view returns (uint, uint, uint, uint, uint);
function dai(address) external view returns (uint);
function urns(bytes32, address) external view returns (uint, uint);
function gem(bytes32, address) external view returns (uint);
}
interface SpotLike {
function ilks(bytes32) external view returns (PipLike, uint);
}
interface PipLike {
function peek() external view returns (bytes32, bool);
}
interface InstaMcdAddress {
function manager() external view returns (address);
function vat() external view returns (address);
function jug() external view returns (address);
function spot() external view returns (address);
function pot() external view returns (address);
function getCdps() external view returns (address);
}
contract DSMath {
function add(uint x, uint y) internal pure returns (uint z) {
require((z = x + y) >= x, "math-not-safe");
}
function mul(uint x, uint y) internal pure returns (uint z) {
require(y == 0 || (z = x * y) / y == x, "math-not-safe");
}
uint constant WAD = 10 ** 18;
uint constant RAY = 10 ** 27;
function rmul(uint x, uint y) internal pure returns (uint z) {
z = add(mul(x, y), RAY / 2) / RAY;
}
function wmul(uint x, uint y) internal pure returns (uint z) {
z = add(mul(x, y), WAD / 2) / WAD;
}
function rdiv(uint x, uint y) internal pure returns (uint z) {
z = add(mul(x, RAY), y / 2) / y;
}
function wdiv(uint x, uint y) internal pure returns (uint z) {
z = add(mul(x, WAD), y / 2) / y;
}
function sub(uint x, uint y) internal pure returns (uint z) {
require((z = x - y) <= x, "ds-math-sub-underflow");
}
}
contract Helper is DSMath {
/**
* @dev Return ethereum address
*/
function getEthAddress() internal pure returns (address) {
return 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; // ETH Address
}
/**
* @dev Return WTH address
*/
function getWethAddress() internal pure returns (address) {
return 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; // WETH Address mainnet
// return 0xd0A1E359811322d97991E03f863a0C30C2cF029C; // WETH Address kovan
}
/**
* @dev Return eth price feed address
*/
function getEthPriceFeed() internal pure returns (address) {
return 0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419; // mainnet
// return 0x9326BFA02ADD2366b30bacB125260Af641031331; // kovan
}
}
contract CompoundHelpers is Helper {
/**
* @dev get Compound Comptroller
*/
function getComptroller() public pure returns (ComptrollerLensInterface) {
return ComptrollerLensInterface(0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B); // mainnet
// return ComptrollerLensInterface(0x1f5D7F3CaAC149fE41b8bd62A3673FE6eC0AB73b); // kovan
}
/**
* @dev get Compound Open Feed Oracle Address
*/
function getOracleAddress() public pure returns (address) {
return 0x9B8Eb8b3d6e2e0Db36F41455185FEF7049a35CaE;
}
/**
* @dev get ETH Address
*/
function getCETHAddress() public pure returns (address) {
return 0x4Ddc2D193948926D02f9B1fE9e1daa0718270ED5;
}
/**
* @dev Return InstaDApp Mapping Addresses
*/
function getMappingAddr() internal pure returns (address) {
return 0xe81F70Cc7C0D46e12d70efc60607F16bbD617E88; // InstaMapping Address
}
struct CompData {
uint tokenPriceInEth;
uint tokenPriceInUsd;
}
}
contract CompoundResolver is CompoundHelpers {
function getCompPrice(CTokenInterface cToken) public view returns (uint tokenPrice, uint ethPrice) {
uint decimals = getCETHAddress() == address(cToken) ? 18 : TokenInterface(cToken.underlying()).decimals();
uint price = OrcaleComp(getOracleAddress()).getUnderlyingPrice(address(cToken));
ethPrice = OrcaleComp(getOracleAddress()).getUnderlyingPrice(getCETHAddress());
tokenPrice = price / 10 ** (18 - decimals);
}
function getCompoundData(address token, uint ethAmount) public view returns (uint) {
address cTokenAddr = InstaMapping(getMappingAddr()).cTokenMapping(token);
if (cTokenAddr == address(0)) return 0;
ComptrollerLensInterface comptroller = getComptroller();
(, uint cf, ) = comptroller.markets(getCETHAddress());
CTokenInterface cToken = CTokenInterface(cTokenAddr);
(uint tokenPrice, uint ethPrice) = getCompPrice(cToken);
uint ethColl = wmul(ethAmount, ethPrice);
ethColl = wmul(ethColl, sub(cf, 10**16));
uint debtCanBorrow = wdiv(ethColl, tokenPrice);
return debtCanBorrow;
}
}
contract AaveHelpers is CompoundResolver {
/**
* @dev get Aave Provider Address
*/
function getAaveProviderAddress() internal pure returns (address) {
return 0x24a42fD28C976A61Df5D00D0599C34c4f90748c8; //mainnet
// return 0x506B0B2CF20FAA8f38a4E2B524EE43e1f4458Cc5; //kovan
}
struct AaveTokenData {
uint ltv;
uint threshold;
bool usageAsCollEnabled;
bool borrowEnabled;
bool stableBorrowEnabled;
bool isActive;
}
function collateralData(AaveInterface aave, address token) internal view returns(AaveTokenData memory) {
AaveTokenData memory aaveTokenData;
(
aaveTokenData.ltv,
aaveTokenData.threshold,
,
,
aaveTokenData.usageAsCollEnabled,
aaveTokenData.borrowEnabled,
aaveTokenData.stableBorrowEnabled,
aaveTokenData.isActive
) = aave.getReserveConfigurationData(token);
return aaveTokenData;
}
function getAavePrices(AaveProviderInterface AaveProvider, address token)
public view returns(uint tokenPrice, uint ethPrice) {
uint tokenPriceInETH = AavePriceInterface(AaveProvider.getPriceOracle()).getAssetPrice(token);
uint ethPriceDecimals = ChainLinkInterface(getEthPriceFeed()).decimals();
ethPrice = uint(ChainLinkInterface(getEthPriceFeed()).latestAnswer());
ethPrice = ethPrice * (10 ** (18 - ethPriceDecimals));
tokenPrice = wmul(tokenPriceInETH, ethPrice);
}
function getAaveData(address token, uint ethAmount)
public view returns (uint) {
AaveProviderInterface AaveProvider = AaveProviderInterface(getAaveProviderAddress());
AaveInterface aave = AaveInterface(AaveProvider.getLendingPool());
AaveCoreInterface aaveCore = AaveCoreInterface(AaveProvider.getLendingPoolCore());
if (aaveCore.getReserveATokenAddress(token) == address(0)) return 0;
AaveTokenData memory aaveToken = collateralData(aave, token);
AaveTokenData memory aaveEthToken = collateralData(aave, getEthAddress());
if (!aaveToken.borrowEnabled) return 0;
(uint tokenPrice, uint ethPrice) = getAavePrices(AaveProvider, token);
uint ethColl = wmul(ethAmount, ethPrice);
uint cf = sub(aaveEthToken.ltv, 1) * (10 ** 16);
ethColl = wmul(ethColl, cf);
uint debtCanBorrow = wdiv(ethColl, tokenPrice);
return debtCanBorrow;
}
}
contract MakerHelpers is AaveHelpers {
/**
* @dev get MakerDAO MCD Address contract
*/
function getMcdAddresses() public pure returns (address) {
return 0xF23196DF1C440345DE07feFbe556a5eF0dcD29F0;
}
/**
* @dev get Dai address
*/
function getDaiAddress() public pure returns (address) {
return 0x6B175474E89094C44Da98b954EedeAC495271d0F;
}
/**
* @dev Convert String to bytes32.
*/
function stringToBytes32(string memory str) internal pure returns (bytes32 result) {
require(bytes(str).length != 0, "String-Empty");
// solium-disable-next-line security/no-inline-assembly
assembly {
result := mload(add(str, 32))
}
}
function getColPrice(bytes32 ilk) internal view returns (uint price) {
address spot = InstaMcdAddress(getMcdAddresses()).spot();
address vat = InstaMcdAddress(getMcdAddresses()).vat();
(, uint mat) = SpotLike(spot).ilks(ilk);
(,,uint spotPrice,,) = VatLike(vat).ilks(ilk);
price = rmul(mat, spotPrice);
}
function getColRatio(bytes32 ilk) internal view returns (uint ratio) {
address spot = InstaMcdAddress(getMcdAddresses()).spot();
(, ratio) = SpotLike(spot).ilks(ilk);
ratio = rdiv(RAY, ratio);
}
}
contract MakerResolver is MakerHelpers {
function getMakerData(address token, uint ethAmt) public view returns (uint) {
if (token != getDaiAddress()) return 0;
bytes32 ilk = stringToBytes32("ETH-A");
uint ethPrice = getColPrice(ilk);
ethPrice = ethPrice / 10 ** 9;
uint cf = getColRatio(ilk) / 10 ** 9;
uint ethColl = wmul(ethAmt, ethPrice);
ethColl = wmul(ethColl, cf);
uint debtCanBorrow = ethColl;
return debtCanBorrow;
}
}
contract DydxFlashloanHelper is MakerResolver {
/**
* @dev get Dydx Solo Address
*/
function getSoloAddress() public pure returns (address addr) {
addr = 0x1E0447b19BB6EcFdAe1e4AE1694b0C3659614e4e;
}
}
contract DydxFlashloanResolver is DydxFlashloanHelper {
struct RouteData {
uint dydx;
uint maker;
uint compound;
uint aave;
}
function getTokenLimit(address token) public view returns (RouteData memory){
RouteData memory routeData;
uint ethBalanceSolo = TokenInterface(getWethAddress()).balanceOf(getSoloAddress());
routeData.dydx = token == getEthAddress() ? ethBalanceSolo : TokenInterface(token).balanceOf(getSoloAddress());
routeData.dydx = wmul(routeData.dydx, 99 * 10 ** 16);
routeData.maker = getMakerData(token, ethBalanceSolo);
routeData.compound = getCompoundData(token, ethBalanceSolo);
routeData.aave = getAaveData(token, ethBalanceSolo);
return routeData;
}
function getTokensLimit(address[] memory tokens) public view returns (RouteData[] memory){
uint _len = tokens.length;
RouteData[] memory routeData = new RouteData[](_len);
for (uint i = 0; i < _len; i++) {
routeData[i] = getTokenLimit(tokens[i]);
}
return routeData;
}
}
contract InstaPoolResolver is DydxFlashloanResolver {
string public constant name = "instapool-Resolver-v3";
}