From 81f8ade0418f7815d6ba255707e3356135be6b61 Mon Sep 17 00:00:00 2001 From: Mubaris NK Date: Sun, 11 Apr 2021 19:41:11 +0530 Subject: [PATCH] Add checkRatio and minor changes --- .../senders/aave-v2-migrator/helpers.sol | 71 +++++++++++++++++-- .../senders/aave-v2-migrator/interfaces.sol | 25 +++++++ .../senders/aave-v2-migrator/variables.sol | 6 ++ 3 files changed, 98 insertions(+), 4 deletions(-) diff --git a/contracts/senders/aave-v2-migrator/helpers.sol b/contracts/senders/aave-v2-migrator/helpers.sol index ac0f506..06e98fb 100644 --- a/contracts/senders/aave-v2-migrator/helpers.sol +++ b/contracts/senders/aave-v2-migrator/helpers.sol @@ -14,12 +14,40 @@ import { AaveDataProviderInterface, AaveInterface, ATokenInterface, - StateSenderInterface + StateSenderInterface, + ReserveConfigurationMap } from "./interfaces.sol"; abstract contract Helpers is DSMath, Stores, Variables { using SafeERC20 for IERC20; + /** + * @dev Aave reserve configuration bit masks + */ + uint256 constant LIQUIDATION_THRESHOLD_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFF; + uint256 constant DECIMALS_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFF; + uint256 constant LIQUIDATION_THRESHOLD_START_BIT_POSITION = 16; + uint256 constant RESERVE_DECIMALS_START_BIT_POSITION = 48; + + /** + * @dev Additional math helpers + */ + uint256 constant PERCENTAGE_FACTOR = 1e4; //percentage plus two decimals + uint256 constant HALF_PERCENT = PERCENTAGE_FACTOR / 2; + + function percentMul(uint256 value, uint256 percentage) internal pure returns (uint256) { + if (value == 0 || percentage == 0) { + return 0; + } + + require( + value <= (type(uint256).max - HALF_PERCENT) / percentage, + "percent-mul-overflow" + ); + + return (value * percentage + HALF_PERCENT) / PERCENTAGE_FACTOR; + } + function _paybackBehalfOne(AaveInterface aave, address token, uint amt, uint rateMode, address user) private { address _token = token == ethAddr ? wethAddr : token; aave.repay(_token, amt, rateMode, user); @@ -98,17 +126,52 @@ abstract contract Helpers is DSMath, Stores, Variables { } } + function _getParams(uint config) internal returns ( + uint liqudationThreshold, uint decimals + ) { + liqudationThreshold = (config & ~LIQUIDATION_THRESHOLD_MASK) >> LIQUIDATION_THRESHOLD_START_BIT_POSITION; + decimals = (config & ~DECIMALS_MASK) >> RESERVE_DECIMALS_START_BIT_POSITION; + } + function isPositionSafe() internal returns (bool isOk) { AaveInterface aave = AaveInterface(aaveProvider.getLendingPool()); (,,,,,uint healthFactor) = aave.getUserAccountData(address(this)); - // TODO: Check throughly minLimit = 100%/80% = 125% (20% gap initially) uint minLimit = wdiv(1e18, safeRatioGap); isOk = healthFactor > minLimit; require(isOk, "position-at-risk"); } function _checkRatio(AaveData memory data) public returns (bool isOk) { - // TODO: @mubaris Check the debt/collateral ratio should be less than "safeRatioGap" from Liquidation of that particular user assets - } + uint totalCollateral; + uint totalDebt; + uint avgLiquidationThresold; + for(uint i = 0; i < data.supplyTokens.length; i++) { + address _token = data.supplyTokens[i] == ethAddr ? wethAddr : data.supplyTokens[i]; + ReserveConfigurationMap memory config = aave.getConfiguration(_token); + (uint _liq, uint _dec) = _getParams(config.data); + uint assetPrice = aaveOracle.getAssetPrice(_token); + uint collateral = div(mul(assetPrice, data.supplyAmts[i]), 10**_dec); + totalCollateral += collateral; + avgLiquidationThresold += mul(collateral, _liq); + } + + for(uint i = 0; data.borrowTokens.length; i++) { + address _token = data.supplyTokens[i] == ethAddr ? wethAddr : data.supplyTokens[i]; + ReserveConfigurationMap memory config = aave.getConfiguration(_token); + (, uint _dec) = _getParams(config.data); + uint assetPrice = aaveOracle.getAssetPrice(_token); + uint debt = div(mul(assetPrice, data.borrowAmts[i]), 10**_dec); + totalDebt += debt; + } + + if (totalCollateral > 0) { + avgLiquidationThresold = div(avgLiquidationThresold, totalCollateral); + } + + uint healthFactor = wdiv(percentMul(totalCollateral, avgLiquidationThresold), totalDebt); + uint minLimit = wdiv(1e18, safeRatioGap); + isOk = healthFactor > minLimit; + require(isOk, "position-at-risk"); + } } \ No newline at end of file diff --git a/contracts/senders/aave-v2-migrator/interfaces.sol b/contracts/senders/aave-v2-migrator/interfaces.sol index 9b5e5a0..a8e40cb 100644 --- a/contracts/senders/aave-v2-migrator/interfaces.sol +++ b/contracts/senders/aave-v2-migrator/interfaces.sol @@ -1,6 +1,20 @@ pragma solidity >=0.7.0; pragma experimental ABIEncoderV2; +struct ReserveConfigurationMap { + //bit 0-15: LTV + //bit 16-31: Liq. threshold + //bit 32-47: Liq. bonus + //bit 48-55: Decimals + //bit 56: Reserve is active + //bit 57: reserve is frozen + //bit 58: borrowing is enabled + //bit 59: stable rate borrowing enabled + //bit 60-63: reserved + //bit 64-79: reserve factor + uint256 data; +} + interface AaveInterface { function deposit(address _asset, uint256 _amount, address _onBehalfOf, uint16 _referralCode) external; function withdraw(address _asset, uint256 _amount, address _to) external; @@ -21,6 +35,10 @@ interface AaveInterface { uint256 ltv, uint256 healthFactor ); + function getConfiguration(address asset) + external + view + returns (ReserveConfigurationMap memory); } interface AaveLendingPoolProviderInterface { @@ -71,6 +89,13 @@ interface ATokenInterface { function approve(address, uint256) external; } +interface AaveOracleInterface { + function getAssetPrice(address _asset) external view returns (uint256); + function getAssetsPrices(address[] calldata _assets) external view returns(uint256[] memory); + function getSourceOfAsset(address _asset) external view returns(address); + function getFallbackOracle() external view returns(address); +} + interface StateSenderInterface { function syncState(address receiver, bytes calldata data) external; function register(address sender, address receiver) external; diff --git a/contracts/senders/aave-v2-migrator/variables.sol b/contracts/senders/aave-v2-migrator/variables.sol index 644aea1..83bdd8c 100644 --- a/contracts/senders/aave-v2-migrator/variables.sol +++ b/contracts/senders/aave-v2-migrator/variables.sol @@ -3,6 +3,7 @@ pragma solidity ^0.7.0; import { AaveLendingPoolProviderInterface, AaveDataProviderInterface, + AaveOracleInterface, StateSenderInterface, IndexInterface, FlashloanInterface @@ -53,6 +54,11 @@ contract Variables { */ AaveDataProviderInterface constant internal aaveData = AaveDataProviderInterface(0x057835Ad21a177dbdd3090bB1CAE03EaCF78Fc6d); + /** + * @dev Aave Price Oracle + */ + AaveOracleInterface constant internal aaveOracle = AaveOracleInterface(0xA50ba011c48153De246E5192C8f9258A2ba79Ca9); + /** * @dev Polygon State Sync Contract */