mirror of
				https://github.com/Instadapp/dsa-polygon-migration.git
				synced 2024-07-29 22:27:58 +00:00 
			
		
		
		
	many updates at once
This commit is contained in:
		
							parent
							
								
									9779cd4241
								
							
						
					
					
						commit
						2213f12058
					
				|  | @ -7,8 +7,6 @@ abstract contract Stores { | |||
| 
 | ||||
|     /** | ||||
|     * @dev Return ethereum address | ||||
|     * ETH on Mainnet | ||||
|     * MATIC on Polygon | ||||
|     */ | ||||
|     address constant internal ethAddr = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; | ||||
| 
 | ||||
							
								
								
									
										37
									
								
								contracts/common/stores-polygon.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								contracts/common/stores-polygon.sol
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,37 @@ | |||
| pragma solidity ^0.7.0; | ||||
| 
 | ||||
| import { MemoryInterface } from "./interfaces.sol"; | ||||
| 
 | ||||
| 
 | ||||
| abstract contract Stores { | ||||
| 
 | ||||
|     /** | ||||
|     * @dev Return matic address | ||||
|     */ | ||||
|     address constant internal maticAddr = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; | ||||
| 
 | ||||
|     /** | ||||
|     * @dev Return Wrapped MATIC address | ||||
|     */ | ||||
|     address constant internal wmaticAddr = 0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270; | ||||
| 
 | ||||
|     /** | ||||
|     * @dev Return memory variable address | ||||
|     */ | ||||
|     MemoryInterface constant internal instaMemory = MemoryInterface(address(0)); // TODO: memory address on Polygon | ||||
| 
 | ||||
|     /** | ||||
|     * @dev Get Uint value from InstaMemory Contract. | ||||
|     */ | ||||
|     function getUint(uint getId, uint val) internal returns (uint returnVal) { | ||||
|         returnVal = getId == 0 ? val : instaMemory.getUint(getId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|     * @dev Set Uint value in InstaMemory Contract. | ||||
|     */ | ||||
|     function setUint(uint setId, uint val) virtual internal { | ||||
|         if (setId != 0) instaMemory.setUint(setId, val); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -1,7 +1,7 @@ | |||
| pragma solidity ^0.7.0; | ||||
| 
 | ||||
| import { DSMath } from "../../common/math.sol"; | ||||
| import { Stores } from "../../common/stores.sol"; | ||||
| import { Stores } from "../../common/stores-polygon.sol"; | ||||
| 
 | ||||
| import {  | ||||
|     AaveLendingPoolProviderInterface, | ||||
|  |  | |||
|  | @ -3,31 +3,19 @@ pragma solidity >=0.7.0; | |||
| import { DSMath } from "../../common/math.sol"; | ||||
| import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; | ||||
| import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; | ||||
| import { Stores } from "../../common/stores-polygon.sol"; | ||||
| import { Variables } from "./variables.sol"; | ||||
| 
 | ||||
| import { | ||||
|     TokenMappingInterface, | ||||
|     AaveData, | ||||
|     AaveLendingPoolProviderInterface, | ||||
|     AaveDataProviderInterface, | ||||
|     AaveInterface | ||||
| } from "./interfaces.sol"; | ||||
| 
 | ||||
| abstract contract Helpers is DSMath { | ||||
| abstract contract Helpers is Stores, DSMath, Variables { | ||||
|     using SafeERC20 for IERC20; | ||||
| 
 | ||||
|     // 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 | ||||
|     mapping(address => mapping(address => uint)) flashDeposits; // Flash deposits of particular token | ||||
|     mapping(address => uint) flashAmts; // token amount for flashloan usage (these token will always stay raw in this contract) | ||||
| 
 | ||||
|     // TODO: Replace this | ||||
|     TokenMappingInterface tokenMapping = TokenMappingInterface(address(2)); | ||||
| 
 | ||||
|     AaveLendingPoolProviderInterface constant internal aaveProvider = AaveLendingPoolProviderInterface(0xd05e3E715d945B59290df0ae8eF85c1BdB684744); | ||||
| 
 | ||||
|     function remapTokens(AaveData memory data) internal view returns (AaveData memory) { | ||||
|         for (uint i = 0; i < data.supplyTokens.length; i++) { | ||||
|             data.supplyTokens[i] = tokenMapping.getMapping(data.supplyTokens[i]); | ||||
|  | @ -45,8 +33,7 @@ abstract contract Helpers is DSMath { | |||
|         require(isOk, "position-at-risk"); | ||||
|     } | ||||
| 
 | ||||
|     function transferAtokens(address dsa, address[] memory supplyTokens, uint[] memory supplyAmts) internal { | ||||
|         AaveInterface aave = AaveInterface(aaveProvider.getLendingPool()); | ||||
|     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) | ||||
|  | @ -63,8 +50,7 @@ abstract contract Helpers is DSMath { | |||
|                 if (tokenLiq < _reqAmt) { | ||||
|                     _flashAmt = flashAmts[_token]; | ||||
|                     if (_flashAmt > 0) { | ||||
|                         // TODO: deposit _flashAmt to Aave | ||||
|                         aave.deposit(_token, _flashAmt, address(this), 3288); | ||||
|                         aave.deposit(_token, _flashAmt, address(this), 3288); // TODO: what is our ID on Polygon? | ||||
|                         tokenLiq += _flashAmt; | ||||
|                         isFlash = true; | ||||
|                     } | ||||
|  | @ -93,16 +79,20 @@ abstract contract Helpers is DSMath { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     function borrowAndTransferSpells(address dsa, address[] memory borrowTokens, uint[] memory borrowAmts) internal { | ||||
|     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); | ||||
|             uint _borrowAmt = borrowAmts[i]; | ||||
| 
 | ||||
|             uint _flashAmt; | ||||
|             bool isFlash; | ||||
|             if (tokenLiq < _borrowAmt) { | ||||
|                 uint _flashAmt = flashAmts[_token]; | ||||
|                 // TODO: deposit _flashAmt in Aave | ||||
|                 _flashAmt = flashAmts[_token]; | ||||
|                 aave.deposit(_token, _flashAmt, address(this), 3288); // TODO: what is our ID on Polygon? | ||||
|                 isFlash = true; | ||||
|                 tokenLiq += _flashAmt; | ||||
|             } | ||||
|             // TODO: Check number of loops needed. Borrow and supply on user's account. | ||||
|  | @ -128,10 +118,16 @@ abstract contract Helpers is DSMath { | |||
|                     castData[k+1] = abi.encode("ce88b439", _token, finalSplit, 2, 0, 0); // TODO: verify this & is rate mode right? | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             if (isFlash) { | ||||
|                 aave.withdraw(_token, _flashAmt, address(this)); | ||||
|             } | ||||
| 
 | ||||
|             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?) | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -3,21 +3,14 @@ pragma experimental ABIEncoderV2; | |||
| 
 | ||||
| import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; | ||||
| import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; | ||||
| 
 | ||||
| import { AccountInterface, AaveData, IndexInterface } from "./interfaces.sol"; | ||||
| import { TokenInterface } from "../../common/interfaces.sol"; | ||||
| import { AccountInterface, AaveData, AaveInterface, IndexInterface } from "./interfaces.sol"; | ||||
| import { Events } from "./events.sol"; | ||||
| import { Helpers } from "./helpers.sol"; | ||||
| 
 | ||||
| contract MigrateResolver is Helpers, Events { | ||||
|     using SafeERC20 for IERC20; | ||||
| 
 | ||||
|     // dsa => position | ||||
|     mapping(uint => bytes) public positions; | ||||
|     mapping(address => mapping(address => uint)) public deposits; | ||||
| 
 | ||||
|     // InstaIndex Address. | ||||
|     IndexInterface public constant instaIndex = IndexInterface(0x2971AdFa57b20E5a416aE5a708A8655A9c74f723); | ||||
| 
 | ||||
|     function spell(address _target, bytes memory _data) external { | ||||
|         require(msg.sender == instaIndex.master(), "not-master"); | ||||
|         require(_target != address(0), "target-invalid"); | ||||
|  | @ -34,35 +27,50 @@ contract MigrateResolver is Helpers, Events { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // TODO: Deposit in Aave | ||||
|     function deposit(address[] calldata tokens, uint[] calldata amts) external { | ||||
|     // TODO: @mubaris Make this similar to L1 migrator. Have to change ETH by MATIC | ||||
|     function deposit(address[] calldata tokens, uint[] calldata amts) external payable { | ||||
|         uint _length = tokens.length; | ||||
|         require(_length == amts.length, "invalid-length"); | ||||
| 
 | ||||
|         AaveInterface aave = AaveInterface(aaveProvider.getLendingPool()); | ||||
| 
 | ||||
|         uint[] memory _amts = new uint[](_length); | ||||
| 
 | ||||
|         for (uint256 i = 0; i < _length; i++) { | ||||
|             require(isSupportedToken[tokens[i]], "token-not-enabled"); | ||||
|             uint _amt; | ||||
|             address _token = tokens[i]; | ||||
|              | ||||
|             IERC20 tokenContract = IERC20(_token); | ||||
|             uint _amt = amts[i] == uint(-1) ? tokenContract.balanceOf(msg.sender) : amts[i]; | ||||
|             tokenContract.safeTransferFrom(msg.sender, address(this), _amt); | ||||
|             if (_token == maticAddr) { | ||||
|                 require(msg.value == amts[i]); | ||||
|                 _amt = msg.value; | ||||
|                 TokenInterface(wmaticAddr).deposit{value: msg.value}(); | ||||
|                 aave.deposit(wmaticAddr, _amt, address(this), 3288); | ||||
|             } 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); | ||||
|             } | ||||
| 
 | ||||
|             _amts[i] = _amt; | ||||
| 
 | ||||
|             deposits[msg.sender][_token] += _amt; | ||||
|             _amts[i] = _amt; | ||||
|         } | ||||
| 
 | ||||
|         emit LogDeposit(msg.sender, tokens, _amts); | ||||
|     } | ||||
| 
 | ||||
|     // TODO: Withdraw from Aave | ||||
|     // TODO: @mubaris Make this similar to L1 migrator. Have to change ETH by MATIC | ||||
|     function withdraw(address[] calldata tokens, uint[] calldata amts) external { | ||||
|         uint _length = tokens.length; | ||||
|         require(_length == amts.length, "invalid-length"); | ||||
| 
 | ||||
|         AaveInterface aave = AaveInterface(aaveProvider.getLendingPool()); | ||||
| 
 | ||||
|         uint[] memory _amts = new uint[](_length); | ||||
| 
 | ||||
|         for (uint256 i = 0; i < _length; i++) { | ||||
|             require(isSupportedToken[tokens[i]], "token-not-enabled"); | ||||
|             uint _amt = amts[i]; | ||||
|             address _token = tokens[i]; | ||||
|             uint maxAmt = deposits[msg.sender][_token]; | ||||
|  | @ -71,11 +79,27 @@ contract MigrateResolver is Helpers, Events { | |||
|                 _amt = maxAmt; | ||||
|             } | ||||
| 
 | ||||
|             IERC20(_token).safeTransfer(msg.sender, _amt); | ||||
| 
 | ||||
|             deposits[msg.sender][_token] = sub(maxAmt, _amt); | ||||
|             if (_token == maticAddr) { | ||||
|                 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)); | ||||
|                 } | ||||
|                 _tokenContract.withdraw((sub(_amt, _maticBal))); | ||||
|                 msg.sender.call{value: _amt}(""); | ||||
|             } else { | ||||
|                 IERC20 _tokenContract = IERC20(_token); | ||||
|                 uint _tknBal = _tokenContract.balanceOf(address(this)); | ||||
|                 if (_tknBal < _amt) { | ||||
|                     aave.withdraw(_token, sub(_amt, _tknBal), address(this)); | ||||
|                 } | ||||
|                 _tokenContract.safeTransfer(msg.sender, _amt); | ||||
|             } | ||||
| 
 | ||||
|             _amts[i] = _amt; | ||||
| 
 | ||||
|             deposits[msg.sender][_token] = sub(maxAmt, _amt); | ||||
|         } | ||||
| 
 | ||||
|         isPositionSafe(); | ||||
|  | @ -83,9 +107,10 @@ contract MigrateResolver is Helpers, Events { | |||
|         emit LogWithdraw(msg.sender, tokens, _amts); | ||||
|     } | ||||
| 
 | ||||
|     // TODO: Things to factor | ||||
|     // TODO: @mubaris Things to factor | ||||
|     // If there is same token supply and borrow, then close the smaller one | ||||
|     // If there is ideal token then payback or deposit according to the position | ||||
|     // If there is ideal token (other than flashAmt) then payback or deposit according to the position | ||||
|     // Keep flashAmt tokens as ideal | ||||
|     // Object is the decrease the ratio and pay as less interest | ||||
|     function settle() external { | ||||
| 
 | ||||
|  | @ -107,43 +132,34 @@ contract AaveV2Migrator is MigrateResolver { | |||
|         address[] memory supplyTokens = _data.supplyTokens; | ||||
|         address[] memory borrowTokens = _data.borrowTokens; | ||||
| 
 | ||||
|         transferAtokens(dsa, supplyTokens, supplyAmts); | ||||
|         AaveInterface aave = AaveInterface(aaveProvider.getLendingPool()); | ||||
| 
 | ||||
|         // Have to borrow from user's account | ||||
|         borrowAndTransferSpells(dsa, borrowTokens, borrowAmts); | ||||
|         transferAtokens(aave, dsa, supplyTokens, supplyAmts); | ||||
| 
 | ||||
|         // Have to borrow from user's account & transfer | ||||
|         borrowAndTransferSpells(aave, dsa, borrowTokens, borrowAmts); | ||||
| 
 | ||||
|         isPositionSafe(); | ||||
|     } | ||||
| 
 | ||||
|     // function getPosition(address owner) public view returns (AaveData memory data) { | ||||
|     //     data = positions[owner]; | ||||
|     // } | ||||
| 
 | ||||
|     // TODO: have to add more conditions | ||||
|     // TODO: @mubaris - Do we need this? | ||||
|     function canMigrate(AaveData memory data) public view returns (bool can) { | ||||
|         // can = true; | ||||
| 
 | ||||
|         // AaveData memory data = getPosition(owner); | ||||
| 
 | ||||
|         // for (uint i = 0; i < data.supplyTokens.length; i++) { | ||||
|         //     IERC20 token = IERC20(data.supplyTokens[i]); | ||||
|         //     if (token.balanceOf(address(this)) < data.supplyAmts[i]) { | ||||
|         //         can = false; | ||||
|         //     } | ||||
|         // } | ||||
|     } | ||||
| 
 | ||||
|     function onStateReceive(uint256 stateId, bytes calldata receivedData) external { | ||||
|         require(stateId > lastStateId, "wrong-data"); | ||||
|         lastStateId = stateId; | ||||
| 
 | ||||
|         // (AaveData memory data) = abi.decode(receivedData, (AaveData)); | ||||
|         positions[stateId] = receivedData; // TODO: what's the best way to store user's data to create position later | ||||
|         // TODO: what's the best way to store user's data to create position later. | ||||
|         // Can't do it via any address as user can migrate 2 times  | ||||
|         positions[stateId] = receivedData; | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     function migrate(uint _id) external { | ||||
|         bytes memory _data = positions[_id]; | ||||
| 
 | ||||
|         require(_data != bytes(0), "already-migrated"); // TODO: How to resolve this | ||||
|          | ||||
|         AaveData memory data = abi.decode(_data, (AaveData)); | ||||
|  |  | |||
							
								
								
									
										35
									
								
								contracts/receivers2/aave-v2-receiver/variables.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								contracts/receivers2/aave-v2-receiver/variables.sol
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,35 @@ | |||
| pragma solidity ^0.7.0; | ||||
| 
 | ||||
| import { | ||||
|     TokenMappingInterface, | ||||
|     AaveLendingPoolProviderInterface, | ||||
|     IndexInterface | ||||
| } from "./interfaces.sol"; | ||||
| 
 | ||||
| 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 | ||||
|     mapping(address => mapping(address => uint)) flashDeposits; // Flash deposits of particular token | ||||
|     mapping(address => uint) flashAmts; // token amount for flashloan usage (these token will always stay raw in this contract) | ||||
| 
 | ||||
|     // TODO: Replace this | ||||
|     TokenMappingInterface tokenMapping = TokenMappingInterface(address(2)); | ||||
| 
 | ||||
|     AaveLendingPoolProviderInterface constant internal aaveProvider = AaveLendingPoolProviderInterface(0xd05e3E715d945B59290df0ae8eF85c1BdB684744); | ||||
| 
 | ||||
|     // dsa => position | ||||
|     mapping(uint => bytes) public positions; | ||||
|     mapping(address => mapping(address => uint)) public deposits; | ||||
| 
 | ||||
|     // InstaIndex Address. | ||||
|     IndexInterface public constant instaIndex = IndexInterface(0x2971AdFa57b20E5a416aE5a708A8655A9c74f723); | ||||
| 
 | ||||
|     // TODO: Set by construtor? | ||||
|     mapping(address => bool) public isSupportedToken; | ||||
|     address[] public supportedTokens; | ||||
| 
 | ||||
| } | ||||
|  | @ -1,7 +1,7 @@ | |||
| pragma solidity ^0.7.0; | ||||
| 
 | ||||
| import { DSMath } from "../../common/math.sol"; | ||||
| import { Stores } from "../../common/stores.sol"; | ||||
| import { Stores } from "../../common/stores-mainnet.sol"; | ||||
| import { AaveLendingPoolProviderInterface, AaveDataProviderInterface, AaveMigratorInterface } from "./interfaces.sol"; | ||||
| 
 | ||||
| abstract contract Helpers is DSMath, Stores { | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| pragma solidity ^0.7.0; | ||||
| 
 | ||||
| import { DSMath } from "../../common/math.sol"; | ||||
| import { Stores } from "../../common/stores.sol"; | ||||
| import { Stores } from "../../common/stores-mainnet.sol"; | ||||
| 
 | ||||
| import {  | ||||
|     AaveLendingPoolProviderInterface, | ||||
|  |  | |||
|  | @ -1,63 +1,23 @@ | |||
| pragma solidity >=0.7.0; | ||||
| pragma experimental ABIEncoderV2; | ||||
| 
 | ||||
| import { DSMath } from "../../common/math.sol"; | ||||
| import { Stores } from "../../common/stores.sol"; | ||||
| import { Stores } from "../../common/stores-mainnet.sol"; | ||||
| 
 | ||||
| import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; | ||||
| import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; | ||||
| 
 | ||||
| import { Variables } from "./variables.sol"; | ||||
| 
 | ||||
| import {  | ||||
|     AaveLendingPoolProviderInterface, | ||||
|     AaveDataProviderInterface, | ||||
|     AaveInterface, | ||||
|     ATokenInterface, | ||||
|     StateSenderInterface | ||||
| } from "./interfaces.sol"; | ||||
| 
 | ||||
| abstract contract Helpers is DSMath, Stores { | ||||
| 
 | ||||
|     using SafeERC20 for IERC20; | ||||
| 
 | ||||
|     struct AaveDataRaw { | ||||
|         address targetDsa; | ||||
|         uint[] supplyAmts; | ||||
|         uint[] variableBorrowAmts; | ||||
|         uint[] stableBorrowAmts; | ||||
|         address[] supplyTokens; | ||||
|         address[] borrowTokens; | ||||
|     } | ||||
| 
 | ||||
|     struct AaveData { | ||||
|         address targetDsa; | ||||
|         uint[] supplyAmts; | ||||
|         uint[] borrowAmts; | ||||
|         address[] supplyTokens; | ||||
|         address[] borrowTokens; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @dev Aave referal code | ||||
|      */ | ||||
|     uint16 constant internal referralCode = 3228; | ||||
| 
 | ||||
|     address constant internal polygonReceiver = address(2); // Replace this | ||||
| 
 | ||||
|     /** | ||||
|      * @dev Aave Provider | ||||
|      */ | ||||
|     AaveLendingPoolProviderInterface constant internal aaveProvider = AaveLendingPoolProviderInterface(0xB53C1a33016B2DC2fF3653530bfF1848a515c8c5); | ||||
| 
 | ||||
|     /** | ||||
|      * @dev Aave Data Provider | ||||
|      */ | ||||
|     AaveDataProviderInterface constant internal aaveData = AaveDataProviderInterface(0x057835Ad21a177dbdd3090bB1CAE03EaCF78Fc6d); | ||||
| 
 | ||||
|     /** | ||||
|      * @dev Polygon State Sync Contract | ||||
|      */ | ||||
|     StateSenderInterface constant internal stateSender = StateSenderInterface(0x28e4F3a7f651294B9564800b2D01f35189A5bFbE); | ||||
| 
 | ||||
|     function _borrow(address _token, uint _amt) internal { | ||||
|     } | ||||
| abstract contract Helpers is DSMath, Stores, Variables { | ||||
| 
 | ||||
|     function _paybackBehalfOne(AaveInterface aave, address token, uint amt, uint rateMode, address user) private { | ||||
|         aave.repay(token, amt, rateMode, user); | ||||
|  | @ -91,8 +51,9 @@ abstract contract Helpers is DSMath, Stores { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     function _PaybackCalculate(AaveInterface aave, AaveDataRaw memory _data, address sourceDsa) internal returns (uint[] stableBorrow, uint[] variableBorrow, uint[] totalBorrow) { | ||||
|     function _PaybackCalculate(AaveInterface aave, AaveDataRaw memory _data, address sourceDsa) internal returns (uint[] memory stableBorrow, uint[] memory variableBorrow, uint[] memory totalBorrow) { | ||||
|         for (uint i = 0; i < _data.borrowTokens.length; i++) { | ||||
|             require(isSupportedToken[_data.borrowTokens[i]], "token-not-enabled"); | ||||
|             address _token = _data.borrowTokens[i] == ethAddr ? wethAddr : _data.borrowTokens[i]; | ||||
|             _data.borrowTokens[i] = _token; | ||||
| 
 | ||||
|  | @ -108,30 +69,40 @@ abstract contract Helpers is DSMath, Stores { | |||
| 
 | ||||
|             totalBorrow[i] = add(stableBorrow[i], variableBorrow[i]); | ||||
|             if (totalBorrow[i] > 0) { | ||||
|                 IERC20(_token).safeApprove(address(aave), totalBorrow[i]); // TODO: Approval is to Aave address of atokens address? | ||||
|                 IERC20(_token).approve(address(aave), totalBorrow[i]); // TODO: Approval is to Aave address of atokens address? | ||||
|             } | ||||
|             aave.borrow(_token, totalBorrow[i], 2, 3088, address(this)); // TODO: Borrowing debt to payback | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     function _getAtokens(AaveInterface aave, address[] memory supplyTokens, uint[] memory supplyAmts, uint fee) internal returns (uint[] finalAmts) { | ||||
|     function _getAtokens(address dsa, AaveInterface aave, address[] memory supplyTokens, uint[] memory supplyAmts) internal returns (uint[] memory finalAmts) { | ||||
|         for (uint i = 0; i < supplyTokens.length; i++) { | ||||
|             require(isSupportedToken[supplyTokens[i]], "token-not-enabled"); | ||||
|             (address _aToken, ,) = aaveData.getReserveTokensAddresses(supplyTokens[i]); | ||||
|             ATokenInterface aTokenContract = ATokenInterface(_aToken); | ||||
| 
 | ||||
|             // TODO: deduct the fee from finalAmt | ||||
|             uint _finalAmt; | ||||
|             if (supplyAmts[i] == uint(-1)) { | ||||
|                 // TODO: get maximum balance and set the return variable | ||||
|                 _finalAmt = aTokenContract.balanceOf(dsa); | ||||
|             } else { | ||||
|                 finalAmts[i] = supplyAmts[i]; | ||||
|                 _finalAmt = supplyAmts[i]; | ||||
|             } | ||||
| 
 | ||||
|             aTokenContract.transferFrom(sourceDsa, address(this), finalAmts[i]); | ||||
|             aTokenContract.transferFrom(dsa, address(this), finalAmts[i]); | ||||
| 
 | ||||
|             _finalAmt = wmul(_finalAmt, fee); | ||||
|             finalAmts[i] = _finalAmt; | ||||
| 
 | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     function _checkRatio(AaveData data, uint _safeRatioGap) returns (bool isOk) { | ||||
|         // TODO: Check the debt/collateral ratio should be less than "_safeRatioGap" from Liquidation of that particular user assets | ||||
|     function isPositionSafe() internal returns (bool isOk) { | ||||
|         // TODO: Check the final position health | ||||
|         // @mubaris we need to add the function from Aave to check the health should be "safeRatioGap"(currently set to 20%) below liquidation | ||||
|         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 | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -3,31 +3,30 @@ pragma experimental ABIEncoderV2; | |||
| 
 | ||||
| import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; | ||||
| import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; | ||||
| 
 | ||||
| import { TokenInterface } from "../../common/interfaces.sol"; | ||||
| import { Helpers } from "./helpers.sol"; | ||||
| import { AaveInterface, ATokenInterface } from "./interfaces.sol"; | ||||
| import { AaveInterface, ATokenInterface, IndexInterface } from "./interfaces.sol"; | ||||
| import { Events } from "./events.sol"; | ||||
| 
 | ||||
| contract LiquidityResolver is Helpers, Events { | ||||
|     using SafeERC20 for IERC20; | ||||
| 
 | ||||
|     mapping(address => mapping(address => uint)) public deposits; | ||||
| 
 | ||||
|     // This will be used to have debt/collateral ratio always 20% less than liquidation | ||||
|     // TODO: Is this number correct for it? | ||||
|     uint public safeRatioGap = 20000000000000000; // 20%? | ||||
| 
 | ||||
|     uint public fee = 200000000000000; // 0.2% on collateral? | ||||
| 
 | ||||
|     // InstaIndex Address. | ||||
|     IndexInterface public constant instaIndex = IndexInterface(0x2971AdFa57b20E5a416aE5a708A8655A9c74f723); | ||||
|     event variablesUpdate(uint _safeRatioGap, uint _fee); | ||||
| 
 | ||||
|     function updateVariables(uint _safeRatioGap, uint _fee) public { | ||||
|         require(msg.sender == instaIndex.master(), "not-master"); | ||||
|         safeRatioGap = _safeRatioGap; | ||||
|         fee = _fee; | ||||
|         // TODO: Add event | ||||
|         emit variablesUpdate(safeRatioGap, fee); | ||||
|     } | ||||
| 
 | ||||
|     function addTokenSupport(address[] memory _tokens) public { | ||||
|         require(msg.sender == instaIndex.master(), "not-master"); | ||||
|         for (uint i = 0; i < _tokens.length; i++) { | ||||
|             isSupportedToken[_tokens[i]] = true; | ||||
|         } | ||||
|         supportedTokens = _tokens; | ||||
|         // TODO: add event | ||||
|     } | ||||
| 
 | ||||
|     function spell(address _target, bytes memory _data) external { | ||||
|  | @ -46,25 +45,28 @@ contract LiquidityResolver is Helpers, Events { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // TODO: Deposited assets will get deposited into Aave as collateral | ||||
|     function deposit(address[] calldata tokens, uint[] calldata amts) external payable { | ||||
|         uint _length = tokens.length; | ||||
|         require(_length == amts.length, "invalid-length"); | ||||
| 
 | ||||
|         AaveInterface aave = AaveInterface(aaveProvider.getLendingPool()); | ||||
| 
 | ||||
|         uint[] memory _amts = new uint[](_length); | ||||
| 
 | ||||
|         for (uint256 i = 0; i < _length; i++) { | ||||
|             require(isSupportedToken[tokens[i]], "token-not-enabled"); | ||||
|             uint _amt; | ||||
|             address _token = tokens[i]; | ||||
|             if (_token == ethAddr) { | ||||
|                 require(msg.value == amts[i]); | ||||
|                 _amt = msg.value; | ||||
| 
 | ||||
|                 TokenInterface(wethAddr).deposit{value: msg.value}(); | ||||
|                 aave.deposit(wethAddr, _amt, address(this), 3288); | ||||
|             } 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); | ||||
|             } | ||||
| 
 | ||||
|             _amts[i] = _amt; | ||||
|  | @ -75,14 +77,16 @@ contract LiquidityResolver is Helpers, Events { | |||
|         emit LogDeposit(msg.sender, tokens, _amts); | ||||
|     } | ||||
| 
 | ||||
|     // TODO: If not enough ideal token then withdraw the required amount from Aave. Also, check that it should not make position risky | ||||
|     function withdraw(address[] calldata tokens, uint[] calldata amts) external { | ||||
|         uint _length = tokens.length; | ||||
|         require(_length == amts.length, "invalid-length"); | ||||
| 
 | ||||
|         AaveInterface aave = AaveInterface(aaveProvider.getLendingPool()); | ||||
| 
 | ||||
|         uint[] memory _amts = new uint[](_length); | ||||
| 
 | ||||
|         for (uint256 i = 0; i < _length; i++) { | ||||
|             require(isSupportedToken[tokens[i]], "token-not-enabled"); | ||||
|             uint _amt = amts[i]; | ||||
|             address _token = tokens[i]; | ||||
|             uint maxAmt = deposits[msg.sender][_token]; | ||||
|  | @ -91,11 +95,23 @@ contract LiquidityResolver is Helpers, Events { | |||
|                 _amt = maxAmt; | ||||
|             } | ||||
| 
 | ||||
|             // TODO: @everyone check this throughly. Saving 1000 WEI for flashloan WETH. Also, should we make a different contract to handle 2 WEI dydx gas, I think this would be better. | ||||
|             if (_token == ethAddr) { | ||||
|                 TokenInterface(wethAddr).withdraw(_amt); | ||||
|                 TokenInterface _tokenContract = TokenInterface(wethAddr); | ||||
|                 uint _ethBal = address(this).balance; | ||||
|                 uint _tknBal = _tokenContract.balanceOf(address(this)); | ||||
|                 if ((_ethBal + _tknBal + 1000) < _amt) { | ||||
|                     aave.withdraw(wethAddr, sub((_amt + 1000), (_tknBal + _ethBal)), address(this)); | ||||
|                 } | ||||
|                 _tokenContract.withdraw((sub(_amt, _ethBal))); | ||||
|                 msg.sender.call{value: _amt}(""); | ||||
|             } else { | ||||
|                 IERC20(_token).safeTransfer(msg.sender, _amt); | ||||
|                 IERC20 _tokenContract = IERC20(_token); | ||||
|                 uint _tknBal = _tokenContract.balanceOf(address(this)); | ||||
|                 if (_tknBal < _amt) { | ||||
|                     aave.withdraw(_token, sub(_amt, _tknBal), address(this)); | ||||
|                 } | ||||
|                 _tokenContract.safeTransfer(msg.sender, _amt); | ||||
|             } | ||||
| 
 | ||||
|             _amts[i] = _amt; | ||||
|  | @ -103,10 +119,13 @@ contract LiquidityResolver is Helpers, Events { | |||
|             deposits[msg.sender][_token] = sub(maxAmt, _amt); | ||||
|         } | ||||
| 
 | ||||
|         isPositionSafe(); | ||||
| 
 | ||||
|         emit LogWithdraw(msg.sender, tokens, _amts); | ||||
|     } | ||||
| 
 | ||||
|     // TODO: Things to factor | ||||
|     // TODO: @mubaris Things to factor | ||||
|     // use supportedTokens array to loop through | ||||
|     // If there is same token supply and borrow, then close the smaller one | ||||
|     // If there is ideal token then payback or deposit according to the position | ||||
|     // Object is the decrease the ratio and pay as less interest | ||||
|  | @ -141,7 +160,7 @@ contract MigrateResolver is LiquidityResolver { | |||
|         _PaybackStable(_data.borrowTokens.length, aave, _data.borrowTokens, stableBorrows, sourceDsa); | ||||
|         _PaybackVariable(_data.borrowTokens.length, aave, _data.borrowTokens, variableBorrows, sourceDsa); | ||||
| 
 | ||||
|         (uint[] totalSupplies) = _getAtokens(aave, _data.supplyTokens, _data.supplyAmts, fee); | ||||
|         (uint[] totalSupplies) = _getAtokens(sourceDsa, aave, _data.supplyTokens, _data.supplyAmts, fee); | ||||
| 
 | ||||
|         // Aave on Polygon doesn't have stable borrowing so we'll borrow all the debt in variable | ||||
|         AaveData memory data; | ||||
|  | @ -153,11 +172,13 @@ contract MigrateResolver is LiquidityResolver { | |||
|         data.targetDsa = _data.targetDsa; | ||||
|         data.borrowAmts = totalBorrows; | ||||
| 
 | ||||
|         // TODO: Check the amount that user is trying to migrate is 20% below the Liquidation | ||||
|         bool isOk = _checkRatio(data, safeRatioGap); | ||||
|         // Checks the amount that user is trying to migrate is 20% below the Liquidation | ||||
|         bool isOk = _checkRatio(data); | ||||
|         require(isOk, "position-risky-to-migrate"); | ||||
| 
 | ||||
|         bytes memory positionData = data; // TODO: Can we do anything else to make the data more secure? (It's secure already) | ||||
|         isPositionSafe(); | ||||
| 
 | ||||
|         bytes memory positionData = data; // TODO: @everyone Can we do anything else to make the data more secure? (It's secure already) | ||||
|         stateSender.syncState(polygonReceiver, positionData); | ||||
| 
 | ||||
|         emit LogAaveV2Migrate( | ||||
|  | @ -178,16 +199,19 @@ contract MigrateResolver is LiquidityResolver { | |||
|     function migrateWithFlash(AaveDataRaw calldata _data, uint ethAmt) external { | ||||
|         bytes data = abi.encode(_data, msg.sender, ethAmt); | ||||
|          | ||||
|         // TODO: integrate dydx flashloan and borrow "ethAmt" and transfer ETH to this address | ||||
|         // TODO: @everyone integrate dydx flashloan and borrow "ethAmt" and transfer ETH to this address | ||||
|         // Should we create a new contract for flashloan or interact directly from this contract? Mainly to resolve 2 WEI bug of dydx flashloan | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     // TODO: @everyone | ||||
|     function callFunction( | ||||
|         address sender, | ||||
|         Account.Info memory account, | ||||
|         bytes memory data | ||||
|     ) public override { | ||||
|         require(sender == address(this), "wrong-sender"); | ||||
|         // require(msg.sender == dydxFlash, "wrong-sender"); // TODO: msg.sender should be flashloan contract | ||||
|         (address l2DSA, AaveDataRaw memory _data, address sourceDsa, uint ethAmt) = abi.decode( | ||||
|             data, | ||||
|             (address, AaveDataRaw, address, uint) | ||||
|  |  | |||
							
								
								
									
										65
									
								
								contracts/senders2/aave-v2-migrator/variables.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								contracts/senders2/aave-v2-migrator/variables.sol
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,65 @@ | |||
| pragma solidity ^0.7.0; | ||||
| 
 | ||||
| import { | ||||
|     AaveLendingPoolProviderInterface, | ||||
|     AaveDataProviderInterface, | ||||
|     StateSenderInterface, | ||||
|     IndexInterface | ||||
| } from "./interfaces.sol"; | ||||
| 
 | ||||
| contract Variables { | ||||
| 
 | ||||
|     struct AaveDataRaw { | ||||
|         address targetDsa; | ||||
|         uint[] supplyAmts; | ||||
|         uint[] variableBorrowAmts; | ||||
|         uint[] stableBorrowAmts; | ||||
|         address[] supplyTokens; | ||||
|         address[] borrowTokens; | ||||
|     } | ||||
| 
 | ||||
|     struct AaveData { | ||||
|         address targetDsa; | ||||
|         uint[] supplyAmts; | ||||
|         uint[] borrowAmts; | ||||
|         address[] supplyTokens; | ||||
|         address[] borrowTokens; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @dev Aave referal code | ||||
|      */ | ||||
|     uint16 constant internal referralCode = 3228; | ||||
| 
 | ||||
|     address constant internal polygonReceiver = address(2); // Replace this | ||||
| 
 | ||||
|     // This will be used to have debt/collateral ratio always 20% less than liquidation | ||||
|     // TODO: Is this number correct for it? | ||||
|     // TODO: Add update function for this | ||||
|     uint public safeRatioGap = 20000000000000000; // 20%? | ||||
|     uint public fee = 998000000000000000; // 0.2% (99.8%) on collateral? TODO: Is this right? | ||||
|     // TODO: Set by construtor? | ||||
|     mapping(address => bool) public isSupportedToken; | ||||
|     address[] public supportedTokens; | ||||
| 
 | ||||
|     /** | ||||
|      * @dev Aave Provider | ||||
|      */ | ||||
|     AaveLendingPoolProviderInterface constant internal aaveProvider = AaveLendingPoolProviderInterface(0xB53C1a33016B2DC2fF3653530bfF1848a515c8c5); | ||||
| 
 | ||||
|     /** | ||||
|      * @dev Aave Data Provider | ||||
|      */ | ||||
|     AaveDataProviderInterface constant internal aaveData = AaveDataProviderInterface(0x057835Ad21a177dbdd3090bB1CAE03EaCF78Fc6d); | ||||
| 
 | ||||
|     /** | ||||
|      * @dev Polygon State Sync Contract | ||||
|      */ | ||||
|     StateSenderInterface constant internal stateSender = StateSenderInterface(0x28e4F3a7f651294B9564800b2D01f35189A5bFbE); | ||||
| 
 | ||||
|     mapping(address => mapping(address => uint)) public deposits; | ||||
| 
 | ||||
|     // InstaIndex Address. | ||||
|     IndexInterface public constant instaIndex = IndexInterface(0x2971AdFa57b20E5a416aE5a708A8655A9c74f723); | ||||
| 
 | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Samyak Jain
						Samyak Jain