Merge pull request #234 from Instadapp/aave-bug-swapBorrowMode

Bug Fixes | aave
This commit is contained in:
Thrilok kumar 2022-06-19 22:10:35 +05:30 committed by GitHub
commit 1ae4a0abef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 1636 additions and 215 deletions

View File

@ -433,7 +433,7 @@ abstract contract AaveResolver is Events, Helpers {
* @dev Swap borrow rate mode
* @notice Swaps user borrow rate mode between variable and stable
* @param token The address of the token to swap borrow rate.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
* @param rateMode Desired borrow rate mode. (Stable = 1, Variable = 2)
* @param rateMode current rate mode. (Stable = 1, Variable = 2)
*/
function swapBorrowRateMode(address token, uint256 rateMode)
external
@ -442,12 +442,10 @@ abstract contract AaveResolver is Events, Helpers {
{
AaveInterface aave = AaveInterface(aaveProvider.getPool());
uint256 currentRateMode = rateMode == 1 ? 2 : 1;
bool isEth = token == ethAddr;
address _token = isEth ? wethAddr : token;
if (getPaybackBalance(_token, currentRateMode) > 0) {
if (getPaybackBalance(_token, rateMode) > 0) {
aave.swapBorrowRateMode(_token, rateMode);
}

View File

@ -266,9 +266,11 @@ abstract contract AaveResolver is Events, Helpers {
AaveInterface aave = AaveInterface(aaveProvider.getLendingPool());
for (uint256 i = 0; i < _length; i++) {
address token = tokens[i];
if (getCollateralBalance(token) > 0 && !getIsColl(token)) {
aave.setUserUseReserveAsCollateral(token, true);
bool isAvax = tokens[i] == avaxAddr;
address _token = isAvax ? wavaxAddr : tokens[i];
if (getCollateralBalance(_token) > 0 && !getIsColl(_token)) {
aave.setUserUseReserveAsCollateral(_token, true);
}
}
@ -280,7 +282,7 @@ abstract contract AaveResolver is Events, Helpers {
* @dev Swap borrow rate mode
* @notice Swaps user borrow rate mode between variable and stable
* @param token The address of the token to swap borrow rate.(For AVAX: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
* @param rateMode Desired borrow rate mode. (Stable = 1, Variable = 2)
* @param rateMode Current Rate mode. (Stable = 1, Variable = 2)
*/
function swapBorrowRateMode(address token, uint256 rateMode)
external
@ -289,10 +291,11 @@ abstract contract AaveResolver is Events, Helpers {
{
AaveInterface aave = AaveInterface(aaveProvider.getLendingPool());
uint256 currentRateMode = rateMode == 1 ? 2 : 1;
bool isAVAX = token == avaxAddr;
address _token = isAVAX ? wavaxAddr : token;
if (getPaybackBalance(token, currentRateMode) > 0) {
aave.swapBorrowRateMode(token, rateMode);
if (getPaybackBalance(_token, rateMode) > 0) {
aave.swapBorrowRateMode(_token, rateMode);
}
_eventName = "LogSwapRateMode(address,uint256)";

View File

@ -434,7 +434,7 @@ abstract contract AaveResolver is Events, Helpers {
* @dev Swap borrow rate mode
* @notice Swaps user borrow rate mode between variable and stable
* @param token The address of the token to swap borrow rate.(For avax: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
* @param rateMode Desired borrow rate mode. (Stable = 1, Variable = 2)
* @param rateMode Current rate mode (Stable = 1, Variable = 2)
*/
function swapBorrowRateMode(address token, uint256 rateMode)
external
@ -443,12 +443,10 @@ abstract contract AaveResolver is Events, Helpers {
{
AaveInterface aave = AaveInterface(aaveProvider.getPool());
uint256 currentRateMode = rateMode == 1 ? 2 : 1;
bool isAVAX = token == avaxAddr;
address _token = isAVAX ? wavaxAddr : token;
if (getPaybackBalance(_token, currentRateMode) > 0) {
if (getPaybackBalance(_token, rateMode) > 0) {
aave.swapBorrowRateMode(_token, rateMode);
}

View File

@ -432,7 +432,7 @@ abstract contract AaveResolver is Events, Helpers {
* @dev Swap borrow rate mode
* @notice Swaps user borrow rate mode between variable and stable
* @param token The address of the token to swap borrow rate.(For ftm: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
* @param rateMode Desired borrow rate mode. (Stable = 1, Variable = 2)
* @param rateMode Current rate mode. (Stable = 1, Variable = 2)
*/
function swapBorrowRateMode(address token, uint256 rateMode)
external
@ -441,11 +441,10 @@ abstract contract AaveResolver is Events, Helpers {
{
AaveInterface aave = AaveInterface(aaveProvider.getPool());
uint256 currentRateMode = rateMode == 1 ? 2 : 1;
bool isFTM = token == ftmAddr;
address _token = isFTM ? wftmAddr : token;
if (getPaybackBalance(_token, currentRateMode) > 0) {
if (getPaybackBalance(_token, rateMode) > 0) {
aave.swapBorrowRateMode(_token, rateMode);
}

View File

@ -13,162 +13,182 @@ import { Events } from "./events.sol";
import { AaveInterface } from "./interface.sol";
abstract contract AaveResolver is Events, Helpers {
/**
* @dev Deposit ETH/ERC20_Token.
* @notice Deposit a token to Aave v2 for lending / collaterization.
* @param token The address of the token to deposit.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
* @param amt The amount of the token to deposit. (For max: `uint256(-1)`)
* @param getId ID to retrieve amt.
* @param setId ID stores the amount of tokens deposited.
*/
function deposit(
address token,
uint256 amt,
uint256 getId,
uint256 setId
) external payable returns (string memory _eventName, bytes memory _eventParam) {
uint _amt = getUint(getId, amt);
/**
* @dev Deposit ETH/ERC20_Token.
* @notice Deposit a token to Aave v2 for lending / collaterization.
* @param token The address of the token to deposit.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
* @param amt The amount of the token to deposit. (For max: `uint256(-1)`)
* @param getId ID to retrieve amt.
* @param setId ID stores the amount of tokens deposited.
*/
function deposit(
address token,
uint256 amt,
uint256 getId,
uint256 setId
)
external
payable
returns (string memory _eventName, bytes memory _eventParam)
{
uint256 _amt = getUint(getId, amt);
AaveInterface aave = AaveInterface(aaveProvider.getLendingPool());
AaveInterface aave = AaveInterface(aaveProvider.getLendingPool());
bool isEth = token == ethAddr;
address _token = isEth ? wethAddr : token;
bool isEth = token == ethAddr;
address _token = isEth ? wethAddr : token;
TokenInterface tokenContract = TokenInterface(_token);
TokenInterface tokenContract = TokenInterface(_token);
if (isEth) {
_amt = _amt == uint(-1) ? address(this).balance : _amt;
convertEthToWeth(isEth, tokenContract, _amt);
} else {
_amt = _amt == uint(-1) ? tokenContract.balanceOf(address(this)) : _amt;
}
if (isEth) {
_amt = _amt == uint256(-1) ? address(this).balance : _amt;
convertEthToWeth(isEth, tokenContract, _amt);
} else {
_amt = _amt == uint256(-1)
? tokenContract.balanceOf(address(this))
: _amt;
}
approve(tokenContract, address(aave), _amt);
approve(tokenContract, address(aave), _amt);
aave.deposit(_token, _amt, address(this), referralCode);
aave.deposit(_token, _amt, address(this), referralCode);
if (!getIsColl(_token)) {
aave.setUserUseReserveAsCollateral(_token, true);
}
if (!getIsColl(_token)) {
aave.setUserUseReserveAsCollateral(_token, true);
}
setUint(setId, _amt);
setUint(setId, _amt);
_eventName = "LogDeposit(address,uint256,uint256,uint256)";
_eventParam = abi.encode(token, _amt, getId, setId);
}
_eventName = "LogDeposit(address,uint256,uint256,uint256)";
_eventParam = abi.encode(token, _amt, getId, setId);
}
/**
* @dev Withdraw ETH/ERC20_Token.
* @notice Withdraw deposited token from Aave v2
* @param token The address of the token to withdraw.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
* @param amt The amount of the token to withdraw. (For max: `uint256(-1)`)
* @param getId ID to retrieve amt.
* @param setId ID stores the amount of tokens withdrawn.
*/
function withdraw(
address token,
uint256 amt,
uint256 getId,
uint256 setId
) external payable returns (string memory _eventName, bytes memory _eventParam) {
uint _amt = getUint(getId, amt);
/**
* @dev Withdraw ETH/ERC20_Token.
* @notice Withdraw deposited token from Aave v2
* @param token The address of the token to withdraw.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
* @param amt The amount of the token to withdraw. (For max: `uint256(-1)`)
* @param getId ID to retrieve amt.
* @param setId ID stores the amount of tokens withdrawn.
*/
function withdraw(
address token,
uint256 amt,
uint256 getId,
uint256 setId
)
external
payable
returns (string memory _eventName, bytes memory _eventParam)
{
uint256 _amt = getUint(getId, amt);
AaveInterface aave = AaveInterface(aaveProvider.getLendingPool());
bool isEth = token == ethAddr;
address _token = isEth ? wethAddr : token;
AaveInterface aave = AaveInterface(aaveProvider.getLendingPool());
bool isEth = token == ethAddr;
address _token = isEth ? wethAddr : token;
TokenInterface tokenContract = TokenInterface(_token);
TokenInterface tokenContract = TokenInterface(_token);
uint initialBal = tokenContract.balanceOf(address(this));
aave.withdraw(_token, _amt, address(this));
uint finalBal = tokenContract.balanceOf(address(this));
uint256 initialBal = tokenContract.balanceOf(address(this));
aave.withdraw(_token, _amt, address(this));
uint256 finalBal = tokenContract.balanceOf(address(this));
_amt = sub(finalBal, initialBal);
_amt = sub(finalBal, initialBal);
convertWethToEth(isEth, tokenContract, _amt);
convertWethToEth(isEth, tokenContract, _amt);
setUint(setId, _amt);
setUint(setId, _amt);
_eventName = "LogWithdraw(address,uint256,uint256,uint256)";
_eventParam = abi.encode(token, _amt, getId, setId);
}
_eventName = "LogWithdraw(address,uint256,uint256,uint256)";
_eventParam = abi.encode(token, _amt, getId, setId);
}
/**
* @dev Borrow ETH/ERC20_Token.
* @notice Borrow a token using Aave v2
* @param token The address of the token to borrow.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
* @param amt The amount of the token to borrow.
* @param rateMode The type of borrow debt. (For Stable: 1, Variable: 2)
* @param getId ID to retrieve amt.
* @param setId ID stores the amount of tokens borrowed.
*/
function borrow(
address token,
uint256 amt,
uint256 rateMode,
uint256 getId,
uint256 setId
) external payable returns (string memory _eventName, bytes memory _eventParam) {
uint _amt = getUint(getId, amt);
/**
* @dev Borrow ETH/ERC20_Token.
* @notice Borrow a token using Aave v2
* @param token The address of the token to borrow.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
* @param amt The amount of the token to borrow.
* @param rateMode The type of borrow debt. (For Stable: 1, Variable: 2)
* @param getId ID to retrieve amt.
* @param setId ID stores the amount of tokens borrowed.
*/
function borrow(
address token,
uint256 amt,
uint256 rateMode,
uint256 getId,
uint256 setId
)
external
payable
returns (string memory _eventName, bytes memory _eventParam)
{
uint256 _amt = getUint(getId, amt);
AaveInterface aave = AaveInterface(aaveProvider.getLendingPool());
AaveInterface aave = AaveInterface(aaveProvider.getLendingPool());
bool isEth = token == ethAddr;
address _token = isEth ? wethAddr : token;
bool isEth = token == ethAddr;
address _token = isEth ? wethAddr : token;
aave.borrow(_token, _amt, rateMode, referralCode, address(this));
convertWethToEth(isEth, TokenInterface(_token), _amt);
aave.borrow(_token, _amt, rateMode, referralCode, address(this));
convertWethToEth(isEth, TokenInterface(_token), _amt);
setUint(setId, _amt);
setUint(setId, _amt);
_eventName = "LogBorrow(address,uint256,uint256,uint256,uint256)";
_eventParam = abi.encode(token, _amt, rateMode, getId, setId);
}
_eventName = "LogBorrow(address,uint256,uint256,uint256,uint256)";
_eventParam = abi.encode(token, _amt, rateMode, getId, setId);
}
/**
* @dev Payback borrowed ETH/ERC20_Token.
* @notice Payback debt owed.
* @param token The address of the token to payback.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
* @param amt The amount of the token to payback. (For max: `uint256(-1)`)
* @param rateMode The type of debt paying back. (For Stable: 1, Variable: 2)
* @param getId ID to retrieve amt.
* @param setId ID stores the amount of tokens paid back.
*/
function payback(
address token,
uint256 amt,
uint256 rateMode,
uint256 getId,
uint256 setId
) external payable returns (string memory _eventName, bytes memory _eventParam) {
uint _amt = getUint(getId, amt);
/**
* @dev Payback borrowed ETH/ERC20_Token.
* @notice Payback debt owed.
* @param token The address of the token to payback.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
* @param amt The amount of the token to payback. (For max: `uint256(-1)`)
* @param rateMode The type of debt paying back. (For Stable: 1, Variable: 2)
* @param getId ID to retrieve amt.
* @param setId ID stores the amount of tokens paid back.
*/
function payback(
address token,
uint256 amt,
uint256 rateMode,
uint256 getId,
uint256 setId
)
external
payable
returns (string memory _eventName, bytes memory _eventParam)
{
uint256 _amt = getUint(getId, amt);
AaveInterface aave = AaveInterface(aaveProvider.getLendingPool());
AaveInterface aave = AaveInterface(aaveProvider.getLendingPool());
bool isEth = token == ethAddr;
address _token = isEth ? wethAddr : token;
bool isEth = token == ethAddr;
address _token = isEth ? wethAddr : token;
TokenInterface tokenContract = TokenInterface(_token);
TokenInterface tokenContract = TokenInterface(_token);
if (_amt == uint(-1)) {
uint _amtDSA = isEth ? address(this).balance : tokenContract.balanceOf(address(this));
uint _amtDebt = getPaybackBalance(_token, rateMode);
_amt = _amtDSA <= _amtDebt ? _amtDSA : _amtDebt;
}
if (_amt == uint256(-1)) {
uint256 _amtDSA = isEth
? address(this).balance
: tokenContract.balanceOf(address(this));
uint256 _amtDebt = getPaybackBalance(_token, rateMode);
_amt = _amtDSA <= _amtDebt ? _amtDSA : _amtDebt;
}
if (isEth) convertEthToWeth(isEth, tokenContract, _amt);
if (isEth) convertEthToWeth(isEth, tokenContract, _amt);
approve(tokenContract, address(aave), _amt);
approve(tokenContract, address(aave), _amt);
aave.repay(_token, _amt, rateMode, address(this));
aave.repay(_token, _amt, rateMode, address(this));
setUint(setId, _amt);
setUint(setId, _amt);
_eventName = "LogPayback(address,uint256,uint256,uint256,uint256)";
_eventParam = abi.encode(token, _amt, rateMode, getId, setId);
}
_eventName = "LogPayback(address,uint256,uint256,uint256,uint256)";
_eventParam = abi.encode(token, _amt, rateMode, getId, setId);
}
/**
/**
* @dev Payback borrowed ETH/ERC20_Token on behalf of a user.
* @notice Payback debt owed on behalf os a user.
* @param token The address of the token to payback.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
@ -199,9 +219,15 @@ abstract contract AaveResolver is Events, Helpers {
TokenInterface tokenContract = TokenInterface(_token);
if (_amt == uint(-1)) {
uint _amtDSA = isEth ? address(this).balance : tokenContract.balanceOf(address(this));
uint _amtDebt = getOnBehalfOfPaybackBalance(_token, rateMode, onBehalfOf);
if (_amt == uint256(-1)) {
uint256 _amtDSA = isEth
? address(this).balance
: tokenContract.balanceOf(address(this));
uint256 _amtDebt = getOnBehalfOfPaybackBalance(
_token,
rateMode,
onBehalfOf
);
_amt = _amtDSA <= _amtDebt ? _amtDSA : _amtDebt;
}
@ -214,56 +240,69 @@ abstract contract AaveResolver is Events, Helpers {
setUint(setId, _amt);
_eventName = "LogPaybackOnBehalfOf(address,uint256,uint256,address,uint256,uint256)";
_eventParam = abi.encode(token, _amt, rateMode, onBehalfOf, getId, setId);
_eventParam = abi.encode(
token,
_amt,
rateMode,
onBehalfOf,
getId,
setId
);
}
/**
* @dev Enable collateral
* @notice Enable an array of tokens as collateral
* @param tokens Array of tokens to enable collateral
*/
function enableCollateral(
address[] calldata tokens
) external payable returns (string memory _eventName, bytes memory _eventParam) {
uint _length = tokens.length;
require(_length > 0, "0-tokens-not-allowed");
/**
* @dev Enable collateral
* @notice Enable an array of tokens as collateral
* @param tokens Array of tokens to enable collateral
*/
function enableCollateral(address[] calldata tokens)
external
payable
returns (string memory _eventName, bytes memory _eventParam)
{
uint256 _length = tokens.length;
require(_length > 0, "0-tokens-not-allowed");
AaveInterface aave = AaveInterface(aaveProvider.getLendingPool());
AaveInterface aave = AaveInterface(aaveProvider.getLendingPool());
for (uint i = 0; i < _length; i++) {
address token = tokens[i];
if (getCollateralBalance(token) > 0 && !getIsColl(token)) {
aave.setUserUseReserveAsCollateral(token, true);
}
}
for (uint256 i = 0; i < _length; i++) {
bool isEth = tokens[i] == ethAddr;
address _token = isEth ? wethAddr : tokens[i];
_eventName = "LogEnableCollateral(address[])";
_eventParam = abi.encode(tokens);
}
if (getCollateralBalance(_token) > 0 && !getIsColl(_token)) {
aave.setUserUseReserveAsCollateral(_token, true);
}
}
/**
* @dev Swap borrow rate mode
* @notice Swaps user borrow rate mode between variable and stable
* @param token The address of the token to swap borrow rate.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
* @param rateMode Desired borrow rate mode. (Stable = 1, Variable = 2)
*/
function swapBorrowRateMode(
address token,
uint rateMode
) external payable returns (string memory _eventName, bytes memory _eventParam) {
AaveInterface aave = AaveInterface(aaveProvider.getLendingPool());
_eventName = "LogEnableCollateral(address[])";
_eventParam = abi.encode(tokens);
}
uint currentRateMode = rateMode == 1 ? 2 : 1;
/**
* @dev Swap borrow rate mode
* @notice Swaps user borrow rate mode between variable and stable
* @param token The address of the token to swap borrow rate.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
* @param rateMode Current Rate mode. (Stable = 1, Variable = 2)
*/
function swapBorrowRateMode(address token, uint256 rateMode)
external
payable
returns (string memory _eventName, bytes memory _eventParam)
{
AaveInterface aave = AaveInterface(aaveProvider.getLendingPool());
if (getPaybackBalance(token, currentRateMode) > 0) {
aave.swapBorrowRateMode(token, rateMode);
}
bool isEth = token == ethAddr;
address _token = isEth ? wethAddr : token;
_eventName = "LogSwapRateMode(address,uint256)";
_eventParam = abi.encode(token, rateMode);
}
if (getPaybackBalance(_token, rateMode) > 0) {
aave.swapBorrowRateMode(_token, rateMode);
}
_eventName = "LogSwapRateMode(address,uint256)";
_eventParam = abi.encode(token, rateMode);
}
}
contract ConnectV2AaveV2 is AaveResolver {
string constant public name = "AaveV2-v1.2";
string public constant name = "AaveV2-v1.2";
}

View File

@ -103,7 +103,7 @@ abstract contract AaveResolver is Events, Helpers {
aave.supply(_token, _amt, address(this), referralCode);
if (getCollateralBalance(_token) > 0 && getIsColl(token)) {
if (getCollateralBalance(_token) > 0 && getIsColl(_token)) {
aave.setUserUseReserveAsCollateral(_token, false);
}
@ -224,7 +224,14 @@ abstract contract AaveResolver is Events, Helpers {
setUint(setId, _amt);
_eventName = "LogBorrowOnBehalfOf(address,uint256,uint256,address,uint256,uint256)";
_eventParam = abi.encode(token, _amt, rateMode, onBehalfOf, getId, setId);
_eventParam = abi.encode(
token,
_amt,
rateMode,
onBehalfOf,
getId,
setId
);
}
/**
@ -344,7 +351,9 @@ abstract contract AaveResolver is Events, Helpers {
TokenInterface tokenContract = TokenInterface(_token);
_amt = _amt == uint256(-1) ? getOnBehalfOfPaybackBalance(_token, rateMode, onBehalfOf) : _amt;
_amt = _amt == uint256(-1)
? getOnBehalfOfPaybackBalance(_token, rateMode, onBehalfOf)
: _amt;
if (isEth) convertEthToWeth(isEth, tokenContract, _amt);
@ -355,10 +364,16 @@ abstract contract AaveResolver is Events, Helpers {
setUint(setId, _amt);
_eventName = "LogPaybackOnBehalfOf(address,uint256,uint256,address,uint256,uint256)";
_eventParam = abi.encode(token, _amt, rateMode, onBehalfOf, getId, setId);
_eventParam = abi.encode(
token,
_amt,
rateMode,
onBehalfOf,
getId,
setId
);
}
/**
* @dev Enable collateral
* @notice Enable an array of tokens as collateral
@ -375,9 +390,11 @@ abstract contract AaveResolver is Events, Helpers {
AaveInterface aave = AaveInterface(aaveProvider.getPool());
for (uint256 i = 0; i < _length; i++) {
address token = tokens[i];
if (getCollateralBalance(token) > 0 && !getIsColl(token)) {
aave.setUserUseReserveAsCollateral(token, true);
bool isEth = tokens[i] == ethAddr;
address _token = isEth ? wethAddr : tokens[i];
if (getCollateralBalance(_token) > 0 && !getIsColl(_token)) {
aave.setUserUseReserveAsCollateral(_token, true);
}
}
@ -389,7 +406,7 @@ abstract contract AaveResolver is Events, Helpers {
* @dev Swap borrow rate mode
* @notice Swaps user borrow rate mode between variable and stable
* @param token The address of the token to swap borrow rate.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
* @param rateMode Desired borrow rate mode. (Stable = 1, Variable = 2)
* @param rateMode Current rate mode. (Stable = 1, Variable = 2)
*/
function swapBorrowRateMode(address token, uint256 rateMode)
external
@ -398,10 +415,11 @@ abstract contract AaveResolver is Events, Helpers {
{
AaveInterface aave = AaveInterface(aaveProvider.getPool());
uint256 currentRateMode = rateMode == 1 ? 2 : 1;
bool isEth = token == ethAddr;
address _token = isEth ? wethAddr : token;
if (getPaybackBalance(token, currentRateMode) > 0) {
aave.swapBorrowRateMode(token, rateMode);
if (getPaybackBalance(_token, rateMode) > 0) {
aave.swapBorrowRateMode(_token, rateMode);
}
_eventName = "LogSwapRateMode(address,uint256)";
@ -460,8 +478,14 @@ abstract contract AaveResolver is Events, Helpers {
setUint(setId, _amt);
_eventName = "LogDelegateBorrow(address,uint256,uint256,address,uint256,uint256)";
_eventParam = abi.encode(token, _amt, rateMode, delegateTo, getId, setId);
_eventParam = abi.encode(
token,
_amt,
rateMode,
delegateTo,
getId,
setId
);
}
}

View File

@ -434,7 +434,7 @@ abstract contract AaveResolver is Events, Helpers {
* @dev Swap borrow rate mode
* @notice Swaps user borrow rate mode between variable and stable
* @param token The address of the token to swap borrow rate.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
* @param rateMode Desired borrow rate mode. (Stable = 1, Variable = 2)
* @param rateMode Current borrow rate (Stable = 1, Variable = 2)
*/
function swapBorrowRateMode(address token, uint256 rateMode)
external
@ -443,12 +443,10 @@ abstract contract AaveResolver is Events, Helpers {
{
AaveInterface aave = AaveInterface(aaveProvider.getPool());
uint256 currentRateMode = rateMode == 1 ? 2 : 1;
bool isEth = token == ethAddr;
address _token = isEth ? wethAddr : token;
if (getPaybackBalance(_token, currentRateMode) > 0) {
if (getPaybackBalance(_token, rateMode) > 0) {
aave.swapBorrowRateMode(_token, rateMode);
}

View File

@ -266,9 +266,11 @@ abstract contract AaveResolver is Events, Helpers {
AaveInterface aave = AaveInterface(aaveProvider.getLendingPool());
for (uint256 i = 0; i < _length; i++) {
address token = tokens[i];
if (getCollateralBalance(token) > 0 && !getIsColl(token)) {
aave.setUserUseReserveAsCollateral(token, true);
bool isMatic = tokens[i] == maticAddr;
address _token = isMatic ? wmaticAddr : tokens[i];
if (getCollateralBalance(_token) > 0 && !getIsColl(_token)) {
aave.setUserUseReserveAsCollateral(_token, true);
}
}
@ -280,7 +282,7 @@ abstract contract AaveResolver is Events, Helpers {
* @dev Swap borrow rate mode
* @notice Swaps user borrow rate mode between variable and stable
* @param token The address of the token to swap borrow rate.(For MATIC: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
* @param rateMode Desired borrow rate mode. (Stable = 1, Variable = 2)
* @param rateMode Current Rate mode. (Stable = 1, Variable = 2)
*/
function swapBorrowRateMode(address token, uint256 rateMode)
external
@ -289,10 +291,11 @@ abstract contract AaveResolver is Events, Helpers {
{
AaveInterface aave = AaveInterface(aaveProvider.getLendingPool());
uint256 currentRateMode = rateMode == 1 ? 2 : 1;
bool isMatic = token == maticAddr;
address _token = isMatic ? wmaticAddr : token;
if (getPaybackBalance(token, currentRateMode) > 0) {
aave.swapBorrowRateMode(token, rateMode);
if (getPaybackBalance(_token, rateMode) > 0) {
aave.swapBorrowRateMode(_token, rateMode);
}
_eventName = "LogSwapRateMode(address,uint256)";

View File

@ -434,7 +434,7 @@ abstract contract AaveResolver is Events, Helpers {
* @dev Swap borrow rate mode
* @notice Swaps user borrow rate mode between variable and stable
* @param token The address of the token to swap borrow rate.(For matic: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
* @param rateMode Desired borrow rate mode. (Stable = 1, Variable = 2)
* @param rateMode Current borrow rate s(Stable = 1, Variable = 2)
*/
function swapBorrowRateMode(address token, uint256 rateMode)
external
@ -443,12 +443,10 @@ abstract contract AaveResolver is Events, Helpers {
{
AaveInterface aave = AaveInterface(aaveProvider.getPool());
uint256 currentRateMode = rateMode == 1 ? 2 : 1;
bool isMatic = token == maticAddr;
address _token = isMatic ? wmaticAddr : token;
if (getPaybackBalance(_token, currentRateMode) > 0) {
if (getPaybackBalance(_token, rateMode) > 0) {
aave.swapBorrowRateMode(_token, rateMode);
}

View File

@ -43,7 +43,7 @@ const networkGasPriceConfig: Record<string, number> = {
avalanche: 40,
arbitrum: 1,
optimism: 0.001,
fantom: 300
fantom: 210
};
function createConfig(network: string) {

View File

@ -0,0 +1,292 @@
import { expect, should } from "chai";
import hre, { ethers, waffle } from "hardhat";
import type { Signer, Contract } from "ethers";
import { ecsign, ecrecover, pubToAddress } from "ethereumjs-util";
import { keccak256 } from "@ethersproject/keccak256";
import { defaultAbiCoder } from "@ethersproject/abi";
import { BigNumber } from "bignumber.js";
import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2";
import { addresses } from "../../../scripts/tests/arbitrum/addresses";
import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector";
import { abis } from "../../../scripts/constant/abis";
import { getMasterSigner } from "../../../scripts/tests/getMasterSigner";
import { parseEther, parseUnits } from "ethers/lib/utils";
import { encodeSpells } from "../../../scripts/tests/encodeSpells";
import encodeFlashcastData from "../../../scripts/tests/encodeFlashcastData";
import { ConnectV2AaveV3Arbitrum__factory, IERC20__factory } from "../../../typechain";
const ABI = ["function balanceOf(address account) public view returns (uint256)"];
const aDaiAddress = "0x82E64f49Ed5EC1bC6e43DAD4FC8Af9bb3A2312EE";
const aaveAddress = "0x69FA688f1Dc47d4B5d8029D5a35FB7a548310654";
let account = "0xc5ed2333f8a2c351fca35e5ebadb2a82f5d254c3";
const DAI = "0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1";
const USDC = "0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8";
const mnemonic = "test test test test test test test test test test test junk";
const connectorName = "AAVE-V3-X";
let signer: any, wallet0: any;
const aaveAbi = [
{
inputs: [
{ internalType: "address", name: "asset", type: "address" },
{ internalType: "address", name: "user", type: "address" }
],
name: "getUserReserveData",
outputs: [
{ internalType: "uint256", name: "currentATokenBalance", type: "uint256" },
{ internalType: "uint256", name: "currentStableDebt", type: "uint256" },
{ internalType: "uint256", name: "currentVariableDebt", type: "uint256" },
{ internalType: "uint256", name: "principalStableDebt", type: "uint256" },
{ internalType: "uint256", name: "scaledVariableDebt", type: "uint256" },
{ internalType: "uint256", name: "stableBorrowRate", type: "uint256" },
{ internalType: "uint256", name: "liquidityRate", type: "uint256" },
{ internalType: "uint40", name: "stableRateLastUpdated", type: "uint40" },
{ internalType: "bool", name: "usageAsCollateralEnabled", type: "bool" }
],
stateMutability: "view",
type: "function"
}
];
const erc20Abi = [
{
constant: false,
inputs: [
{
name: "_spender",
type: "address"
},
{
name: "_value",
type: "uint256"
}
],
name: "approve",
outputs: [
{
name: "",
type: "bool"
}
],
payable: false,
stateMutability: "nonpayable",
type: "function"
},
{
constant: true,
inputs: [],
name: "totalSupply",
outputs: [
{
name: "",
type: "uint256"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
{
constant: true,
inputs: [
{
name: "_owner",
type: "address"
}
],
name: "balanceOf",
outputs: [
{
name: "balance",
type: "uint256"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
{
constant: false,
inputs: [
{
name: "_to",
type: "address"
},
{
name: "_value",
type: "uint256"
}
],
name: "transfer",
outputs: [
{
name: "",
type: "bool"
}
],
payable: false,
stateMutability: "nonpayable",
type: "function"
}
];
const token = new ethers.Contract(DAI, erc20Abi);
const aDai = new ethers.Contract(aDaiAddress, ABI);
const usdcToken = new ethers.Contract(USDC, erc20Abi);
const aave = new ethers.Contract(aaveAddress, aaveAbi);
describe("Aave v3 Position for Arbitrum", function () {
let dsaWallet0: any;
let masterSigner: Signer;
let instaConnectorsV2: Contract;
let connector: any;
const wallet = ethers.Wallet.fromMnemonic(mnemonic);
before(async () => {
await hre.network.provider.request({
method: "hardhat_reset",
params: [
{
forking: {
//@ts-ignore
jsonRpcUrl: hre.config.networks.hardhat.forking.url,
blockNumber: 9333600
}
}
]
});
masterSigner = await getMasterSigner();
[wallet0] = await ethers.getSigners();
await hre.network.provider.send("hardhat_setBalance", [account, ethers.utils.parseEther("10").toHexString()]);
await hre.network.provider.request({
method: "hardhat_impersonateAccount",
params: [account]
});
signer = await ethers.getSigner(account);
await token.connect(signer).transfer(wallet0.address, ethers.utils.parseEther("10"));
instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2);
connector = await deployAndEnableConnector({
connectorName,
contractArtifact: ConnectV2AaveV3Arbitrum__factory,
signer: masterSigner,
connectors: instaConnectorsV2
});
});
describe("Deployment", async () => {
it("Should set correct name", async () => {
expect(await connector.name()).to.eq("AaveV3-v1.2");
});
});
describe("DSA wallet setup", async () => {
it("Should build DSA v2", async () => {
dsaWallet0 = await buildDSAv2(wallet0.address);
expect(!!dsaWallet0.address).to.be.true;
});
it("Deposit ETH into DSA wallet", async function () {
await wallet0.sendTransaction({
to: dsaWallet0.address,
value: ethers.utils.parseEther("5")
});
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("5"));
});
});
describe("check user AAVE position", async () => {
it("Should create DSA Aave v3 position of DAI(collateral) and USDC(debt)", async () => {
await token.connect(signer).transfer(dsaWallet0.address, ethers.utils.parseEther("10"));
const spells = [
//deposit DAI in aave
{
connector: connectorName,
method: "deposit",
args: [DAI, parseEther("10"), 0, 0]
},
//borrow USDC from aave
{
connector: connectorName,
method: "borrow",
args: [USDC, parseUnits("3", 6), 2, 0, 0]
}
];
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.address);
const receipt = await tx.wait();
});
it("Should check position of dsa", async () => {
expect(await aDai.connect(wallet0).balanceOf(dsaWallet0.address)).to.be.gte(
new BigNumber(10).multipliedBy(1e18).toString()
);
expect(await usdcToken.connect(wallet0).balanceOf(dsaWallet0.address)).to.be.gte(
new BigNumber(3).multipliedBy(1e6).toString()
);
expect((await aave.connect(wallet0).getUserReserveData(USDC, dsaWallet0.address)).currentStableDebt).to.be.equal(
0
);
expect((await aave.connect(wallet0).getUserReserveData(USDC, dsaWallet0.address)).currentVariableDebt).to.be.gte(
new BigNumber(3).multipliedBy(1e6).toString()
);
console.log(
`\tstable borrow before: ${
(await aave.connect(wallet0).getUserReserveData(USDC, dsaWallet0.address)).currentStableDebt
}`
);
console.log(
`\tvariable borrow before: ${
(await aave.connect(wallet0).getUserReserveData(USDC, dsaWallet0.address)).currentVariableDebt
}`
);
});
it("Should swap borrowRateMode", async () => {
const spells = [
//deposit DAI in aave
{
connector: connectorName,
method: "swapBorrowRateMode",
args: [USDC, 2]
}
];
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.address);
const receipt = await tx.wait();
});
it("Should check position of dsa", async () => {
expect(await aDai.connect(wallet0).balanceOf(dsaWallet0.address)).to.be.gte(
new BigNumber(10).multipliedBy(1e18).toString()
);
expect(await usdcToken.connect(wallet0).balanceOf(dsaWallet0.address)).to.be.gte(
new BigNumber(3).multipliedBy(1e6).toString()
);
expect(
(await aave.connect(wallet0).getUserReserveData(USDC, dsaWallet0.address)).currentVariableDebt
).to.be.equal(0);
expect((await aave.connect(wallet0).getUserReserveData(USDC, dsaWallet0.address)).currentStableDebt).to.be.gte(
new BigNumber(3).multipliedBy(1e6).toString()
);
console.log(
`\tstable borrow after: ${
(await aave.connect(wallet0).getUserReserveData(USDC, dsaWallet0.address)).currentStableDebt
}`
);
console.log(
`\tvariable borrow after: ${
(await aave.connect(wallet0).getUserReserveData(USDC, dsaWallet0.address)).currentVariableDebt
}`
);
});
});
});

View File

@ -0,0 +1,273 @@
import { expect, should } from "chai";
import hre, { ethers, waffle } from "hardhat";
import type { Signer, Contract } from "ethers";
import { BigNumber } from "bignumber.js";
import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2";
import { addresses } from "../../../scripts/tests/avalanche/addresses";
import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector";
import { abis } from "../../../scripts/constant/abis";
import { getMasterSigner } from "../../../scripts/tests/getMasterSigner";
import { parseEther, parseUnits } from "ethers/lib/utils";
import { encodeSpells } from "../../../scripts/tests/encodeSpells";
import { ConnectV2AaveV3Avalanche__factory, IERC20__factory } from "../../../typechain";
const ABI = ["function balanceOf(address account) public view returns (uint256)"];
const aDaiAddress = "0x82E64f49Ed5EC1bC6e43DAD4FC8Af9bb3A2312EE";
const aaveAddress = "0x69FA688f1Dc47d4B5d8029D5a35FB7a548310654";
const ETH = "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E";
let account = "0xC4Aa5b4d4049324C09376D586482c7F8fB57542a";
const DAI = "0xd586E7F844cEa2F87f50152665BCbc2C279D8d70";
const mnemonic = "test test test test test test test test test test test junk";
const connectorName = "AAVE-V3-X";
let signer: any, wallet0: any;
const aaveAbi = [
{
inputs: [
{ internalType: "address", name: "asset", type: "address" },
{ internalType: "address", name: "user", type: "address" }
],
name: "getUserReserveData",
outputs: [
{ internalType: "uint256", name: "currentATokenBalance", type: "uint256" },
{ internalType: "uint256", name: "currentStableDebt", type: "uint256" },
{ internalType: "uint256", name: "currentVariableDebt", type: "uint256" },
{ internalType: "uint256", name: "principalStableDebt", type: "uint256" },
{ internalType: "uint256", name: "scaledVariableDebt", type: "uint256" },
{ internalType: "uint256", name: "stableBorrowRate", type: "uint256" },
{ internalType: "uint256", name: "liquidityRate", type: "uint256" },
{ internalType: "uint40", name: "stableRateLastUpdated", type: "uint40" },
{ internalType: "bool", name: "usageAsCollateralEnabled", type: "bool" }
],
stateMutability: "view",
type: "function"
}
];
const erc20Abi = [
{
constant: false,
inputs: [
{
name: "_spender",
type: "address"
},
{
name: "_value",
type: "uint256"
}
],
name: "approve",
outputs: [
{
name: "",
type: "bool"
}
],
payable: false,
stateMutability: "nonpayable",
type: "function"
},
{
constant: true,
inputs: [],
name: "totalSupply",
outputs: [
{
name: "",
type: "uint256"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
{
constant: true,
inputs: [
{
name: "_owner",
type: "address"
}
],
name: "balanceOf",
outputs: [
{
name: "balance",
type: "uint256"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
{
constant: false,
inputs: [
{
name: "_to",
type: "address"
},
{
name: "_value",
type: "uint256"
}
],
name: "transfer",
outputs: [
{
name: "",
type: "bool"
}
],
payable: false,
stateMutability: "nonpayable",
type: "function"
}
];
const token = new ethers.Contract(DAI, erc20Abi);
const aDai = new ethers.Contract(aDaiAddress, ABI);
const ethToken = new ethers.Contract(ETH, erc20Abi);
const aave = new ethers.Contract(aaveAddress, aaveAbi);
describe("Aave v3 Position for Avalanche", function () {
let dsaWallet0: any;
let masterSigner: Signer;
let instaConnectorsV2: Contract;
let connector: any;
const wallet = ethers.Wallet.fromMnemonic(mnemonic);
before(async () => {
await hre.network.provider.request({
method: "hardhat_reset",
params: [
{
forking: {
//@ts-ignore
jsonRpcUrl: hre.config.networks.hardhat.forking.url,
blockNumber: 16201000
}
}
]
});
masterSigner = await getMasterSigner();
[wallet0] = await ethers.getSigners();
await hre.network.provider.send("hardhat_setBalance", [account, ethers.utils.parseEther("10").toHexString()]);
await hre.network.provider.request({
method: "hardhat_impersonateAccount",
params: [account]
});
signer = await ethers.getSigner(account);
await token.connect(signer).transfer(wallet0.address, ethers.utils.parseEther("8"));
instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2);
connector = await deployAndEnableConnector({
connectorName,
contractArtifact: ConnectV2AaveV3Avalanche__factory,
signer: masterSigner,
connectors: instaConnectorsV2
});
});
describe("Deployment", async () => {
it("Should set correct name", async () => {
expect(await connector.name()).to.eq("AaveV3-v1.2");
});
});
describe("DSA wallet setup", async () => {
it("Should build DSA v2", async () => {
dsaWallet0 = await buildDSAv2(wallet0.address);
expect(!!dsaWallet0.address).to.be.true;
});
it("Deposit ETH into DSA wallet", async function () {
await wallet0.sendTransaction({
to: dsaWallet0.address,
value: ethers.utils.parseEther("5")
});
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("5"));
});
});
describe("check user AAVE position", async () => {
it("Should create DSA Aave v3 position of DAI(collateral) and USDC(debt)", async () => {
await token.connect(signer).transfer(dsaWallet0.address, ethers.utils.parseEther("8"));
const spells = [
//deposit DAI in aave
{
connector: connectorName,
method: "deposit",
args: [DAI, parseEther("8"), 0, 0]
},
//borrow USDC from aave
{
connector: connectorName,
method: "borrow",
args: [ETH, parseUnits("1", 6), 2, 0, 0]
}
];
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.address);
const receipt = await tx.wait();
});
it("Should check position of dsa", async () => {
expect(await aDai.connect(wallet0).balanceOf(dsaWallet0.address)).to.be.gte(
new BigNumber(8).multipliedBy(1e18).toString()
);
expect(await ethToken.connect(wallet0).balanceOf(dsaWallet0.address)).to.be.gte(
new BigNumber(1).multipliedBy(1e6).toString()
);
expect((await aave.connect(wallet0).getUserReserveData(ETH, dsaWallet0.address)).currentStableDebt).to.be.equal(
0
);
expect((await aave.connect(wallet0).getUserReserveData(ETH, dsaWallet0.address)).currentVariableDebt).to.be.gte(
new BigNumber(1).multipliedBy(1e6).toString()
);
console.log(`\tstable borrow before: ${(await aave.connect(wallet0).getUserReserveData(ETH, dsaWallet0.address)).currentStableDebt}`);
console.log(`\tvariable borrow before: ${(await aave.connect(wallet0).getUserReserveData(ETH, dsaWallet0.address)).currentVariableDebt}`);
});
it("Should swap borrowRateMode", async () => {
const spells = [
//deposit DAI in aave
{
connector: connectorName,
method: "swapBorrowRateMode",
args: [ETH, 2]
}
];
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.address);
const receipt = await tx.wait();
});
it("Should check position of dsa", async () => {
expect(await aDai.connect(wallet0).balanceOf(dsaWallet0.address)).to.be.gte(
new BigNumber(8).multipliedBy(1e18).toString()
);
expect(await ethToken.connect(wallet0).balanceOf(dsaWallet0.address)).to.be.gte(
new BigNumber(1).multipliedBy(1e6).toString()
);
expect(
(await aave.connect(wallet0).getUserReserveData(ETH, dsaWallet0.address)).currentVariableDebt
).to.be.equal(0);
expect((await aave.connect(wallet0).getUserReserveData(ETH, dsaWallet0.address)).currentStableDebt).to.be.gte(
new BigNumber(1).multipliedBy(1e6).toString()
);
console.log(`\tstable borrow after: ${(await aave.connect(wallet0).getUserReserveData(ETH, dsaWallet0.address)).currentStableDebt}`);
console.log(`\tvariable borrow after: ${(await aave.connect(wallet0).getUserReserveData(ETH, dsaWallet0.address)).currentVariableDebt}`)
});
});
});

264
test/fantom/aave/v3-test.ts Normal file
View File

@ -0,0 +1,264 @@
import { expect, should } from "chai";
import hre, { ethers, waffle } from "hardhat";
import type { Signer, Contract } from "ethers";
import { BigNumber } from "bignumber.js";
import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2";
import { addresses } from "../../../scripts/tests/fantom/addresses";
import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector";
import { abis } from "../../../scripts/constant/abis";
import { getMasterSigner } from "../../../scripts/tests/getMasterSigner";
import { parseEther, parseUnits } from "ethers/lib/utils";
import { encodeSpells } from "../../../scripts/tests/encodeSpells";
import { ConnectV2AaveV3Fantom__factory, IERC20__factory } from "../../../typechain";
const ABI = ["function balanceOf(address account) public view returns (uint256)"];
const aDaiAddress = "0x82E64f49Ed5EC1bC6e43DAD4FC8Af9bb3A2312EE";
const aaveAddress = "0x69FA688f1Dc47d4B5d8029D5a35FB7a548310654";
let account = "0x1c664Bafc646510684Ba1588798c67fe22a8c7cf";
const DAI = "0x8D11eC38a3EB5E956B052f67Da8Bdc9bef8Abf3E";
const USDC = "0x04068DA6C83AFCFA0e13ba15A6696662335D5B75";
const mnemonic = "test test test test test test test test test test test junk";
const connectorName = "AAVE-V3-X";
let signer: any, wallet0: any;
const aaveAbi = [
{
inputs: [
{ internalType: "address", name: "asset", type: "address" },
{ internalType: "address", name: "user", type: "address" }
],
name: "getUserReserveData",
outputs: [
{ internalType: "uint256", name: "currentATokenBalance", type: "uint256" },
{ internalType: "uint256", name: "currentStableDebt", type: "uint256" },
{ internalType: "uint256", name: "currentVariableDebt", type: "uint256" },
{ internalType: "uint256", name: "principalStableDebt", type: "uint256" },
{ internalType: "uint256", name: "scaledVariableDebt", type: "uint256" },
{ internalType: "uint256", name: "stableBorrowRate", type: "uint256" },
{ internalType: "uint256", name: "liquidityRate", type: "uint256" },
{ internalType: "uint40", name: "stableRateLastUpdated", type: "uint40" },
{ internalType: "bool", name: "usageAsCollateralEnabled", type: "bool" }
],
stateMutability: "view",
type: "function"
}
];
const erc20Abi = [
{
constant: false,
inputs: [
{
name: "_spender",
type: "address"
},
{
name: "_value",
type: "uint256"
}
],
name: "approve",
outputs: [
{
name: "",
type: "bool"
}
],
payable: false,
stateMutability: "nonpayable",
type: "function"
},
{
constant: true,
inputs: [],
name: "totalSupply",
outputs: [
{
name: "",
type: "uint256"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
{
constant: true,
inputs: [
{
name: "_owner",
type: "address"
}
],
name: "balanceOf",
outputs: [
{
name: "balance",
type: "uint256"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
{
constant: false,
inputs: [
{
name: "_to",
type: "address"
},
{
name: "_value",
type: "uint256"
}
],
name: "transfer",
outputs: [
{
name: "",
type: "bool"
}
],
payable: false,
stateMutability: "nonpayable",
type: "function"
}
];
const token = new ethers.Contract(DAI, erc20Abi);
const aDai = new ethers.Contract(aDaiAddress, ABI);
const usdcToken = new ethers.Contract(USDC, erc20Abi);
const aave = new ethers.Contract(aaveAddress, aaveAbi);
describe("Aave v3 Position for Fantom", function () {
let dsaWallet0: any;
let masterSigner: Signer;
let instaConnectorsV2: Contract;
let connector: any;
const wallet = ethers.Wallet.fromMnemonic(mnemonic);
before(async () => {
await hre.network.provider.request({
method: "hardhat_reset",
params: [
{
forking: {
//@ts-ignore
jsonRpcUrl: hre.config.networks.hardhat.forking.url,
blockNumber: 40790000
}
}
]
});
masterSigner = await getMasterSigner();
[wallet0] = await ethers.getSigners();
await hre.network.provider.send("hardhat_setBalance", [account, ethers.utils.parseEther("10").toHexString()]);
await hre.network.provider.request({
method: "hardhat_impersonateAccount",
params: [account]
});
signer = await ethers.getSigner(account);
await token.connect(signer).transfer(wallet0.address, ethers.utils.parseEther("10"));
instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2);
connector = await deployAndEnableConnector({
connectorName,
contractArtifact: ConnectV2AaveV3Fantom__factory,
signer: masterSigner,
connectors: instaConnectorsV2
});
});
describe("Deployment", async () => {
it("Should set correct name", async () => {
expect(await connector.name()).to.eq("AaveV3-v1.2");
});
});
describe("DSA wallet setup", async () => {
it("Should build DSA v2", async () => {
dsaWallet0 = await buildDSAv2(wallet0.address);
expect(!!dsaWallet0.address).to.be.true;
});
it("Deposit ETH into DSA wallet", async function () {
await wallet0.sendTransaction({
to: dsaWallet0.address,
value: ethers.utils.parseEther("5")
});
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("5"));
});
});
describe("check user AAVE position", async () => {
it("Should create DSA Aave v3 position of DAI(collateral) and USDC(debt)", async () => {
await token.connect(signer).transfer(dsaWallet0.address, ethers.utils.parseEther("10"));
const spells = [
//deposit DAI in aave
{
connector: connectorName,
method: "deposit",
args: [DAI, parseEther("10"), 0, 0]
},
//borrow USDC from aave
{
connector: connectorName,
method: "borrow",
args: [USDC, parseUnits("3", 6), 2, 0, 0]
}
];
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.address);
const receipt = await tx.wait();
});
it("Should check position of dsa", async () => {
expect(await aDai.connect(wallet0).balanceOf(dsaWallet0.address)).to.be.gte(
new BigNumber(10).multipliedBy(1e18).toString()
);
expect(await usdcToken.connect(wallet0).balanceOf(dsaWallet0.address)).to.be.gte(
new BigNumber(3).multipliedBy(1e6).toString()
);
expect((await aave.connect(wallet0).getUserReserveData(USDC, dsaWallet0.address)).currentStableDebt).to.be.equal(0);
expect((await aave.connect(wallet0).getUserReserveData(USDC, dsaWallet0.address)).currentVariableDebt).to.be.gte(
new BigNumber(3).multipliedBy(1e6).toString()
);
});
it("Should swap borrowRateMode", async () => {
const spells = [
//deposit DAI in aave
{
connector: connectorName,
method: "swapBorrowRateMode",
args: [USDC, 2]
}
];
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.address);
const receipt = await tx.wait();
});
it("Should check position of dsa", async () => {
expect(await aDai.connect(wallet0).balanceOf(dsaWallet0.address)).to.be.gte(
new BigNumber(10).multipliedBy(1e18).toString()
);
expect(await usdcToken.connect(wallet0).balanceOf(dsaWallet0.address)).to.be.gte(
new BigNumber(3).multipliedBy(1e6).toString()
);
expect((await aave.connect(wallet0).getUserReserveData(USDC, dsaWallet0.address)).currentVariableDebt).to.be.equal(0);
expect((await aave.connect(wallet0).getUserReserveData(USDC, dsaWallet0.address)).currentStableDebt).to.be.gte(
new BigNumber(3).multipliedBy(1e6).toString()
);
});
});
});

View File

@ -0,0 +1,268 @@
import { expect, should } from "chai";
import hre, { ethers, waffle } from "hardhat";
import type { Signer, Contract } from "ethers";
import { ecsign, ecrecover, pubToAddress } from "ethereumjs-util";
import { keccak256 } from "@ethersproject/keccak256";
import { defaultAbiCoder } from "@ethersproject/abi";
import { BigNumber } from "bignumber.js";
import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2";
import { addresses } from "../../../scripts/tests/optimism/addresses";
import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector";
import { abis } from "../../../scripts/constant/abis";
import { getMasterSigner } from "../../../scripts/tests/getMasterSigner";
import { parseEther, parseUnits } from "ethers/lib/utils";
import { encodeSpells } from "../../../scripts/tests/encodeSpells";
import encodeFlashcastData from "../../../scripts/tests/encodeFlashcastData";
import { ConnectV2AaveV3Optimism__factory, IERC20__factory } from "../../../typechain";
const ABI = ["function balanceOf(address account) public view returns (uint256)"];
const aDaiAddress = "0x82E64f49Ed5EC1bC6e43DAD4FC8Af9bb3A2312EE";
const aaveAddress = "0x69FA688f1Dc47d4B5d8029D5a35FB7a548310654";
let account = "0xa06067164E76285cef0ac6C42B3AD3Ce9BE5039A";
const DAI = "0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1";
const USDC = "0x7F5c764cBc14f9669B88837ca1490cCa17c31607";
const mnemonic = "test test test test test test test test test test test junk";
const connectorName = "AAVE-V3-X";
let signer: any, wallet0: any;
const aaveAbi = [
{
inputs: [
{ internalType: "address", name: "asset", type: "address" },
{ internalType: "address", name: "user", type: "address" }
],
name: "getUserReserveData",
outputs: [
{ internalType: "uint256", name: "currentATokenBalance", type: "uint256" },
{ internalType: "uint256", name: "currentStableDebt", type: "uint256" },
{ internalType: "uint256", name: "currentVariableDebt", type: "uint256" },
{ internalType: "uint256", name: "principalStableDebt", type: "uint256" },
{ internalType: "uint256", name: "scaledVariableDebt", type: "uint256" },
{ internalType: "uint256", name: "stableBorrowRate", type: "uint256" },
{ internalType: "uint256", name: "liquidityRate", type: "uint256" },
{ internalType: "uint40", name: "stableRateLastUpdated", type: "uint40" },
{ internalType: "bool", name: "usageAsCollateralEnabled", type: "bool" }
],
stateMutability: "view",
type: "function"
}
];
const erc20Abi = [
{
constant: false,
inputs: [
{
name: "_spender",
type: "address"
},
{
name: "_value",
type: "uint256"
}
],
name: "approve",
outputs: [
{
name: "",
type: "bool"
}
],
payable: false,
stateMutability: "nonpayable",
type: "function"
},
{
constant: true,
inputs: [],
name: "totalSupply",
outputs: [
{
name: "",
type: "uint256"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
{
constant: true,
inputs: [
{
name: "_owner",
type: "address"
}
],
name: "balanceOf",
outputs: [
{
name: "balance",
type: "uint256"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
{
constant: false,
inputs: [
{
name: "_to",
type: "address"
},
{
name: "_value",
type: "uint256"
}
],
name: "transfer",
outputs: [
{
name: "",
type: "bool"
}
],
payable: false,
stateMutability: "nonpayable",
type: "function"
}
];
const token = new ethers.Contract(DAI, erc20Abi);
const aDai = new ethers.Contract(aDaiAddress, ABI);
const usdcToken = new ethers.Contract(USDC, erc20Abi);
const aave = new ethers.Contract(aaveAddress, aaveAbi);
describe("Aave v3 Position for Optimism", function () {
let dsaWallet0: any;
let masterSigner: Signer;
let instaConnectorsV2: Contract;
let connector: any;
const wallet = ethers.Wallet.fromMnemonic(mnemonic);
before(async () => {
await hre.network.provider.request({
method: "hardhat_reset",
params: [
{
forking: {
//@ts-ignore
jsonRpcUrl: hre.config.networks.hardhat.forking.url,
blockNumber: 12230000
}
}
]
});
masterSigner = await getMasterSigner();
[wallet0] = await ethers.getSigners();
await hre.network.provider.send("hardhat_setBalance", [account, ethers.utils.parseEther("10").toHexString()]);
await hre.network.provider.request({
method: "hardhat_impersonateAccount",
params: [account]
});
signer = await ethers.getSigner(account);
await token.connect(signer).transfer(wallet0.address, ethers.utils.parseEther("10"));
instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2);
connector = await deployAndEnableConnector({
connectorName,
contractArtifact: ConnectV2AaveV3Optimism__factory,
signer: masterSigner,
connectors: instaConnectorsV2
});
});
describe("Deployment", async () => {
it("Should set correct name", async () => {
expect(await connector.name()).to.eq("AaveV3-v1.2");
});
});
describe("DSA wallet setup", async () => {
it("Should build DSA v2", async () => {
dsaWallet0 = await buildDSAv2(wallet0.address);
expect(!!dsaWallet0.address).to.be.true;
});
it("Deposit ETH into DSA wallet", async function () {
await wallet0.sendTransaction({
to: dsaWallet0.address,
value: ethers.utils.parseEther("5")
});
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("5"));
});
});
describe("check user AAVE position", async () => {
it("Should create DSA Aave v3 position of DAI(collateral) and USDC(debt)", async () => {
await token.connect(signer).transfer(dsaWallet0.address, ethers.utils.parseEther("10"));
const spells = [
//deposit DAI in aave
{
connector: connectorName,
method: "deposit",
args: [DAI, parseEther("10"), 0, 0]
},
//borrow USDC from aave
{
connector: connectorName,
method: "borrow",
args: [USDC, parseUnits("3", 6), 2, 0, 0]
}
];
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.address);
const receipt = await tx.wait();
});
it("Should check position of dsa", async () => {
expect(await aDai.connect(wallet0).balanceOf(dsaWallet0.address)).to.be.gte(
new BigNumber(10).multipliedBy(1e18).toString()
);
expect(await usdcToken.connect(wallet0).balanceOf(dsaWallet0.address)).to.be.gte(
new BigNumber(3).multipliedBy(1e6).toString()
);
expect((await aave.connect(wallet0).getUserReserveData(USDC, dsaWallet0.address)).currentStableDebt).to.be.equal(0);
expect((await aave.connect(wallet0).getUserReserveData(USDC, dsaWallet0.address)).currentVariableDebt).to.be.gte(
new BigNumber(3).multipliedBy(1e6).toString()
);
});
it("Should swap borrowRateMode", async () => {
const spells = [
//deposit DAI in aave
{
connector: connectorName,
method: "swapBorrowRateMode",
args: [USDC, 2]
}
];
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.address);
const receipt = await tx.wait();
});
it("Should check position of dsa", async () => {
expect(await aDai.connect(wallet0).balanceOf(dsaWallet0.address)).to.be.gte(
new BigNumber(10).multipliedBy(1e18).toString()
);
expect(await usdcToken.connect(wallet0).balanceOf(dsaWallet0.address)).to.be.gte(
new BigNumber(3).multipliedBy(1e6).toString()
);
expect((await aave.connect(wallet0).getUserReserveData(USDC, dsaWallet0.address)).currentVariableDebt).to.be.equal(0);
expect((await aave.connect(wallet0).getUserReserveData(USDC, dsaWallet0.address)).currentStableDebt).to.be.gte(
new BigNumber(3).multipliedBy(1e6).toString()
);
});
});
});

View File

@ -0,0 +1,264 @@
import { expect, should } from "chai";
import hre, { ethers, waffle } from "hardhat";
import type { Signer, Contract } from "ethers";
import { BigNumber } from "bignumber.js";
import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2";
import { addresses } from "../../../scripts/tests/polygon/addresses";
import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector";
import { abis } from "../../../scripts/constant/abis";
import { getMasterSigner } from "../../../scripts/tests/getMasterSigner";
import { parseEther, parseUnits } from "ethers/lib/utils";
import { encodeSpells } from "../../../scripts/tests/encodeSpells";
import { ConnectV2AaveV3Polygon__factory, IERC20__factory } from "../../../typechain";
const ABI = ["function balanceOf(address account) public view returns (uint256)"];
const aDaiAddress = "0x82E64f49Ed5EC1bC6e43DAD4FC8Af9bb3A2312EE";
const aaveAddress = "0x69FA688f1Dc47d4B5d8029D5a35FB7a548310654";
const account = "0xf04adbf75cdfc5ed26eea4bbbb991db002036bdd";
const DAI = "0x8f3cf7ad23cd3cadbd9735aff958023239c6a063";
const USDC = "0x2791bca1f2de4661ed88a30c99a7a9449aa84174";
const mnemonic = "test test test test test test test test test test test junk";
const connectorName = "AAVE-V3-X";
let signer: any, wallet0: any;
const aaveAbi = [
{
inputs: [
{ internalType: "address", name: "asset", type: "address" },
{ internalType: "address", name: "user", type: "address" }
],
name: "getUserReserveData",
outputs: [
{ internalType: "uint256", name: "currentATokenBalance", type: "uint256" },
{ internalType: "uint256", name: "currentStableDebt", type: "uint256" },
{ internalType: "uint256", name: "currentVariableDebt", type: "uint256" },
{ internalType: "uint256", name: "principalStableDebt", type: "uint256" },
{ internalType: "uint256", name: "scaledVariableDebt", type: "uint256" },
{ internalType: "uint256", name: "stableBorrowRate", type: "uint256" },
{ internalType: "uint256", name: "liquidityRate", type: "uint256" },
{ internalType: "uint40", name: "stableRateLastUpdated", type: "uint40" },
{ internalType: "bool", name: "usageAsCollateralEnabled", type: "bool" }
],
stateMutability: "view",
type: "function"
}
];
const erc20Abi = [
{
constant: false,
inputs: [
{
name: "_spender",
type: "address"
},
{
name: "_value",
type: "uint256"
}
],
name: "approve",
outputs: [
{
name: "",
type: "bool"
}
],
payable: false,
stateMutability: "nonpayable",
type: "function"
},
{
constant: true,
inputs: [],
name: "totalSupply",
outputs: [
{
name: "",
type: "uint256"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
{
constant: true,
inputs: [
{
name: "_owner",
type: "address"
}
],
name: "balanceOf",
outputs: [
{
name: "balance",
type: "uint256"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
{
constant: false,
inputs: [
{
name: "_to",
type: "address"
},
{
name: "_value",
type: "uint256"
}
],
name: "transfer",
outputs: [
{
name: "",
type: "bool"
}
],
payable: false,
stateMutability: "nonpayable",
type: "function"
}
];
const token = new ethers.Contract(DAI, erc20Abi);
const aDai = new ethers.Contract(aDaiAddress, ABI);
const usdcToken = new ethers.Contract(USDC, erc20Abi);
const aave = new ethers.Contract(aaveAddress, aaveAbi);
describe("Aave v3 Position for Polygon", function () {
let dsaWallet0: any;
let masterSigner: Signer;
let instaConnectorsV2: Contract;
let connector: any;
const wallet = ethers.Wallet.fromMnemonic(mnemonic);
before(async () => {
await hre.network.provider.request({
method: "hardhat_reset",
params: [
{
forking: {
//@ts-ignore
jsonRpcUrl: hre.config.networks.hardhat.forking.url,
blockNumber: 26652016
}
}
]
});
masterSigner = await getMasterSigner();
[wallet0] = await ethers.getSigners();
await hre.network.provider.send("hardhat_setBalance", [account, ethers.utils.parseEther("10").toHexString()]);
await hre.network.provider.request({
method: "hardhat_impersonateAccount",
params: [account]
});
signer = await ethers.getSigner(account);
await token.connect(signer).transfer(wallet0.address, ethers.utils.parseEther("10"));
instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2);
connector = await deployAndEnableConnector({
connectorName,
contractArtifact: ConnectV2AaveV3Polygon__factory,
signer: masterSigner,
connectors: instaConnectorsV2
});
});
describe("Deployment", async () => {
it("Should set correct name", async () => {
expect(await connector.name()).to.eq("AaveV3-v1.2");
});
});
describe("DSA wallet setup", async () => {
it("Should build DSA v2", async () => {
dsaWallet0 = await buildDSAv2(wallet0.address);
expect(!!dsaWallet0.address).to.be.true;
});
it("Deposit ETH into DSA wallet", async function () {
await wallet0.sendTransaction({
to: dsaWallet0.address,
value: ethers.utils.parseEther("5")
});
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("5"));
});
});
describe("check user AAVE position", async () => {
it("Should create DSA Aave v3 position of DAI(collateral) and USDC(debt)", async () => {
await token.connect(signer).transfer(dsaWallet0.address, ethers.utils.parseEther("10"));
const spells = [
//deposit DAI in aave
{
connector: connectorName,
method: "deposit",
args: [DAI, parseEther("10"), 0, 0]
},
//borrow USDC from aave
{
connector: connectorName,
method: "borrow",
args: [USDC, parseUnits("3", 6), 2, 0, 0]
}
];
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.address);
const receipt = await tx.wait();
});
it("Should check position of dsa", async () => {
expect(await aDai.connect(wallet0).balanceOf(dsaWallet0.address)).to.be.gte(
new BigNumber(10).multipliedBy(1e18).toString()
);
expect(await usdcToken.connect(wallet0).balanceOf(dsaWallet0.address)).to.be.gte(
new BigNumber(3).multipliedBy(1e6).toString()
);
expect((await aave.connect(wallet0).getUserReserveData(USDC, dsaWallet0.address)).currentStableDebt).to.be.equal(0);
expect((await aave.connect(wallet0).getUserReserveData(USDC, dsaWallet0.address)).currentVariableDebt).to.be.gte(
new BigNumber(3).multipliedBy(1e6).toString()
);
});
it("Should swap borrowRateMode", async () => {
const spells = [
//deposit DAI in aave
{
connector: connectorName,
method: "swapBorrowRateMode",
args: [USDC, 2]
}
];
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.address);
const receipt = await tx.wait();
});
it("Should check position of dsa", async () => {
expect(await aDai.connect(wallet0).balanceOf(dsaWallet0.address)).to.be.gte(
new BigNumber(10).multipliedBy(1e18).toString()
);
expect(await usdcToken.connect(wallet0).balanceOf(dsaWallet0.address)).to.be.gte(
new BigNumber(3).multipliedBy(1e6).toString()
);
expect((await aave.connect(wallet0).getUserReserveData(USDC, dsaWallet0.address)).currentVariableDebt).to.be.equal(0);
expect((await aave.connect(wallet0).getUserReserveData(USDC, dsaWallet0.address)).currentStableDebt).to.be.gte(
new BigNumber(3).multipliedBy(1e6).toString()
);
});
});
});