mirror of
https://github.com/Instadapp/dsa-connectors.git
synced 2024-07-29 22:37:00 +00:00
Aave-v3 to Notional refinance
This commit is contained in:
parent
fbca8bdfe3
commit
7b002f9704
|
|
@ -5,6 +5,8 @@ import { TokenInterface } from "./interface.sol";
|
|||
|
||||
contract Events {
|
||||
event LogRefinance(
|
||||
uint256 indexed source,
|
||||
uint256 indexed target,
|
||||
uint256 collateralFee,
|
||||
uint256 debtFee,
|
||||
address[] tokens,
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ pragma experimental ABIEncoderV2;
|
|||
|
||||
// import { Helpers } from "./helpers.sol";
|
||||
import { Basic } from "../../common/basic.sol";
|
||||
import { Token, NotionalInterface, BalanceAction, BalanceActionWithTrades, DepositActionType, AaveV2LendingPoolProviderInterface, AaveV2DataProviderInterface, AaveV2Interface } from "./interface.sol";
|
||||
import { Token, NotionalInterface, BalanceAction, BalanceActionWithTrades, DepositActionType, AaveV2LendingPoolProviderInterface, AaveV2DataProviderInterface, AaveV2Interface, AaveV3PoolProviderInterface, AaveV3Interface, AaveV3DataProviderInterface } from "./interface.sol";
|
||||
import { TokenInterface } from "../../common/interfaces.sol";
|
||||
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
|
||||
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||
|
|
@ -12,6 +12,13 @@ import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|||
contract Helpers is Basic {
|
||||
using SafeERC20 for IERC20;
|
||||
|
||||
enum Protocol {
|
||||
AaveV2,
|
||||
AaveV3,
|
||||
Compound,
|
||||
Notional
|
||||
}
|
||||
|
||||
uint256 internal constant LEND_TRADE = 0;
|
||||
uint256 internal constant BORROW_TRADE = 1;
|
||||
uint256 internal constant INTERNAL_TOKEN_PRECISION = 1e8;
|
||||
|
|
@ -21,7 +28,7 @@ contract Helpers is Basic {
|
|||
address payable constant feeCollector =
|
||||
0xb1DC62EC38E6E3857a887210C38418E4A17Da5B2;
|
||||
|
||||
AaveV2DataProviderInterface internal constant aaveData =
|
||||
AaveV2DataProviderInterface internal constant aaveV2Data =
|
||||
AaveV2DataProviderInterface(0x057835Ad21a177dbdd3090bB1CAE03EaCF78Fc6d);
|
||||
|
||||
NotionalInterface internal constant notional =
|
||||
|
|
@ -34,6 +41,17 @@ contract Helpers is Basic {
|
|||
AaveV2LendingPoolProviderInterface(
|
||||
0xB53C1a33016B2DC2fF3653530bfF1848a515c8c5
|
||||
);
|
||||
/**
|
||||
* @dev Aave V3 Pool Provider
|
||||
*/
|
||||
AaveV3PoolProviderInterface internal constant getAaveV3Provider =
|
||||
AaveV3PoolProviderInterface(0xA55125A90d75a95EC00130E8E8C197dB5641Eb19); //rinkeby address
|
||||
|
||||
/**
|
||||
* @dev Aave V3 Pool Data Provider
|
||||
*/
|
||||
AaveV3DataProviderInterface internal constant aaveV3Data =
|
||||
AaveV3DataProviderInterface(0x256bBbeDbA70a1240a1EB64210abB1b063267408); //rinkeby address
|
||||
|
||||
/**
|
||||
* @dev get Referral Code
|
||||
|
|
@ -41,6 +59,9 @@ contract Helpers is Basic {
|
|||
uint16 internal constant getReferralCode = 3228;
|
||||
|
||||
struct NotionalBorrowData {
|
||||
// refinance to Notional from source
|
||||
Protocol source;
|
||||
// length of tokens
|
||||
uint256 length;
|
||||
// debt fee
|
||||
uint256 fee;
|
||||
|
|
@ -73,6 +94,17 @@ contract Helpers is Basic {
|
|||
);
|
||||
}
|
||||
|
||||
// withdraw balance of Aave v3
|
||||
function getWithdrawBalanceV3(
|
||||
AaveV3DataProviderInterface aaveData,
|
||||
address token
|
||||
) internal view returns (uint256 bal) {
|
||||
(bal, , , , , , , , ) = aaveData.getUserReserveData(
|
||||
token,
|
||||
address(this)
|
||||
);
|
||||
}
|
||||
|
||||
function getAssetOrUnderlyingToken(uint16 currencyId, bool underlying)
|
||||
internal
|
||||
view
|
||||
|
|
@ -109,12 +141,29 @@ contract Helpers is Basic {
|
|||
returns (uint256 bal)
|
||||
{
|
||||
if (rateMode == 1) {
|
||||
(, bal, , , , , , , ) = aaveData.getUserReserveData(
|
||||
(, bal, , , , , , , ) = aaveV2Data.getUserReserveData(
|
||||
token,
|
||||
address(this)
|
||||
);
|
||||
} else {
|
||||
(, , bal, , , , , , ) = aaveData.getUserReserveData(
|
||||
(, , bal, , , , , , ) = aaveV2Data.getUserReserveData(
|
||||
token,
|
||||
address(this)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function getAaveV3PaybackAmt(uint256 rateMode, address token)
|
||||
internal
|
||||
returns (uint256 bal)
|
||||
{
|
||||
if (rateMode == 1) {
|
||||
(, bal, , , , , , , ) = aaveV3Data.getUserReserveData(
|
||||
token,
|
||||
address(this)
|
||||
);
|
||||
} else {
|
||||
(, , bal, , , , , , ) = aaveV3Data.getUserReserveData(
|
||||
token,
|
||||
address(this)
|
||||
);
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { Helpers } from "../helpers.sol";
|
|||
import { AaveV2DataProviderInterface, AaveV2LendingPoolProviderInterface, AaveV2Interface } from "../interface.sol";
|
||||
import { TokenInterface } from "../../../common/interfaces.sol";
|
||||
|
||||
contract AaveHelpers is Helpers {
|
||||
contract AaveV2Helpers is Helpers {
|
||||
// payback token to Aave V2, amts sent already checked for MAX
|
||||
function _aaveV2PaybackOne(
|
||||
AaveV2Interface aave,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,72 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.6;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import { Helpers } from "../helpers.sol";
|
||||
|
||||
import { AaveV3DataProviderInterface, AaveV3PoolProviderInterface, AaveV3Interface } from "../interface.sol";
|
||||
import { TokenInterface } from "../../../common/interfaces.sol";
|
||||
|
||||
contract AaveV3Helpers is Helpers {
|
||||
// payback token to Aave V2, amts sent already checked for MAX
|
||||
function _aaveV3PaybackOne(
|
||||
AaveV3Interface aave,
|
||||
TokenInterface token,
|
||||
uint256 amt,
|
||||
uint256 rateMode
|
||||
) internal {
|
||||
if (amt > 0) {
|
||||
bool isEth = address(token) == wethAddr;
|
||||
if (isEth) convertEthToWeth(isEth, token, amt);
|
||||
approve(token, address(aave), amt);
|
||||
aave.repay(address(token), amt, rateMode, address(this));
|
||||
}
|
||||
}
|
||||
|
||||
function _aaveV3Payback(
|
||||
uint256 length,
|
||||
AaveV3Interface aave,
|
||||
TokenInterface[] memory tokens,
|
||||
uint256[] memory amts,
|
||||
uint256[] memory rateModes
|
||||
) internal {
|
||||
for (uint256 i = 0; i < length; i++) {
|
||||
_aaveV3PaybackOne(aave, tokens[i], amts[i], rateModes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// withdraw aToken from aaveV2
|
||||
function _aaveV3WithdrawOne(
|
||||
AaveV3Interface aave,
|
||||
AaveV3DataProviderInterface aaveData,
|
||||
TokenInterface token,
|
||||
uint256 amt
|
||||
) internal returns (uint256 _amt) {
|
||||
if (amt > 0) {
|
||||
bool isEth = address(token) == wethAddr;
|
||||
aave.withdraw(address(token), amt, address(this));
|
||||
_amt = amt == uint256(-1)
|
||||
? getWithdrawBalanceV3(aaveData, address(token))
|
||||
: amt;
|
||||
convertWethToEth(isEth, token, _amt);
|
||||
}
|
||||
}
|
||||
|
||||
function _aaveV3Withdraw(
|
||||
AaveV3Interface aave,
|
||||
AaveV3DataProviderInterface aaveData,
|
||||
uint256 length,
|
||||
TokenInterface[] memory tokens,
|
||||
uint256[] memory amts
|
||||
) internal returns (uint256[] memory) {
|
||||
uint256[] memory finalAmts = new uint256[](length);
|
||||
for (uint256 i = 0; i < length; i++) {
|
||||
finalAmts[i] = _aaveV3WithdrawOne(
|
||||
aave,
|
||||
aaveData,
|
||||
tokens[i],
|
||||
amts[i]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -52,7 +52,16 @@ contract NotionalHelpers is Helpers {
|
|||
|
||||
//calculating payback amounts for Aave v2
|
||||
if (_amt == uint256(-1)) {
|
||||
_amt = getAaveV2PaybackAmt(data.rateModes[i], data.tokens[i]);
|
||||
if (data.source == Protocol.AaveV2)
|
||||
_amt = getAaveV2PaybackAmt(
|
||||
data.rateModes[i],
|
||||
data.tokens[i]
|
||||
);
|
||||
else if(data.source == Protocol.AaveV3)
|
||||
_amt = getAaveV3PaybackAmt(
|
||||
data.rateModes[i],
|
||||
data.tokens[i]
|
||||
);
|
||||
}
|
||||
finalAmts[i] = _amt;
|
||||
|
||||
|
|
|
|||
|
|
@ -169,4 +169,81 @@ interface AaveV2Interface {
|
|||
|
||||
interface AaveV2LendingPoolProviderInterface {
|
||||
function getLendingPool() external view returns (address);
|
||||
}
|
||||
|
||||
// Aave V3 interfaces
|
||||
interface AaveV3Interface {
|
||||
function supply(
|
||||
address asset,
|
||||
uint256 amount,
|
||||
address onBehalfOf,
|
||||
uint16 referralCode
|
||||
) external;
|
||||
|
||||
function withdraw(
|
||||
address asset,
|
||||
uint256 amount,
|
||||
address to
|
||||
) external returns (uint256);
|
||||
|
||||
function borrow(
|
||||
address asset,
|
||||
uint256 amount,
|
||||
uint256 interestRateMode,
|
||||
uint16 referralCode,
|
||||
address onBehalfOf
|
||||
) external;
|
||||
|
||||
function repay(
|
||||
address asset,
|
||||
uint256 amount,
|
||||
uint256 interestRateMode,
|
||||
address onBehalfOf
|
||||
) external returns (uint256);
|
||||
|
||||
function repayWithATokens(
|
||||
address asset,
|
||||
uint256 amount,
|
||||
uint256 interestRateMode
|
||||
) external returns (uint256);
|
||||
|
||||
function setUserUseReserveAsCollateral(address asset, bool useAsCollateral)
|
||||
external;
|
||||
|
||||
function setUserEMode(uint8 categoryId) external;
|
||||
}
|
||||
|
||||
interface AaveV3PoolProviderInterface {
|
||||
function getPool() external view returns (address);
|
||||
}
|
||||
|
||||
interface AaveV3DataProviderInterface {
|
||||
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 getReserveEModeCategory(address asset)
|
||||
external
|
||||
view
|
||||
returns (uint256);
|
||||
}
|
||||
|
|
@ -3,16 +3,19 @@ pragma solidity ^0.7.6;
|
|||
pragma experimental ABIEncoderV2;
|
||||
|
||||
/**
|
||||
* @title Refinance Notional, Aave v2.
|
||||
* @dev Refinancing.
|
||||
* @title Refinance.
|
||||
* @dev Refinancing among Notional, Aave v2, Aave v3.
|
||||
*/
|
||||
import { AaveV2Interface, AaveV2DataProviderInterface, AaveV2LendingPoolProviderInterface } from "./interface.sol";
|
||||
import { AaveV2Interface, AaveV2DataProviderInterface, AaveV2LendingPoolProviderInterface, AaveV3Interface, AaveV3DataProviderInterface, AaveV3PoolProviderInterface } from "./interface.sol";
|
||||
import { TokenInterface } from "../../common/interfaces.sol";
|
||||
import { AaveHelpers } from "./helpers/aaveV2.sol";
|
||||
import { AaveV2Helpers } from "./helpers/aaveV2.sol";
|
||||
import { AaveV3Helpers } from "./helpers/aaveV3.sol";
|
||||
import { NotionalHelpers } from "./helpers/notional.sol";
|
||||
|
||||
contract RefinanceResolver is AaveHelpers, NotionalHelpers {
|
||||
contract RefinanceResolver is AaveV2Helpers, AaveV3Helpers, NotionalHelpers {
|
||||
struct RefinanceData {
|
||||
Protocol source;
|
||||
Protocol target;
|
||||
uint256 collateralFee;
|
||||
uint256 debtFee;
|
||||
uint256[] currencyIDs;
|
||||
|
|
@ -27,8 +30,10 @@ contract RefinanceResolver is AaveHelpers, NotionalHelpers {
|
|||
}
|
||||
|
||||
struct RefinanceInternalData {
|
||||
AaveV2Interface aave;
|
||||
AaveV2DataProviderInterface aaveData;
|
||||
AaveV2Interface aaveV2;
|
||||
AaveV2DataProviderInterface aaveV2Data;
|
||||
AaveV3Interface aaveV3;
|
||||
AaveV3DataProviderInterface aaveV3Data;
|
||||
uint256[] depositAmts;
|
||||
uint256[] paybackAmts;
|
||||
address[] tokens;
|
||||
|
|
@ -53,11 +58,15 @@ contract RefinanceResolver is AaveHelpers, NotionalHelpers {
|
|||
require(data.mintNTokens.length == length, "length-mismatch");
|
||||
|
||||
RefinanceInternalData memory refinanceInternalData;
|
||||
refinanceInternalData.aave = AaveV2Interface(
|
||||
refinanceInternalData.aaveV2 = AaveV2Interface(
|
||||
AaveV2LendingPoolProviderInterface(getAaveV2Provider)
|
||||
.getLendingPool()
|
||||
);
|
||||
refinanceInternalData.aaveData = aaveData;
|
||||
refinanceInternalData.aaveV2Data = aaveV2Data;
|
||||
refinanceInternalData.aaveV3 = AaveV3Interface(
|
||||
AaveV3PoolProviderInterface(getAaveV3Provider).getPool()
|
||||
);
|
||||
refinanceInternalData.aaveV3Data = aaveV3Data;
|
||||
|
||||
refinanceInternalData.depositAmts;
|
||||
refinanceInternalData.paybackAmts;
|
||||
|
|
@ -69,51 +78,108 @@ contract RefinanceResolver is AaveHelpers, NotionalHelpers {
|
|||
);
|
||||
|
||||
// Aave v2 to Notional
|
||||
NotionalBorrowData memory _notionalBorrowData;
|
||||
if (
|
||||
data.source == Protocol.AaveV2 && data.target == Protocol.Notional
|
||||
) {
|
||||
NotionalBorrowData memory _notionalBorrowData;
|
||||
|
||||
_notionalBorrowData.length = length;
|
||||
_notionalBorrowData.fee = data.debtFee;
|
||||
_notionalBorrowData.tokens = refinanceInternalData.tokens;
|
||||
_notionalBorrowData.redeemToUnderlying = data.redeemBorrowToUnderlying;
|
||||
_notionalBorrowData.amts = data.borrowAmts;
|
||||
_notionalBorrowData.rateModes = data.paybackRateModes;
|
||||
_notionalBorrowData.fCashAmount = data.borrowfCashAmts;
|
||||
_notionalBorrowData.maxBorrowRate = data.maxBorrowingRates;
|
||||
_notionalBorrowData.currencyIDs = data.currencyIDs;
|
||||
_notionalBorrowData.marketIndex = data.borrowMarketIndices;
|
||||
_notionalBorrowData.length = length;
|
||||
_notionalBorrowData.source = data.source;
|
||||
_notionalBorrowData.fee = data.debtFee;
|
||||
_notionalBorrowData.tokens = refinanceInternalData.tokens;
|
||||
_notionalBorrowData.redeemToUnderlying = data
|
||||
.redeemBorrowToUnderlying;
|
||||
_notionalBorrowData.amts = data.borrowAmts;
|
||||
_notionalBorrowData.rateModes = data.paybackRateModes;
|
||||
_notionalBorrowData.fCashAmount = data.borrowfCashAmts;
|
||||
_notionalBorrowData.maxBorrowRate = data.maxBorrowingRates;
|
||||
_notionalBorrowData.currencyIDs = data.currencyIDs;
|
||||
_notionalBorrowData.marketIndex = data.borrowMarketIndices;
|
||||
|
||||
//borrow on Notional
|
||||
refinanceInternalData.paybackAmts = _notionalBorrow(
|
||||
_notionalBorrowData
|
||||
);
|
||||
//payback debt on Aave-v2
|
||||
_aaveV2Payback(
|
||||
length,
|
||||
refinanceInternalData.aave,
|
||||
refinanceInternalData.tokenInterfaces,
|
||||
refinanceInternalData.paybackAmts,
|
||||
data.paybackRateModes
|
||||
);
|
||||
//withdraw aTokens from Aave-v2
|
||||
refinanceInternalData.depositAmts = _aaveV2Withdraw(
|
||||
refinanceInternalData.aave,
|
||||
refinanceInternalData.aaveData,
|
||||
length,
|
||||
refinanceInternalData.tokenInterfaces,
|
||||
data.withdrawAmts
|
||||
);
|
||||
//deposit on Notional
|
||||
_notionalDeposit(
|
||||
length,
|
||||
data.collateralFee,
|
||||
data.currencyIDs,
|
||||
refinanceInternalData.depositAmts,
|
||||
refinanceInternalData.tokens,
|
||||
data.mintNTokens
|
||||
);
|
||||
//borrow on Notional
|
||||
refinanceInternalData.paybackAmts = _notionalBorrow(
|
||||
_notionalBorrowData
|
||||
);
|
||||
//payback debt on Aave-v2
|
||||
_aaveV2Payback(
|
||||
length,
|
||||
refinanceInternalData.aaveV2,
|
||||
refinanceInternalData.tokenInterfaces,
|
||||
refinanceInternalData.paybackAmts,
|
||||
data.paybackRateModes
|
||||
);
|
||||
//withdraw aTokens from Aave-v2
|
||||
refinanceInternalData.depositAmts = _aaveV2Withdraw(
|
||||
refinanceInternalData.aaveV2,
|
||||
refinanceInternalData.aaveV2Data,
|
||||
length,
|
||||
refinanceInternalData.tokenInterfaces,
|
||||
data.withdrawAmts
|
||||
);
|
||||
//deposit on Notional
|
||||
_notionalDeposit(
|
||||
length,
|
||||
data.collateralFee,
|
||||
data.currencyIDs,
|
||||
refinanceInternalData.depositAmts,
|
||||
refinanceInternalData.tokens,
|
||||
data.mintNTokens
|
||||
);
|
||||
}
|
||||
// Aave v3 to Notional
|
||||
else if (
|
||||
data.source == Protocol.AaveV3 && data.target == Protocol.Notional
|
||||
) {
|
||||
NotionalBorrowData memory _notionalBorrowData;
|
||||
|
||||
_notionalBorrowData.length = length;
|
||||
_notionalBorrowData.source = data.source;
|
||||
_notionalBorrowData.fee = data.debtFee;
|
||||
_notionalBorrowData.tokens = refinanceInternalData.tokens;
|
||||
_notionalBorrowData.redeemToUnderlying = data
|
||||
.redeemBorrowToUnderlying;
|
||||
_notionalBorrowData.amts = data.borrowAmts;
|
||||
_notionalBorrowData.rateModes = data.paybackRateModes;
|
||||
_notionalBorrowData.fCashAmount = data.borrowfCashAmts;
|
||||
_notionalBorrowData.maxBorrowRate = data.maxBorrowingRates;
|
||||
_notionalBorrowData.currencyIDs = data.currencyIDs;
|
||||
_notionalBorrowData.marketIndex = data.borrowMarketIndices;
|
||||
|
||||
//borrow on Notional
|
||||
refinanceInternalData.paybackAmts = _notionalBorrow(
|
||||
_notionalBorrowData
|
||||
);
|
||||
//payback debt on Aave-v3
|
||||
_aaveV3Payback(
|
||||
length,
|
||||
refinanceInternalData.aaveV3,
|
||||
refinanceInternalData.tokenInterfaces,
|
||||
refinanceInternalData.paybackAmts,
|
||||
data.paybackRateModes
|
||||
);
|
||||
//withdraw aTokens from Aave-v3
|
||||
refinanceInternalData.depositAmts = _aaveV3Withdraw(
|
||||
refinanceInternalData.aaveV3,
|
||||
refinanceInternalData.aaveV3Data,
|
||||
length,
|
||||
refinanceInternalData.tokenInterfaces,
|
||||
data.withdrawAmts
|
||||
);
|
||||
//deposit on Notional
|
||||
_notionalDeposit(
|
||||
length,
|
||||
data.collateralFee,
|
||||
data.currencyIDs,
|
||||
refinanceInternalData.depositAmts,
|
||||
refinanceInternalData.tokens,
|
||||
data.mintNTokens
|
||||
);
|
||||
}
|
||||
|
||||
_eventName = "LogRefinance(uint,uint,address[],uint[],uint[],uint[],uint[])";
|
||||
_eventParam = abi.encode(
|
||||
uint256(data.source),
|
||||
uint256(data.target),
|
||||
data.collateralFee,
|
||||
data.debtFee,
|
||||
refinanceInternalData.tokens,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user