From 10dde58404153397620b1a12b9e4cfe5f000b499 Mon Sep 17 00:00:00 2001 From: Mubaris NK Date: Mon, 12 Apr 2021 11:32:42 +0530 Subject: [PATCH] TODOs in receiver --- .../receivers/aave-v2-receiver/events.sol | 24 ++++++++ .../receivers/aave-v2-receiver/helpers.sol | 42 +++++++------- .../receivers/aave-v2-receiver/interfaces.sol | 15 ++++- contracts/receivers/aave-v2-receiver/main.sol | 57 +++++++++++++------ .../receivers/aave-v2-receiver/variables.sol | 4 +- contracts/senders/aave-v2-migrator/main.sol | 2 - 6 files changed, 102 insertions(+), 42 deletions(-) diff --git a/contracts/receivers/aave-v2-receiver/events.sol b/contracts/receivers/aave-v2-receiver/events.sol index a60963f..8614bde 100644 --- a/contracts/receivers/aave-v2-receiver/events.sol +++ b/contracts/receivers/aave-v2-receiver/events.sol @@ -13,4 +13,28 @@ contract Events { address[] tokens, uint[] amts ); + + event LogUpdateSafeRatioGap( + uint256 oldSafeRatioGap, + uint256 newSafeRatioGap + ); + + event LogAddSupportedTokens( + uint256[] tokens + ); + + event LogSettle(); + + event LogAaveV2Migrate( + address indexed user, + address[] supplyTokens, + address[] borrowTokens, + uint256[] supplyAmts, + uint256[] borrowAmts + ); + + event LogStateSync( + uint256 indexed stateId, + bytes data + ); } \ No newline at end of file diff --git a/contracts/receivers/aave-v2-receiver/helpers.sol b/contracts/receivers/aave-v2-receiver/helpers.sol index c0dccf9..98ca621 100644 --- a/contracts/receivers/aave-v2-receiver/helpers.sol +++ b/contracts/receivers/aave-v2-receiver/helpers.sol @@ -10,7 +10,8 @@ import { TokenMappingInterface, AaveData, AaveDataProviderInterface, - AaveInterface + AaveInterface, + AccountInterface } from "./interfaces.sol"; abstract contract Helpers is Stores, DSMath, Variables { @@ -29,21 +30,24 @@ abstract contract Helpers is Stores, DSMath, Variables { } function isPositionSafe() internal returns (bool isOk) { - // TODO: Check the final position health + AaveInterface aave = AaveInterface(aaveProvider.getLendingPool()); + (,,,,,uint healthFactor) = aave.getUserAccountData(address(this)); + uint minLimit = wdiv(1e18, safeRatioGap); + isOk = healthFactor > minLimit; require(isOk, "position-at-risk"); } function transferAtokens(AaveInterface aave, address dsa, address[] memory supplyTokens, uint[] memory supplyAmts) internal { for (uint i = 0; i < supplyTokens.length; i++) { - address _token = supplyTokens[i]; - IERC20 _atokenContract = IERC20(_token); // TODO: Fetch atoken from Aave mapping (change _token to atoken address) + address _token = supplyTokens[i] == maticAddr ? wmaticAddr : supplyTokens[i]; + (address _aToken, ,) = aaveData.getReserveTokensAddresses(_token); + IERC20 _atokenContract = IERC20(_aToken); uint _atokenBal = _atokenContract.balanceOf(address(this)); uint _supplyAmt = supplyAmts[i]; bool isFlash; uint _flashAmt; - // get Aave liquidity of token - uint tokenLiq = uint(0); + (uint tokenLiq,,,,,,,,,) = aaveData.getReserveData(_token); if (_atokenBal < _supplyAmt) { uint _reqAmt = _supplyAmt - _atokenBal; @@ -61,11 +65,11 @@ abstract contract Helpers is Stores, DSMath, Variables { uint finalSplit = _reqAmt - (splitAmt * (num - 1)); // TODO: to resolve upper decimal error for (uint j = 0; j < num; j++) { - if (i < num - 1) { - aave.borrow(_token, splitAmt, 2, 3288, address(this)); // TODO: is "2" for interest rate mode. Right? + if (j < num - 1) { + aave.borrow(_token, splitAmt, 2, 3288, address(this)); aave.deposit(_token, splitAmt, address(this), 3288); } else { - aave.borrow(_token, finalSplit, 2, 3288, address(this)); // TODO: is "2" for interest rate mode. Right? + aave.borrow(_token, finalSplit, 2, 3288, address(this)); aave.deposit(_token, finalSplit, address(this), 3288); } } @@ -81,10 +85,9 @@ abstract contract Helpers is Stores, DSMath, Variables { function borrowAndTransferSpells(AaveInterface aave, address dsa, address[] memory borrowTokens, uint[] memory borrowAmts) internal { for (uint i = 0; i < borrowTokens.length; i++) { - address _token = borrowTokens[i]; - address _atoken = address(0); // TODO: Fetch atoken address - // get Aave liquidity of token - uint tokenLiq = uint(0); + address _token = supplyTokens[i] == maticAddr ? wmaticAddr : supplyTokens[i]; + (address _atoken, ,) = aaveData.getReserveTokensAddresses(_token); + (uint tokenLiq,,,,,,,,,) = aaveData.getReserveData(_token); uint _borrowAmt = borrowAmts[i]; uint _flashAmt; @@ -106,16 +109,16 @@ abstract contract Helpers is Stores, DSMath, Variables { for (uint j = 0; j < num; j++) { targets[j] = "AAVE-A"; uint k = j * 2; - if (i < num - 1) { + if (j < num - 1) { // borrow spell - castData[k] = abi.encode("6abcd3de", _token, splitAmt, 2, 0, 0); // TODO: verify this & is rate mode right? + castData[k] = abi.encode("6abcd3de", _token, splitAmt, 2, 0, 0); // deposit spell - castData[k+1] = abi.encode("ce88b439", _token, splitAmt, 2, 0, 0); // TODO: verify this & is rate mode right? + castData[k+1] = abi.encode("ce88b439", _token, splitAmt, 2, 0, 0); } else { // borrow spell - castData[k] = abi.encode("6abcd3de", _token, finalSplit, 2, 0, 0); // TODO: verify this & is rate mode right? + castData[k] = abi.encode("6abcd3de", _token, finalSplit, 2, 0, 0); // deposit spell - castData[k+1] = abi.encode("ce88b439", _token, finalSplit, 2, 0, 0); // TODO: verify this & is rate mode right? + castData[k+1] = abi.encode("ce88b439", _token, finalSplit, 2, 0, 0); } } @@ -125,7 +128,8 @@ abstract contract Helpers is Stores, DSMath, Variables { targets[spellsAmt] = "BASIC-A"; // TODO: right spell? castData[spellsAmt] = abi.encode("4bd3ab82", _atoken, _borrowAmt, address(this), 0, 0); // encode the data of atoken withdrawal - // TODO: Call DSAs cast and borrow (maybe create a new implementation which only this contract can run?) + + AccountInterface(dsa).castMigrate(targets, castData, address(this)); } } diff --git a/contracts/receivers/aave-v2-receiver/interfaces.sol b/contracts/receivers/aave-v2-receiver/interfaces.sol index 50aa0bc..e15cf82 100644 --- a/contracts/receivers/aave-v2-receiver/interfaces.sol +++ b/contracts/receivers/aave-v2-receiver/interfaces.sol @@ -5,12 +5,11 @@ interface AccountInterface { function enable(address) external; function disable(address) external; function isAuth(address) external view returns (bool); - function cast( + function castMigrate( string[] calldata _targets, bytes[] calldata _datas, address _origin ) external payable returns (bytes32); - function migrateAave(address) external payable returns (bytes32); } interface TokenMappingInterface { @@ -62,6 +61,18 @@ interface AaveDataProviderInterface { bool isActive, bool isFrozen ); + function getReserveData(address asset) external view returns ( + uint256 availableLiquidity, + uint256 totalStableDebt, + uint256 totalVariableDebt, + uint256 liquidityRate, + uint256 variableBorrowRate, + uint256 stableBorrowRate, + uint256 averageStableBorrowRate, + uint256 liquidityIndex, + uint256 variableBorrowIndex, + uint40 lastUpdateTimestamp + ); } interface AaveInterface { diff --git a/contracts/receivers/aave-v2-receiver/main.sol b/contracts/receivers/aave-v2-receiver/main.sol index 36218b8..18804ce 100644 --- a/contracts/receivers/aave-v2-receiver/main.sol +++ b/contracts/receivers/aave-v2-receiver/main.sol @@ -11,6 +11,22 @@ import { Helpers } from "./helpers.sol"; contract MigrateResolver is Helpers, Events { using SafeERC20 for IERC20; + function updateSafeRatioGap(uint _safeRatioGap) public { + require(msg.sender == instaIndex.master(), "not-master"); + emit LogUpdateSafeRatioGap(safeRatioGap, _safeRatioGap); + safeRatioGap = _safeRatioGap; + } + + function addTokenSupport(address[] memory _tokens) public { + require(msg.sender == instaIndex.master(), "not-master"); + for (uint i = 0; i < _tokens.length; i++) { + require(!isSupportedToken[_tokens[i]], "already-added"); + isSupportedToken[_tokens[i]] = true; + supportedTokens.push(_tokens[i]); + } + emit LogAddSupportedTokens(_tokens); + } + function spell(address _target, bytes memory _data) external { require(msg.sender == instaIndex.master(), "not-master"); require(_target != address(0), "target-invalid"); @@ -39,19 +55,23 @@ contract MigrateResolver is Helpers, Events { for (uint256 i = 0; i < _length; i++) { require(isSupportedToken[tokens[i]], "token-not-enabled"); uint _amt; - address _token = tokens[i]; - if (_token == maticAddr) { + bool isMatic = tokens[i] == maticAddr; + address _token = isMatic ? wmaticAddr : tokens[i]; + + IERC20 tokenContract = IERC20(_token); + + if (isMatic) { require(msg.value == amts[i]); - _amt = msg.value; TokenInterface(wmaticAddr).deposit{value: msg.value}(); - aave.deposit(wmaticAddr, _amt, address(this), 3288); + _amt = msg.value; } else { - IERC20 tokenContract = IERC20(_token); _amt = amts[i] == uint(-1) ? tokenContract.balanceOf(msg.sender) : amts[i]; tokenContract.safeTransferFrom(msg.sender, address(this), _amt); - aave.deposit(_token, _amt, address(this), 3288); } + tokenContract.safeApprove(address(aave),_amt); + aave.deposit(_token, _amt, address(this), 3288); + _amts[i] = _amt; deposits[msg.sender][_token] += _amt; @@ -71,7 +91,8 @@ contract MigrateResolver is Helpers, Events { for (uint256 i = 0; i < _length; i++) { require(isSupportedToken[tokens[i]], "token-not-enabled"); uint _amt = amts[i]; - address _token = tokens[i]; + bool isMatic = tokens[i] == maticAddr; + address _token = isMatic ? wmaticAddr : tokens[i]; uint maxAmt = deposits[msg.sender][_token]; if (_amt > maxAmt) { @@ -80,14 +101,20 @@ contract MigrateResolver is Helpers, Events { deposits[msg.sender][_token] = sub(maxAmt, _amt); - if (_token == maticAddr) { + if (isMatic) { TokenInterface _tokenContract = TokenInterface(wmaticAddr); uint _maticBal = address(this).balance; uint _tknBal = _tokenContract.balanceOf(address(this)); - if ((_maticBal + _tknBal) < _amt) { - aave.withdraw(wmaticAddr, sub(_amt, (_tknBal + _maticBal)), address(this)); + if (_maticBal > _amt) { + msg.sender.call{value: _amt}(""); + _amts[i] = _amt; + continue; } - _tokenContract.withdraw((sub(_amt, _maticBal))); + + if ((_ethBal + _tknBal) < _amt) { + aave.withdraw(wmaticAddr, sub(_amt, (_tknBal + _ethBal)), address(this)); + } + _tokenContract.withdraw((sub(_amt, _ethBal))); msg.sender.call{value: _amt}(""); } else { IERC20 _tokenContract = IERC20(_token); @@ -139,7 +166,7 @@ contract MigrateResolver is Helpers, Events { } } } - // TODO: emit event + emit LogSettle(); } } @@ -167,7 +194,7 @@ contract AaveV2Migrator is MigrateResolver { isPositionSafe(); - // TODO: emit event + emit LogAaveV2Migrate(dsa, supplyTokens, borrowTokens, supplyAmts, supplyAmts); } function onStateReceive(uint256 stateId, bytes calldata receivedData) external { @@ -178,7 +205,7 @@ contract AaveV2Migrator is MigrateResolver { // Can't do it via any address as user can migrate 2 times positions[stateId] = receivedData; - // TODO: add event + emit LogStateSync(stateId, receivedData); } function migrate(uint _id) external { @@ -191,7 +218,5 @@ contract AaveV2Migrator is MigrateResolver { _migratePosition(data); delete positions[_id]; - - // TODO: add event } } diff --git a/contracts/receivers/aave-v2-receiver/variables.sol b/contracts/receivers/aave-v2-receiver/variables.sol index 3f7d382..500e206 100644 --- a/contracts/receivers/aave-v2-receiver/variables.sol +++ b/contracts/receivers/aave-v2-receiver/variables.sol @@ -10,7 +10,6 @@ import { contract Variables { // This will be used to have debt/collateral ratio always 20% less than liquidation - // TODO: Is this number correct for it? uint public safeRatioGap = 200000000000000000; // 20%? 2e17 // TODO: Add function for flash deposits and withdraw @@ -25,8 +24,7 @@ contract Variables { /** * @dev Aave Data Provider */ - // TODO: add L2 Data provider address - AaveDataProviderInterface constant internal aaveData = AaveDataProviderInterface(address(0)); + AaveDataProviderInterface constant internal aaveData = AaveDataProviderInterface(0x7551b5D2763519d4e37e8B81929D336De671d46d); // dsa => position diff --git a/contracts/senders/aave-v2-migrator/main.sol b/contracts/senders/aave-v2-migrator/main.sol index 3c81c3e..f81ec6f 100644 --- a/contracts/senders/aave-v2-migrator/main.sol +++ b/contracts/senders/aave-v2-migrator/main.sol @@ -11,8 +11,6 @@ import { Events } from "./events.sol"; contract LiquidityResolver is Helpers, Events { using SafeERC20 for IERC20; - event variablesUpdate(uint _safeRatioGap, uint _fee); - function updateVariables(uint _safeRatioGap, uint _fee) public { require(msg.sender == instaIndex.master(), "not-master"); emit LogUpdateVariables(fee, _fee, safeRatioGap, _safeRatioGap);