dsa-polygon-migration/contracts/receivers/aave-v2-receiver/helpers.sol

145 lines
6.4 KiB
Solidity
Raw Normal View History

2021-04-05 00:33:23 +00:00
pragma solidity >=0.7.0;
2021-04-15 10:39:23 +00:00
pragma experimental ABIEncoderV2;
2021-04-05 00:33:23 +00:00
import { DSMath } from "../../common/math.sol";
2021-04-07 00:22:28 +00:00
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
2021-04-07 23:45:00 +00:00
import { Stores } from "../../common/stores-polygon.sol";
import { Variables } from "./variables.sol";
2021-04-07 00:22:28 +00:00
import {
TokenMappingInterface,
AaveData,
AaveDataProviderInterface,
2021-04-12 06:02:42 +00:00
AaveInterface,
AccountInterface
2021-04-07 00:22:28 +00:00
} from "./interfaces.sol";
2021-04-05 00:33:23 +00:00
2021-04-07 23:45:00 +00:00
abstract contract Helpers is Stores, DSMath, Variables {
2021-04-07 00:22:28 +00:00
using SafeERC20 for IERC20;
2021-04-15 10:39:23 +00:00
struct TransferHelperData {
address token;
address atoken;
uint atokenBal;
uint supplyAmt;
uint tokenLiq;
}
struct SpellHelperData {
address token;
address atoken;
uint tokenLiq;
uint borrowAmt;
}
2021-04-07 00:22:28 +00:00
function remapTokens(AaveData memory data) internal view returns (AaveData memory) {
2021-04-05 00:33:23 +00:00
for (uint i = 0; i < data.supplyTokens.length; i++) {
data.supplyTokens[i] = tokenMapping.getMapping(data.supplyTokens[i]);
}
for (uint i = 0; i < data.borrowTokens.length; i++) {
data.borrowTokens[i] = tokenMapping.getMapping(data.borrowTokens[i]);
}
return data;
}
2021-04-07 00:22:28 +00:00
function getCollateralStatus(address token, address user) internal view returns (bool enabled) {
(uint bal, , , , , , , , bool isCol) = aaveData.getUserReserveData(token, user);
enabled = bal > 0 && !isCol;
}
function isPositionSafe() internal view returns (bool isOk) {
2021-04-12 06:02:42 +00:00
AaveInterface aave = AaveInterface(aaveProvider.getLendingPool());
(,,,,,uint healthFactor) = aave.getUserAccountData(address(this));
uint minLimit = wdiv(1e18, safeRatioGap);
isOk = healthFactor > minLimit;
2021-04-07 15:28:21 +00:00
require(isOk, "position-at-risk");
}
2021-04-07 23:45:00 +00:00
function transferAtokens(AaveInterface aave, address dsa, address[] memory supplyTokens, uint[] memory supplyAmts) internal {
2021-04-07 00:22:28 +00:00
for (uint i = 0; i < supplyTokens.length; i++) {
2021-04-15 10:39:23 +00:00
TransferHelperData memory data;
data.token = supplyTokens[i] == maticAddr ? wmaticAddr : supplyTokens[i];
(data.atoken, ,) = aaveData.getReserveTokensAddresses(data.token);
IERC20 _atokenContract = IERC20(data.atoken);
IERC20 _tokenContract = IERC20(data.token);
2021-04-15 10:39:23 +00:00
data.atokenBal = _atokenContract.balanceOf(address(this));
data.supplyAmt = supplyAmts[i];
(data.tokenLiq,,,,,,,,,) = aaveData.getReserveData(data.token);
if (data.atokenBal < data.supplyAmt) {
uint _reqAmt = data.supplyAmt - data.atokenBal;
uint num = _reqAmt/data.tokenLiq + 1; // TODO: Is this right
2021-04-07 00:22:28 +00:00
uint splitAmt = _reqAmt/num; // TODO: Check decimal
uint finalSplit = _reqAmt - (splitAmt * (num - 1)); // TODO: to resolve upper decimal error
_tokenContract.approve(address(aave), _reqAmt);
2021-04-07 00:22:28 +00:00
for (uint j = 0; j < num; j++) {
2021-04-12 06:02:42 +00:00
if (j < num - 1) {
2021-04-15 10:39:23 +00:00
aave.borrow(data.token, splitAmt, 2, 3288, address(this));
aave.deposit(data.token, splitAmt, address(this), 3288);
if (j == 0) aave.setUserUseReserveAsCollateral(data.token, true);
2021-04-07 00:22:28 +00:00
} else {
2021-04-15 10:39:23 +00:00
aave.borrow(data.token, finalSplit, 2, 3288, address(this));
aave.deposit(data.token, finalSplit, address(this), 3288);
2021-04-07 00:22:28 +00:00
}
}
}
2021-04-15 10:39:23 +00:00
_atokenContract.safeTransfer(dsa, data.supplyAmt);
2021-04-07 00:22:28 +00:00
}
}
function borrowAndTransferSpells(AaveInterface aave, address dsa, address[] memory supplyTokens, address[] memory borrowTokens, uint[] memory borrowAmts) internal {
2021-04-07 00:22:28 +00:00
for (uint i = 0; i < borrowTokens.length; i++) {
2021-04-15 10:39:23 +00:00
SpellHelperData memory data;
data.token = borrowTokens[i] == maticAddr ? wmaticAddr : borrowTokens[i];
(data.atoken, ,) = aaveData.getReserveTokensAddresses(data.token);
(data.tokenLiq,,,,,,,,,) = aaveData.getReserveData(data.token);
data.borrowAmt = borrowAmts[i];
2021-04-07 00:22:28 +00:00
// TODO: Check number of loops needed. Borrow and supply on user's account.
2021-04-15 10:39:23 +00:00
uint num = data.borrowAmt/data.tokenLiq + 1; // TODO: Is this right
uint splitAmt = data.borrowAmt/num; // TODO: Check decimal
uint finalSplit = data.borrowAmt - (splitAmt * (num - 1)); // TODO: to resolve upper decimal error
2021-04-07 00:22:28 +00:00
uint spellsAmt = num <= 1 ? (2 * (num + 1)) : (2 * (num + 1)) + 1;
2021-04-07 00:22:28 +00:00
string[] memory targets = new string[](spellsAmt);
bytes[] memory castData = new bytes[](spellsAmt);
targets[0] = "AAVE-V2-A";
castData[0] = abi.encodeWithSignature("enableCollateral(address[])", supplyTokens);
2021-04-07 00:22:28 +00:00
for (uint j = 0; j < num; j++) {
uint skip = 0;
uint k = j * 2 + 1 + skip;
2021-04-07 00:22:28 +00:00
if (i < num - 1) {
2021-04-13 23:10:01 +00:00
targets[k] = "AAVE-V2-A";
2021-04-15 10:39:23 +00:00
castData[k] = abi.encodeWithSignature("borrow(address,uint256,uint256,uint256,uint256)", data.token, splitAmt, 2, 0, 0);
2021-04-13 23:10:01 +00:00
targets[k+1] = "AAVE-V2-A";
2021-04-15 10:39:23 +00:00
castData[k+1] = abi.encodeWithSignature("deposit(address,uint256,uint256,uint256)", data.token, splitAmt, 0, 0);
if (j == 0) {
skip = 1;
targets[k+1] = "AAVE-V2-A";
castData[k+1] = abi.encodeWithSignature("enableCollateral(address[])", data.token, splitAmt, 0, 0);
}
2021-04-07 00:22:28 +00:00
} else {
2021-04-13 23:10:01 +00:00
targets[k] = "AAVE-V2-A";
2021-04-15 10:39:23 +00:00
castData[k] = abi.encodeWithSignature("borrow(address,uint256,uint256,uint256,uint256)", data.token, finalSplit, 2, 0, 0);
2021-04-13 23:10:01 +00:00
targets[k+1] = "AAVE-V2-A";
2021-04-15 10:39:23 +00:00
castData[k+1] = abi.encodeWithSignature("deposit(address,uint256,uint256,uint256)", data.token, finalSplit, 0, 0);
2021-04-07 00:22:28 +00:00
}
}
2021-04-07 23:45:00 +00:00
2021-04-15 22:52:33 +00:00
targets[spellsAmt - 1] = "BASIC-A"; // TODO: right spell?
castData[spellsAmt - 1] = abi.encodeWithSignature("withdraw(address,uint256,address,uint256,uint256)", data.atoken, data.borrowAmt, address(this), 0, 0); // encode the data of atoken withdrawal
2021-04-12 06:02:42 +00:00
AccountInterface(dsa).castMigrate(targets, castData, address(this));
2021-04-07 00:22:28 +00:00
}
2021-04-07 23:45:00 +00:00
2021-04-07 00:22:28 +00:00
}
2021-04-05 00:33:23 +00:00
}