mirror of
https://github.com/Instadapp/dsa-connectors.git
synced 2024-07-29 22:37:00 +00:00
notional-aaveV2 refinance
This commit is contained in:
parent
ae51a19713
commit
fbca8bdfe3
16
contracts/mainnet/connectors/refinance-notional/events.sol
Normal file
16
contracts/mainnet/connectors/refinance-notional/events.sol
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.6;
|
||||
|
||||
import { TokenInterface } from "./interface.sol";
|
||||
|
||||
contract Events {
|
||||
event LogRefinance(
|
||||
uint256 collateralFee,
|
||||
uint256 debtFee,
|
||||
address[] tokens,
|
||||
uint256[] borrowAmts,
|
||||
uint256[] depositAmts,
|
||||
uint256[] borrowMarketIndices,
|
||||
uint256[] maxBorrowingRates
|
||||
);
|
||||
}
|
||||
194
contracts/mainnet/connectors/refinance-notional/helpers.sol
Normal file
194
contracts/mainnet/connectors/refinance-notional/helpers.sol
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.6;
|
||||
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 { TokenInterface } from "../../common/interfaces.sol";
|
||||
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
|
||||
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||
|
||||
contract Helpers is Basic {
|
||||
using SafeERC20 for IERC20;
|
||||
|
||||
uint256 internal constant LEND_TRADE = 0;
|
||||
uint256 internal constant BORROW_TRADE = 1;
|
||||
uint256 internal constant INTERNAL_TOKEN_PRECISION = 1e8;
|
||||
uint256 internal constant ETH_CURRENCY_ID = 1;
|
||||
uint256 internal constant MAX_DEPOSIT = type(uint256).max;
|
||||
|
||||
address payable constant feeCollector =
|
||||
0xb1DC62EC38E6E3857a887210C38418E4A17Da5B2;
|
||||
|
||||
AaveV2DataProviderInterface internal constant aaveData =
|
||||
AaveV2DataProviderInterface(0x057835Ad21a177dbdd3090bB1CAE03EaCF78Fc6d);
|
||||
|
||||
NotionalInterface internal constant notional =
|
||||
NotionalInterface(0x1344A36A1B56144C3Bc62E7757377D288fDE0369);
|
||||
|
||||
/**
|
||||
* @dev get Aave Lending Pool Provider
|
||||
*/
|
||||
AaveV2LendingPoolProviderInterface internal constant getAaveV2Provider =
|
||||
AaveV2LendingPoolProviderInterface(
|
||||
0xB53C1a33016B2DC2fF3653530bfF1848a515c8c5
|
||||
);
|
||||
|
||||
/**
|
||||
* @dev get Referral Code
|
||||
*/
|
||||
uint16 internal constant getReferralCode = 3228;
|
||||
|
||||
struct NotionalBorrowData {
|
||||
uint256 length;
|
||||
// debt fee
|
||||
uint256 fee;
|
||||
// borrow tokens
|
||||
address[] tokens;
|
||||
// true, then redeems the borrowed balance from cTokens to underlying token before transferring to account
|
||||
bool[] redeemToUnderlying;
|
||||
// borrow amts im underlying token denomination
|
||||
uint256[] amts;
|
||||
// aave V2 borrow rate modes
|
||||
uint256[] rateModes;
|
||||
// fCashAmount accounting for the borrowAmt with debtfee, calculated through SDK
|
||||
uint256[] fCashAmount;
|
||||
// borrow rate max, 0 means any is acceptable
|
||||
uint256[] maxBorrowRate;
|
||||
// notion defined currency IDs of borrowTokens
|
||||
uint256[] currencyIDs;
|
||||
// borrow markets based on the maturity where user wants to borrow
|
||||
uint256[] marketIndex;
|
||||
}
|
||||
|
||||
// withdraw balance of Aave v2
|
||||
function getWithdrawBalanceV2(
|
||||
AaveV2DataProviderInterface aaveData,
|
||||
address token
|
||||
) internal view returns (uint256 bal) {
|
||||
(bal, , , , , , , , ) = aaveData.getUserReserveData(
|
||||
token,
|
||||
address(this)
|
||||
);
|
||||
}
|
||||
|
||||
function getAssetOrUnderlyingToken(uint16 currencyId, bool underlying)
|
||||
internal
|
||||
view
|
||||
returns (address)
|
||||
{
|
||||
// prettier-ignore
|
||||
(Token memory assetToken, Token memory underlyingToken) = notional.getCurrency(currencyId);
|
||||
return
|
||||
underlying ? underlyingToken.tokenAddress : assetToken.tokenAddress;
|
||||
}
|
||||
|
||||
function toUint88(uint256 value) internal pure returns (uint88) {
|
||||
require(value <= type(uint88).max, "uint88 value overflow");
|
||||
return uint88(value);
|
||||
}
|
||||
|
||||
function toUint32(uint256 value) internal pure returns (uint32) {
|
||||
require(value <= type(uint32).max, "uint32 value overflow");
|
||||
return uint32(value);
|
||||
}
|
||||
|
||||
function toUint16(uint256 value) internal pure returns (uint16) {
|
||||
require(value <= type(uint16).max, "uint16 value overflow");
|
||||
return uint16(value);
|
||||
}
|
||||
|
||||
function toUint8(uint256 value) internal pure returns (uint8) {
|
||||
require(value <= type(uint8).max, "uint8 value overflow");
|
||||
return uint8(value);
|
||||
}
|
||||
|
||||
function getAaveV2PaybackAmt(uint256 rateMode, address token)
|
||||
internal
|
||||
returns (uint256 bal)
|
||||
{
|
||||
if (rateMode == 1) {
|
||||
(, bal, , , , , , , ) = aaveData.getUserReserveData(
|
||||
token,
|
||||
address(this)
|
||||
);
|
||||
} else {
|
||||
(, , bal, , , , , , ) = aaveData.getUserReserveData(
|
||||
token,
|
||||
address(this)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function calculateFee(
|
||||
uint256 amount,
|
||||
uint256 fee,
|
||||
bool toAdd
|
||||
) internal pure returns (uint256 feeAmount, uint256 _amount) {
|
||||
feeAmount = wmul(amount, fee);
|
||||
_amount = toAdd ? add(amount, feeAmount) : sub(amount, feeAmount);
|
||||
}
|
||||
|
||||
function transferFees(address token, uint256 feeAmt) internal {
|
||||
if (feeAmt > 0) {
|
||||
if (token == ethAddr) {
|
||||
feeCollector.transfer(feeAmt);
|
||||
} else {
|
||||
IERC20(token).safeTransfer(feeCollector, feeAmt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function calculateAndTransferFees(
|
||||
address token,
|
||||
uint256 amt,
|
||||
uint256 fee,
|
||||
bool toAdd
|
||||
) internal {
|
||||
token = (token == wethAddr) ? ethAddr : token;
|
||||
(uint256 feeAmt, uint256 _amt) = calculateFee(amt, fee, toAdd);
|
||||
transferFees(token, feeAmt);
|
||||
}
|
||||
|
||||
function encodeBorrowTrade(
|
||||
uint256 marketIndex,
|
||||
uint256 fCashAmount,
|
||||
uint256 maxBorrowRate
|
||||
) internal pure returns (bytes32) {
|
||||
return
|
||||
(bytes32(BORROW_TRADE) << 248) |
|
||||
(bytes32(marketIndex) << 240) |
|
||||
(bytes32(fCashAmount) << 152) |
|
||||
(bytes32(maxBorrowRate) << 120);
|
||||
}
|
||||
|
||||
function getTokens(uint256 length, uint256[] memory currencyIDs)
|
||||
internal
|
||||
view
|
||||
returns (address[] memory)
|
||||
{
|
||||
address[] memory tokens = new address[](length);
|
||||
for (uint256 i = 0; i < length; i++) {
|
||||
uint16 _currencyId = toUint16(currencyIDs[i]);
|
||||
if (_currencyId == ETH_CURRENCY_ID) {
|
||||
tokens[i] = wethAddr;
|
||||
} else {
|
||||
tokens[i] = getAssetOrUnderlyingToken(_currencyId, true);
|
||||
}
|
||||
}
|
||||
return tokens;
|
||||
}
|
||||
|
||||
function getTokenInterfaces(uint256 length, address[] memory _tokens)
|
||||
internal
|
||||
pure
|
||||
returns (TokenInterface[] memory)
|
||||
{
|
||||
TokenInterface[] memory tokens = new TokenInterface[](length);
|
||||
for (uint256 i = 0; i < length; i++) {
|
||||
tokens[i] = TokenInterface(_tokens[i]);
|
||||
}
|
||||
return tokens;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.6;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import { Helpers } from "../helpers.sol";
|
||||
|
||||
import { AaveV2DataProviderInterface, AaveV2LendingPoolProviderInterface, AaveV2Interface } from "../interface.sol";
|
||||
import { TokenInterface } from "../../../common/interfaces.sol";
|
||||
|
||||
contract AaveHelpers is Helpers {
|
||||
// payback token to Aave V2, amts sent already checked for MAX
|
||||
function _aaveV2PaybackOne(
|
||||
AaveV2Interface aave,
|
||||
TokenInterface token,
|
||||
uint256 amt,
|
||||
uint256 rateMode
|
||||
) internal {
|
||||
if (amt > 0) {
|
||||
bool isEth = address(token) == wethAddr;
|
||||
convertEthToWeth(isEth, token, amt);
|
||||
approve(token, address(aave), amt);
|
||||
aave.repay(address(token), amt, rateMode, address(this));
|
||||
}
|
||||
}
|
||||
|
||||
function _aaveV2Payback(
|
||||
uint256 length,
|
||||
AaveV2Interface aave,
|
||||
TokenInterface[] memory tokens,
|
||||
uint256[] memory amts,
|
||||
uint256[] memory rateModes
|
||||
) internal {
|
||||
for (uint256 i = 0; i < length; i++) {
|
||||
_aaveV2PaybackOne(aave, tokens[i], amts[i], rateModes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// withdraw aToken from aaveV2
|
||||
function _aaveV2WithdrawOne(
|
||||
AaveV2Interface aave,
|
||||
AaveV2DataProviderInterface 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)
|
||||
? getWithdrawBalanceV2(aaveData, address(token))
|
||||
: amt;
|
||||
convertWethToEth(isEth, token, _amt);
|
||||
}
|
||||
}
|
||||
|
||||
function _aaveV2Withdraw(
|
||||
AaveV2Interface aave,
|
||||
AaveV2DataProviderInterface 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] = _aaveV2WithdrawOne(
|
||||
aave,
|
||||
aaveData,
|
||||
tokens[i],
|
||||
amts[i]
|
||||
);
|
||||
}
|
||||
return finalAmts;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.6;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import { Helpers } from "../helpers.sol";
|
||||
import { Token, NotionalInterface, BalanceAction, BalanceActionWithTrades, DepositActionType, AaveV2DataProviderInterface } from "../interface.sol";
|
||||
|
||||
contract NotionalHelpers is Helpers {
|
||||
function _notionalBorrowOne(
|
||||
uint256 fee,
|
||||
bool redeemToUnderlying,
|
||||
uint256 fCashAmount,
|
||||
uint256 maxBorrowRate,
|
||||
uint16 currencyID,
|
||||
uint256 marketIndex
|
||||
) internal {
|
||||
//collateral should be depositied beforehand in other currency
|
||||
BalanceActionWithTrades[]
|
||||
memory actions = new BalanceActionWithTrades[](1);
|
||||
bytes32[] memory trades = new bytes32[](1);
|
||||
trades[0] = encodeBorrowTrade(marketIndex, fCashAmount, maxBorrowRate);
|
||||
|
||||
actions[0].actionType = DepositActionType.None;
|
||||
actions[0].currencyId = currencyID;
|
||||
actions[0].withdrawEntireCashBalance = true;
|
||||
actions[0].depositActionAmount = 0;
|
||||
actions[0].redeemToUnderlying = redeemToUnderlying;
|
||||
actions[0].trades = trades;
|
||||
|
||||
notional.batchBalanceAndTradeAction(address(this), actions);
|
||||
}
|
||||
|
||||
/// @return finalAmts payback amount on Aave
|
||||
function _notionalBorrow(NotionalBorrowData memory data)
|
||||
internal
|
||||
returns (uint256[] memory)
|
||||
{
|
||||
uint256[] memory finalAmts = new uint256[](data.length);
|
||||
for (uint256 i = 0; i < data.length; i++) {
|
||||
uint16 _currencyID = toUint16(data.currencyIDs[i]);
|
||||
uint256 _amt = data.amts[i];
|
||||
|
||||
//borrow token on Notional
|
||||
_notionalBorrowOne(
|
||||
data.fee,
|
||||
data.redeemToUnderlying[i],
|
||||
data.fCashAmount[i],
|
||||
data.maxBorrowRate[i],
|
||||
_currencyID,
|
||||
data.marketIndex[i]
|
||||
);
|
||||
|
||||
//calculating payback amounts for Aave v2
|
||||
if (_amt == uint256(-1)) {
|
||||
_amt = getAaveV2PaybackAmt(data.rateModes[i], data.tokens[i]);
|
||||
}
|
||||
finalAmts[i] = _amt;
|
||||
|
||||
//calculate and transferFees
|
||||
calculateAndTransferFees(data.tokens[i], _amt, data.fee, true);
|
||||
}
|
||||
}
|
||||
|
||||
// deposit as collateral i.e. reduces the risk of liquidation or mint ntokens i.e. provides liquidity, this method doesn't lends to the market at fixed rate
|
||||
function _notionalDepositOne(
|
||||
uint256 fee,
|
||||
uint256 amt,
|
||||
address token,
|
||||
bool mintNToken,
|
||||
uint16 currencyID
|
||||
) internal {
|
||||
if (amt > 0) {
|
||||
(uint256 feeAmt, uint256 depositAmount) = calculateFee(
|
||||
amt,
|
||||
fee,
|
||||
false
|
||||
);
|
||||
|
||||
token = (token == wethAddr) ? ethAddr : token;
|
||||
transferFees(token, feeAmt);
|
||||
|
||||
if (mintNToken) {
|
||||
//deposit cash and mint nTokens
|
||||
BalanceAction[] memory action = new BalanceAction[](1);
|
||||
action[0].actionType = DepositActionType
|
||||
.DepositUnderlyingAndMintNToken;
|
||||
action[0].currencyId = toUint16(currencyID);
|
||||
action[0].depositActionAmount = depositAmount;
|
||||
|
||||
if (currencyID == ETH_CURRENCY_ID) {
|
||||
notional.batchBalanceAction{ value: depositAmount }(
|
||||
address(this),
|
||||
action
|
||||
);
|
||||
} else {
|
||||
notional.batchBalanceAction(address(this), action);
|
||||
}
|
||||
} else {
|
||||
//deposit as collateral
|
||||
if (currencyID == ETH_CURRENCY_ID) {
|
||||
notional.depositUnderlyingToken{ value: depositAmount }(
|
||||
address(this),
|
||||
currencyID,
|
||||
depositAmount
|
||||
);
|
||||
} else {
|
||||
notional.depositAssetToken(
|
||||
address(this),
|
||||
currencyID,
|
||||
depositAmount
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// deposits on notional
|
||||
function _notionalDeposit(
|
||||
uint256 length,
|
||||
uint256 fee,
|
||||
uint256[] memory currencyIDs,
|
||||
uint256[] memory amts,
|
||||
address[] memory tokens,
|
||||
bool[] memory mintNTokens
|
||||
) internal {
|
||||
for (uint256 i = 0; i < length; i++) {
|
||||
_notionalDepositOne(
|
||||
fee,
|
||||
amts[i],
|
||||
tokens[i],
|
||||
mintNTokens[i],
|
||||
toUint16(currencyIDs[i])
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
172
contracts/mainnet/connectors/refinance-notional/interface.sol
Normal file
172
contracts/mainnet/connectors/refinance-notional/interface.sol
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.6;
|
||||
pragma abicoder v2;
|
||||
|
||||
import { TokenInterface } from "../../common/interfaces.sol";
|
||||
|
||||
/// @notice Different types of internal tokens
|
||||
/// - UnderlyingToken: underlying asset for a cToken (except for Ether)
|
||||
/// - cToken: Compound interest bearing token
|
||||
/// - cETH: Special handling for cETH tokens
|
||||
/// - Ether: the one and only
|
||||
/// - NonMintable: tokens that do not have an underlying (therefore not cTokens)
|
||||
enum TokenType {
|
||||
UnderlyingToken,
|
||||
cToken,
|
||||
cETH,
|
||||
Ether,
|
||||
NonMintable
|
||||
}
|
||||
|
||||
/// @notice Specifies different deposit actions that can occur during BalanceAction or BalanceActionWithTrades
|
||||
enum DepositActionType {
|
||||
// No deposit action
|
||||
None,
|
||||
// Deposit asset cash, depositActionAmount is specified in asset cash external precision
|
||||
DepositAsset,
|
||||
// Deposit underlying tokens that are mintable to asset cash, depositActionAmount is specified in underlying token
|
||||
// external precision
|
||||
DepositUnderlying,
|
||||
// Deposits specified asset cash external precision amount into an nToken and mints the corresponding amount of
|
||||
// nTokens into the account
|
||||
DepositAssetAndMintNToken,
|
||||
// Deposits specified underlying in external precision, mints asset cash, and uses that asset cash to mint nTokens
|
||||
DepositUnderlyingAndMintNToken,
|
||||
// Redeems an nToken balance to asset cash. depositActionAmount is specified in nToken precision. Considered a deposit action
|
||||
// because it deposits asset cash into an account. If there are fCash residuals that cannot be sold off, will revert.
|
||||
RedeemNToken,
|
||||
// Converts specified amount of asset cash balance already in Notional to nTokens. depositActionAmount is specified in
|
||||
// Notional internal 8 decimal precision.
|
||||
ConvertCashToNToken
|
||||
}
|
||||
|
||||
/// @notice Defines a balance action with a set of trades to do as well
|
||||
struct BalanceActionWithTrades {
|
||||
DepositActionType actionType;
|
||||
uint16 currencyId;
|
||||
uint256 depositActionAmount;
|
||||
uint256 withdrawAmountInternalPrecision;
|
||||
bool withdrawEntireCashBalance;
|
||||
bool redeemToUnderlying;
|
||||
// Array of tightly packed 32 byte objects that represent trades. See TradeActionType documentation
|
||||
bytes32[] trades;
|
||||
}
|
||||
|
||||
/// @notice Defines a balance action for batchAction
|
||||
struct BalanceAction {
|
||||
// Deposit action to take (if any)
|
||||
DepositActionType actionType;
|
||||
uint16 currencyId;
|
||||
// Deposit action amount must correspond to the depositActionType, see documentation above.
|
||||
uint256 depositActionAmount;
|
||||
// Withdraw an amount of asset cash specified in Notional internal 8 decimal precision
|
||||
uint256 withdrawAmountInternalPrecision;
|
||||
// If set to true, will withdraw entire cash balance. Useful if there may be an unknown amount of asset cash
|
||||
// residual left from trading.
|
||||
bool withdrawEntireCashBalance;
|
||||
// If set to true, will redeem asset cash to the underlying token on withdraw.
|
||||
bool redeemToUnderlying;
|
||||
}
|
||||
|
||||
struct Token {
|
||||
// Address of the token
|
||||
address tokenAddress;
|
||||
// True if the token has a transfer fee which is used internally to determine
|
||||
// the proper balance change
|
||||
bool hasTransferFee;
|
||||
// Decimal precision of the token as a power of 10
|
||||
int256 decimals;
|
||||
// Type of token, enumerated above
|
||||
TokenType tokenType;
|
||||
// Used internally for tokens that have a collateral cap, zero if there is no cap
|
||||
uint256 maxCollateralBalance;
|
||||
}
|
||||
|
||||
interface NotionalInterface {
|
||||
function getCurrency(uint16 currencyId)
|
||||
external
|
||||
view
|
||||
returns (Token memory assetToken, Token memory underlyingToken);
|
||||
|
||||
function getAccountBalance(uint16 currencyId, address account)
|
||||
external
|
||||
view
|
||||
returns (
|
||||
int256 cashBalance,
|
||||
int256 nTokenBalance,
|
||||
uint256 lastClaimTime
|
||||
);
|
||||
|
||||
function depositUnderlyingToken(
|
||||
address account,
|
||||
uint16 currencyId,
|
||||
uint256 amountExternalPrecision
|
||||
) external payable returns (uint256);
|
||||
|
||||
function depositAssetToken(
|
||||
address account,
|
||||
uint16 currencyId,
|
||||
uint256 amountExternalPrecision
|
||||
) external returns (uint256);
|
||||
|
||||
function withdraw(
|
||||
uint16 currencyId,
|
||||
uint88 amountInternalPrecision,
|
||||
bool redeemToUnderlying
|
||||
) external returns (uint256);
|
||||
|
||||
function nTokenClaimIncentives() external returns (uint256);
|
||||
|
||||
function nTokenRedeem(
|
||||
address redeemer,
|
||||
uint16 currencyId,
|
||||
uint96 tokensToRedeem_,
|
||||
bool sellTokenAssets,
|
||||
bool acceptResidualAssets
|
||||
) external returns (int256);
|
||||
|
||||
function batchBalanceAction(
|
||||
address account,
|
||||
BalanceAction[] calldata actions
|
||||
) external payable;
|
||||
|
||||
function batchBalanceAndTradeAction(
|
||||
address account,
|
||||
BalanceActionWithTrades[] calldata actions
|
||||
) external payable;
|
||||
}
|
||||
|
||||
///@dev Aave Interfaces
|
||||
// Aave Protocol Data Provider
|
||||
interface AaveV2DataProviderInterface {
|
||||
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
|
||||
);
|
||||
}
|
||||
|
||||
// Aave v2 Helpers
|
||||
interface AaveV2Interface {
|
||||
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;
|
||||
}
|
||||
|
||||
interface AaveV2LendingPoolProviderInterface {
|
||||
function getLendingPool() external view returns (address);
|
||||
}
|
||||
143
contracts/mainnet/connectors/refinance-notional/main.sol
Normal file
143
contracts/mainnet/connectors/refinance-notional/main.sol
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.6;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
/**
|
||||
* @title Refinance Notional, Aave v2.
|
||||
* @dev Refinancing.
|
||||
*/
|
||||
import { AaveV2Interface, AaveV2DataProviderInterface, AaveV2LendingPoolProviderInterface } from "./interface.sol";
|
||||
import { TokenInterface } from "../../common/interfaces.sol";
|
||||
import { AaveHelpers } from "./helpers/aaveV2.sol";
|
||||
import { NotionalHelpers } from "./helpers/notional.sol";
|
||||
|
||||
contract RefinanceResolver is AaveHelpers, NotionalHelpers {
|
||||
struct RefinanceData {
|
||||
uint256 collateralFee;
|
||||
uint256 debtFee;
|
||||
uint256[] currencyIDs;
|
||||
uint256[] borrowMarketIndices;
|
||||
uint256[] borrowfCashAmts;
|
||||
uint256[] borrowAmts;
|
||||
uint256[] withdrawAmts;
|
||||
uint256[] paybackRateModes;
|
||||
uint256[] maxBorrowingRates;
|
||||
bool[] redeemBorrowToUnderlying;
|
||||
bool[] mintNTokens;
|
||||
}
|
||||
|
||||
struct RefinanceInternalData {
|
||||
AaveV2Interface aave;
|
||||
AaveV2DataProviderInterface aaveData;
|
||||
uint256[] depositAmts;
|
||||
uint256[] paybackAmts;
|
||||
address[] tokens;
|
||||
TokenInterface[] tokenInterfaces;
|
||||
}
|
||||
|
||||
function _refinance(RefinanceData calldata data)
|
||||
internal
|
||||
returns (string memory _eventName, bytes memory _eventParam)
|
||||
{
|
||||
uint256 length = data.currencyIDs.length;
|
||||
require(data.borrowMarketIndices.length == length, "length-mismatch");
|
||||
require(data.borrowfCashAmts.length == length, "length-mismatch");
|
||||
require(data.borrowAmts.length == length, "length-mismatch");
|
||||
require(data.withdrawAmts.length == length, "length-mismatch");
|
||||
require(data.paybackRateModes.length == length, "length-mismatch");
|
||||
require(data.maxBorrowingRates.length == length, "length-mismatch");
|
||||
require(
|
||||
data.redeemBorrowToUnderlying.length == length,
|
||||
"length-mismatch"
|
||||
);
|
||||
require(data.mintNTokens.length == length, "length-mismatch");
|
||||
|
||||
RefinanceInternalData memory refinanceInternalData;
|
||||
refinanceInternalData.aave = AaveV2Interface(
|
||||
AaveV2LendingPoolProviderInterface(getAaveV2Provider)
|
||||
.getLendingPool()
|
||||
);
|
||||
refinanceInternalData.aaveData = aaveData;
|
||||
|
||||
refinanceInternalData.depositAmts;
|
||||
refinanceInternalData.paybackAmts;
|
||||
|
||||
refinanceInternalData.tokens = getTokens(length, data.currencyIDs);
|
||||
refinanceInternalData.tokenInterfaces = getTokenInterfaces(
|
||||
length,
|
||||
refinanceInternalData.tokens
|
||||
);
|
||||
|
||||
// Aave v2 to 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;
|
||||
|
||||
//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
|
||||
);
|
||||
|
||||
_eventName = "LogRefinance(uint,uint,address[],uint[],uint[],uint[],uint[])";
|
||||
_eventParam = abi.encode(
|
||||
data.collateralFee,
|
||||
data.debtFee,
|
||||
refinanceInternalData.tokens,
|
||||
refinanceInternalData.paybackAmts,
|
||||
refinanceInternalData.depositAmts,
|
||||
data.borrowMarketIndices,
|
||||
data.maxBorrowingRates
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Refinance
|
||||
* @notice Refinancing between Notional and Aave V2
|
||||
* @param data refinance data.
|
||||
*/
|
||||
function refinance(RefinanceData calldata data)
|
||||
external
|
||||
payable
|
||||
returns (string memory _eventName, bytes memory _eventParam)
|
||||
{
|
||||
(_eventName, _eventParam) = _refinance(data);
|
||||
}
|
||||
}
|
||||
|
||||
contract ConnectV2Refinance is RefinanceResolver {
|
||||
string public name = "Refinance-v1.2";
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user