From dad172e4b783c5bd414252d10b888edce3da843c Mon Sep 17 00:00:00 2001 From: Mubaris NK Date: Sun, 4 Apr 2021 08:43:47 +0530 Subject: [PATCH] [WIP] Receiver and implementation barebones --- .../aave-v2-migrator/helpers.sol | 31 +++++++ .../aave-v2-migrator/interfaces.sol | 86 +++++++++++++++++++ .../implementations/aave-v2-migrator/main.sol | 46 ++++++++++ contracts/receivers/aave-v2-receiver/main.sol | 34 ++++++++ .../senders/aave-v2-connector/interfaces.sol | 2 +- contracts/senders/aave-v2-connector/main.sol | 2 +- contracts/senders/aave-v2-migrator/main.sol | 14 +-- 7 files changed, 208 insertions(+), 7 deletions(-) create mode 100644 contracts/implementations/aave-v2-migrator/helpers.sol create mode 100644 contracts/implementations/aave-v2-migrator/interfaces.sol create mode 100644 contracts/implementations/aave-v2-migrator/main.sol create mode 100644 contracts/receivers/aave-v2-receiver/main.sol diff --git a/contracts/implementations/aave-v2-migrator/helpers.sol b/contracts/implementations/aave-v2-migrator/helpers.sol new file mode 100644 index 0000000..19a92e5 --- /dev/null +++ b/contracts/implementations/aave-v2-migrator/helpers.sol @@ -0,0 +1,31 @@ +pragma solidity ^0.7.0; + +import { DSMath } from "../../common/math.sol"; +import { Stores } from "../../common/stores.sol"; + +import { + AaveLendingPoolProviderInterface, + AaveDataProviderInterface, + AaveInterface +} from "./interfaces.sol"; + +abstract contract Helpers is DSMath, Stores { + /** + * @dev Aave referal code + */ + uint16 constant internal referalCode = 3228; + + /** + * @dev Aave Provider (TODO - Replace the address) + */ + AaveLendingPoolProviderInterface constant internal aaveProvider = AaveLendingPoolProviderInterface(0xB53C1a33016B2DC2fF3653530bfF1848a515c8c5); + + /** + * @dev Aave Data Provider (TODO - Replace the address) + */ + AaveDataProviderInterface constant internal aaveData = AaveDataProviderInterface(0x057835Ad21a177dbdd3090bB1CAE03EaCF78Fc6d); + + function getIsColl(address token, address user) internal view returns (bool isCol) { + (, , , , , , , , isCol) = aaveData.getUserReserveData(token, user); + } +} \ No newline at end of file diff --git a/contracts/implementations/aave-v2-migrator/interfaces.sol b/contracts/implementations/aave-v2-migrator/interfaces.sol new file mode 100644 index 0000000..5aef679 --- /dev/null +++ b/contracts/implementations/aave-v2-migrator/interfaces.sol @@ -0,0 +1,86 @@ +pragma solidity ^0.7.0; +pragma experimental ABIEncoderV2; + +interface AaveInterface { + function deposit(address _asset, uint256 _amount, address _onBehalfOf, uint16 _referralCode) external; + function withdraw(address _asset, uint256 _amount, address _to) external; + function borrow( + address _asset, + uint256 _amount, + uint256 _interestRateMode, + uint16 _referralCode, + address _onBehalfOf + ) external; + function repay(address _asset, uint256 _amount, uint256 _rateMode, address _onBehalfOf) external; + function setUserUseReserveAsCollateral(address _asset, bool _useAsCollateral) external; + function getUserAccountData(address user) external view returns ( + uint256 totalCollateralETH, + uint256 totalDebtETH, + uint256 availableBorrowsETH, + uint256 currentLiquidationThreshold, + uint256 ltv, + uint256 healthFactor + ); +} + +interface AaveLendingPoolProviderInterface { + function getLendingPool() external view returns (address); +} + +// Aave Protocol Data Provider +interface AaveDataProviderInterface { + function getReserveTokensAddresses(address _asset) external view returns ( + address aTokenAddress, + address stableDebtTokenAddress, + address variableDebtTokenAddress + ); + function getUserReserveData(address _asset, address _user) external view returns ( + uint256 currentATokenBalance, + uint256 currentStableDebt, + uint256 currentVariableDebt, + uint256 principalStableDebt, + uint256 scaledVariableDebt, + uint256 stableBorrowRate, + uint256 liquidityRate, + uint40 stableRateLastUpdated, + bool usageAsCollateralEnabled + ); + function getReserveConfigurationData(address asset) external view returns ( + uint256 decimals, + uint256 ltv, + uint256 liquidationThreshold, + uint256 liquidationBonus, + uint256 reserveFactor, + bool usageAsCollateralEnabled, + bool borrowingEnabled, + bool stableBorrowRateEnabled, + bool isActive, + bool isFrozen + ); +} + +interface AaveAddressProviderRegistryInterface { + function getAddressesProvidersList() external view returns (address[] memory); +} + +interface ATokenInterface { + function scaledBalanceOf(address _user) external view returns (uint256); + function isTransferAllowed(address _user, uint256 _amount) external view returns (bool); + function balanceOf(address _user) external view returns(uint256); + function transferFrom(address, address, uint) external returns (bool); + function approve(address, uint256) external; +} + +struct AaveData { + bool isFinal; + address targetDsa; + uint[] supplyAmts; + uint[] variableBorrowAmts; + uint[] stableBorrowAmts; + address[] supplyTokens; + address[] borrowTokens; +} + +interface ReceiverInterface { + function getPosition(address) external view returns (AaveData memory); +} \ No newline at end of file diff --git a/contracts/implementations/aave-v2-migrator/main.sol b/contracts/implementations/aave-v2-migrator/main.sol new file mode 100644 index 0000000..b8d960f --- /dev/null +++ b/contracts/implementations/aave-v2-migrator/main.sol @@ -0,0 +1,46 @@ +pragma solidity ^0.7.0; +pragma experimental ABIEncoderV2; + +import { TokenInterface, AccountInterface } from "../../common/interfaces.sol"; +import { AaveInterface, ReceiverInterface, AaveData } from "./interfaces.sol"; +import { Helpers } from "./helpers.sol"; + +contract AaveMigratorResolver is Helpers { + ReceiverInterface public immutable receiver; + + constructor(address _receiver) { + receiver = ReceiverInterface(_receiver); + } + + function migrateAave(address owner) external payable returns (bytes32) { + require(msg.sender == address(receiver) && AccountInterface(address(this)).isAuth(owner), "not-authorized"); + AaveData memory data = receiver.getPosition(owner); + require(!data.isFinal, "already-migrated"); + + AaveInterface aave = AaveInterface(aaveProvider.getLendingPool()); + + for (uint i = 0; i < data.supplyTokens.length; i++) { + TokenInterface token = TokenInterface(data.supplyTokens[i]); + uint amt = data.supplyAmts[i]; + token.approve(address(aave), amt); + + aave.deposit(address(token), amt, address(this), referralCode); + if (!getIsColl(address(token))) { + aave.setUserUseReserveAsCollateral(address(token), true); + } + } + + for (uint i = 0; i < data.borrowTokens.length; i++) { + address token = data.borrowTokens[i]; + uint variableAmt = data.variableBorrowAmts[i]; + uint stableAmt = data.stableBorrowAmts[i]; + + if (variableAmt > 0) { + aave.borrow(token, variableAmt, 2, referralCode, address(this)); + } + if (stableAmt > 0) { + aave.borrow(token, stableAmt, 1, referralCode, address(this)); + } + } + } +} \ No newline at end of file diff --git a/contracts/receivers/aave-v2-receiver/main.sol b/contracts/receivers/aave-v2-receiver/main.sol new file mode 100644 index 0000000..ee42d56 --- /dev/null +++ b/contracts/receivers/aave-v2-receiver/main.sol @@ -0,0 +1,34 @@ +pragma solidity ^0.7.0; +pragma experimental ABIEncoderV2; + +import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +contract MigrateResolver { + using SafeERC20 for IERC20; + + struct AaveData { + bool isFinal; + address targetDsa; + uint[] supplyAmts; + uint[] variableBorrowAmts; + uint[] stableBorrowAmts; + address[] supplyTokens; + address[] borrowTokens; + } + + uint private lastStateId; + mapping (address => AaveData) public positions; + + function onStateReceive(uint256 stateId, bytes calldata receivedData) external { + // require(stateId > lastStateId, "wrong-data"); + lastStateId = stateId; + + (address owner, AaveData memory data) = abi.decode(receivedData, (address, AaveData)); + positions[owner] = data; + } + + function getPosition(address owner) public view returns (AaveData memory data) { + data = positions[owner]; + } +} \ No newline at end of file diff --git a/contracts/senders/aave-v2-connector/interfaces.sol b/contracts/senders/aave-v2-connector/interfaces.sol index 0c1a495..ab92fcc 100644 --- a/contracts/senders/aave-v2-connector/interfaces.sol +++ b/contracts/senders/aave-v2-connector/interfaces.sol @@ -72,7 +72,7 @@ interface ATokenInterface { } interface AaveMigratorInterface { - function migrate(address, address[] calldata, address[] calldata) external; + function migrate(address, address, address[] calldata, address[] calldata) external; } // interface StateSenderInterface { diff --git a/contracts/senders/aave-v2-connector/main.sol b/contracts/senders/aave-v2-connector/main.sol index 7950cc2..0337bdd 100644 --- a/contracts/senders/aave-v2-connector/main.sol +++ b/contracts/senders/aave-v2-connector/main.sol @@ -23,7 +23,7 @@ contract AaveMigrateResolver is Helpers, Events { _aTokenContract.approve(address(migrator), _aTokenContract.balanceOf(address(this))); } - migrator.migrate(targetDsa, supplyTokens, borrowTokens); + migrator.migrate(msg.sender, targetDsa, supplyTokens, borrowTokens); _eventName = "LogAaveV2Migrate(address,address,address[],address[])"; _eventParam = abi.encode(msg.sender, targetDsa, supplyTokens, borrowTokens); diff --git a/contracts/senders/aave-v2-migrator/main.sol b/contracts/senders/aave-v2-migrator/main.sol index c96a20b..60efb26 100644 --- a/contracts/senders/aave-v2-migrator/main.sol +++ b/contracts/senders/aave-v2-migrator/main.sol @@ -4,7 +4,6 @@ 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"; @@ -48,6 +47,7 @@ contract MigrateResolver is LiquidityResolver { mapping (address => AaveData) public positions; function migrate( + address owner, address targetDsa, address[] calldata supplyTokens, address[] calldata borrowTokens @@ -72,8 +72,12 @@ contract MigrateResolver is LiquidityResolver { address _token = supplyTokens[i] == ethAddr ? wethAddr : supplyTokens[i]; (address _aToken, ,) = aaveData.getReserveTokensAddresses(_token); + ATokenInterface aTokenContract = ATokenInterface(_aToken); + data.supplyTokens[i] = _token; - data.supplyAmts[i] = ATokenInterface(_aToken).balanceOf(sourceDsa); + data.supplyAmts[i] = aTokenContract.balanceOf(sourceDsa); + + aTokenContract.transferFrom(msg.sender, address(this), data.supplyAmts[i]); } if (borrowTokens.length > 0) { @@ -94,7 +98,7 @@ contract MigrateResolver is LiquidityResolver { uint totalBorrowAmt = add(data.stableBorrowAmts[i], data.variableBorrowAmts[i]); if (totalBorrowAmt > 0) { - TokenInterface(_token).approve(address(aave), totalBorrowAmt); + IERC20(_token).safeApprove(address(aave), totalBorrowAmt); } } @@ -104,8 +108,8 @@ contract MigrateResolver is LiquidityResolver { _Withdraw(supplyTokens.length, aave, data.supplyTokens, data.supplyAmts); - positions[sourceDsa] = data; - bytes memory positionData = abi.encode(sourceDsa, data); + positions[owner] = data; + bytes memory positionData = abi.encode(owner, data); stateSender.syncState(polygonReceiver, positionData); } } \ No newline at end of file