mirror of
https://github.com/Instadapp/dsa-connectors.git
synced 2024-07-29 22:37:00 +00:00
Merge branch 'aave-v2-to-v3-import' of https://github.com/Instadapp/dsa-connectors into aave-v3-addresses-update
This commit is contained in:
commit
ea78b1ccb4
|
@ -2,4 +2,10 @@ ETHERSCAN_API_KEY=""
|
|||
PRIVATE_KEY=""
|
||||
TENDERLY_PROJECT=""
|
||||
TENDERLY_USERNAME=""
|
||||
ALCHEMY_ID=""
|
||||
ALCHEMY_ID=""
|
||||
MAIN_ETHSCAN_KEY=
|
||||
OPT_ETHSCAN_KEY=
|
||||
POLY_ETHSCAN_KEY=
|
||||
ARB_ETHSCAN_KEY=
|
||||
AVAX_ETHSCAN_KEY=
|
||||
FTM_ETHSCAN_KEY=
|
9
.github/workflows/status.yml
vendored
9
.github/workflows/status.yml
vendored
|
@ -6,7 +6,7 @@ on:
|
|||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
permissions:
|
||||
contents: write
|
||||
strategy:
|
||||
matrix:
|
||||
|
@ -32,12 +32,9 @@ jobs:
|
|||
- name: Run status checks
|
||||
id: status_check
|
||||
run: |
|
||||
mkdir -p pr
|
||||
# Run status checks, Remove ANSI colors from the text
|
||||
output=$(node ./status-checks | sed 's/\x1B\[[0-9;]\{1,\}[A-Za-z]//g')
|
||||
# Escape newlines so _all_ the output is included in the set-output
|
||||
output="${output//'%'/'%25'}"
|
||||
output="${output//$'\n'/'%0A'}"
|
||||
output="${output//$'\r'/'%0D'}"
|
||||
output=$(npx ts-node ./status-checks/index.ts | sed 's/\x1B\[[0-9;]\{1,\}[A-Za-z]//g')
|
||||
cat <<< "$output" > "./pr/status-check-output"
|
||||
echo ${{ github.event.number }} > ./pr/number
|
||||
- uses: actions/upload-artifact@v2
|
||||
|
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -63,4 +63,5 @@ build/contracts
|
|||
# buidler
|
||||
artifacts
|
||||
cache
|
||||
typechain
|
||||
typechain
|
||||
|
||||
|
|
73
README.md
73
README.md
|
@ -47,8 +47,27 @@ Run all the tests:
|
|||
```sh
|
||||
$ npm run test
|
||||
```
|
||||
|
||||
(Striclty use this envirnment to test, or otherwise make suitable changes in config file before testing).
|
||||
|
||||
### Deploy
|
||||
|
||||
To deploy a connector using interactive CLI
|
||||
|
||||
```sh
|
||||
$ npm run deploy:runner
|
||||
```
|
||||
|
||||
(To deploy script manually use `scripts/deployment/deployManually.ts` script)
|
||||
|
||||
### checks
|
||||
|
||||
To check that code is compatible with github actions
|
||||
|
||||
```sh
|
||||
$ npm run check
|
||||
```
|
||||
|
||||
## How to add a new connector
|
||||
|
||||
You can create a new PR to add a new connector. To get the PR merged, certain requirements needs to be met which will be explained here.
|
||||
|
@ -57,39 +76,39 @@ You can create a new PR to add a new connector. To get the PR merged, certain re
|
|||
|
||||
Common files for all connectors are in `contracts/common` directory.
|
||||
|
||||
* `math.sol` has methods for mathematical operations (`DSMath`)
|
||||
* `interfaces.sol` contains the common interfaces
|
||||
* `TokenInterface` for ERC-20 interface including WETH
|
||||
* `stores.sol` contains the global constants as well as methods `getId` & `setId` (`Stores`)
|
||||
* `basic.sol` inherits `DSMath` & `Stores` contracts. This contains few details explained below
|
||||
* Wrapping & unwrapping ETH (`convertEthToWeth` & `convertWethToEth`)
|
||||
* Getting token & ETH balance of DSA
|
||||
- `math.sol` has methods for mathematical operations (`DSMath`)
|
||||
- `interfaces.sol` contains the common interfaces
|
||||
- `TokenInterface` for ERC-20 interface including WETH
|
||||
- `stores.sol` contains the global constants as well as methods `getId` & `setId` (`Stores`)
|
||||
- `basic.sol` inherits `DSMath` & `Stores` contracts. This contains few details explained below
|
||||
- Wrapping & unwrapping ETH (`convertEthToWeth` & `convertWethToEth`)
|
||||
- Getting token & ETH balance of DSA
|
||||
|
||||
Connectors are under `contracts/connectors` directory, and should be formatted as follows:
|
||||
|
||||
* Connector events should be in a separate contract: `events.sol`
|
||||
* Interfaces should be defined in a seperate file: `interface.sol`
|
||||
* If the connector has helper methods & constants (including interface instances), this should be defined in a separate file: `helpers.sol`
|
||||
* `Helpers` contract should inherit `Basic` contract from common directory
|
||||
* If the connector doesn't have any helper methods, the main contract should inherit `Basic` contract
|
||||
* The main logic of the contract should be under `main.sol`, and the contract should inherit `Helpers` (if exists, otherwise `Basic`) & `Events`
|
||||
- Connector events should be in a separate contract: `events.sol`
|
||||
- Interfaces should be defined in a seperate file: `interface.sol`
|
||||
- If the connector has helper methods & constants (including interface instances), this should be defined in a separate file: `helpers.sol`
|
||||
- `Helpers` contract should inherit `Basic` contract from common directory
|
||||
- If the connector doesn't have any helper methods, the main contract should inherit `Basic` contract
|
||||
- The main logic of the contract should be under `main.sol`, and the contract should inherit `Helpers` (if exists, otherwise `Basic`) & `Events`
|
||||
|
||||
Few things to consider while writing the connector:
|
||||
|
||||
* Connector should have a public constant string declared `name`, which will be the name of the connector. This will be versioned. Ex: `Compound-v1`
|
||||
* Contract name should start with `ConnectV2` appended with protocol name. Eg: `ConnectV2Compound`
|
||||
* User interacting methods (`external` methods) will not be emitting events, rather the methods will be returning 2 variables:
|
||||
* `_eventName` of `string` type: This will be the event signture defined in the `Events` contract. Ex: `LogDeposit(address,address,uint256,uint256,uint256)`
|
||||
* `_eventParam` of `bytes` type: This will be the abi encoded event parameters
|
||||
* The contracts should not have `selfdestruct()`
|
||||
* The contracts should not have `delegatecall()`
|
||||
* Use `uint(-1)` of `type(uint256).max` for maximum amount everywhere
|
||||
* Use `ethAddr` (declared in `Stores`) to denote Ethereum (non-ERC20)
|
||||
* Use `address(this)` instead of `msg.sender` for fetching balance on-chain, etc
|
||||
* Only `approve()` (declared in `Basic`) limited amount while giving ERC20 allowance, which strictly needs to be 0 by the end of the spell.
|
||||
* User interacting functions should have natspec comments(@dev, @notice, @param).
|
||||
* Use `getUint()` (declared in `Stores`) for getting value that saved from previous spell
|
||||
* Use `setUint()` (declared in `Stores`) for setting value to save for the future spell
|
||||
- Connector should have a public constant string declared `name`, which will be the name of the connector. This will be versioned. Ex: `Compound-v1`
|
||||
- Contract name should start with `ConnectV2` appended with protocol name. Eg: `ConnectV2Compound`
|
||||
- User interacting methods (`external` methods) will not be emitting events, rather the methods will be returning 2 variables:
|
||||
- `_eventName` of `string` type: This will be the event signture defined in the `Events` contract. Ex: `LogDeposit(address,address,uint256,uint256,uint256)`
|
||||
- `_eventParam` of `bytes` type: This will be the abi encoded event parameters
|
||||
- The contracts should not have `selfdestruct()`
|
||||
- The contracts should not have `delegatecall()`
|
||||
- Use `uint(-1)` of `type(uint256).max` for maximum amount everywhere
|
||||
- Use `ethAddr` (declared in `Stores`) to denote Ethereum (non-ERC20)
|
||||
- Use `address(this)` instead of `msg.sender` for fetching balance on-chain, etc
|
||||
- Only `approve()` (declared in `Basic`) limited amount while giving ERC20 allowance, which strictly needs to be 0 by the end of the spell.
|
||||
- User interacting functions should have natspec comments(@dev, @notice, @param).
|
||||
- Use `getUint()` (declared in `Stores`) for getting value that saved from previous spell
|
||||
- Use `setUint()` (declared in `Stores`) for setting value to save for the future spell
|
||||
|
||||
### Support
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
import { TokenInterface } from "./interfaces.sol";
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
interface TokenInterface {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol";
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
import { MemoryInterface, InstaMapping } from "./interfaces.sol";
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
contract Events {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
import { TokenInterface } from "../../../common/interfaces.sol";
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
import { TokenInterface } from "../../../common/interfaces.sol";
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
contract Events {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
import { TokenInterface } from "../../../common/interfaces.sol";
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
import { TokenInterface } from "../../../common/interfaces.sol";
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
|
|
15
contracts/arbitrum/connectors/aave/v3-import/events.sol
Normal file
15
contracts/arbitrum/connectors/aave/v3-import/events.sol
Normal file
|
@ -0,0 +1,15 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
contract Events {
|
||||
event LogAaveV3Import(
|
||||
address indexed user,
|
||||
address[] ctokens,
|
||||
string[] supplyIds,
|
||||
string[] borrowIds,
|
||||
uint256[] flashLoanFees,
|
||||
uint256[] supplyAmts,
|
||||
uint256[] borrowAmts
|
||||
);
|
||||
}
|
287
contracts/arbitrum/connectors/aave/v3-import/helpers.sol
Normal file
287
contracts/arbitrum/connectors/aave/v3-import/helpers.sol
Normal file
|
@ -0,0 +1,287 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
import { DSMath } from "../../../common/math.sol";
|
||||
import { Basic } from "../../../common/basic.sol";
|
||||
import { TokenInterface, AccountInterface } from "../../../common/interfaces.sol";
|
||||
import { AaveInterface, AavePoolProviderInterface, AaveDataProviderInterface } from "./interface.sol";
|
||||
import "./events.sol";
|
||||
import "./interface.sol";
|
||||
|
||||
abstract contract Helper is DSMath, Basic {
|
||||
/**
|
||||
* @dev Aave referal code
|
||||
*/
|
||||
uint16 internal constant referalCode = 3228;
|
||||
|
||||
/**
|
||||
* @dev Aave Lending Pool Provider
|
||||
*/
|
||||
AavePoolProviderInterface internal constant aaveProvider =
|
||||
AavePoolProviderInterface(0xa97684ead0e402dC232d5A977953DF7ECBaB3CDb);
|
||||
|
||||
/**
|
||||
* @dev Aave Protocol Data Provider
|
||||
*/
|
||||
AaveDataProviderInterface internal constant aaveData =
|
||||
AaveDataProviderInterface(0x69FA688f1Dc47d4B5d8029D5a35FB7a548310654);
|
||||
|
||||
function getIsColl(address token, address user)
|
||||
internal
|
||||
view
|
||||
returns (bool isCol)
|
||||
{
|
||||
(, , , , , , , , isCol) = aaveData.getUserReserveData(token, user);
|
||||
}
|
||||
|
||||
struct ImportData {
|
||||
address[] _supplyTokens;
|
||||
address[] _borrowTokens;
|
||||
ATokenInterface[] aTokens;
|
||||
uint256[] supplyAmts;
|
||||
uint256[] variableBorrowAmts;
|
||||
uint256[] variableBorrowAmtsWithFee;
|
||||
uint256[] stableBorrowAmts;
|
||||
uint256[] stableBorrowAmtsWithFee;
|
||||
uint256[] totalBorrowAmts;
|
||||
uint256[] totalBorrowAmtsWithFee;
|
||||
bool convertStable;
|
||||
}
|
||||
|
||||
struct ImportInputData {
|
||||
address[] supplyTokens;
|
||||
address[] borrowTokens;
|
||||
bool convertStable;
|
||||
uint256[] flashLoanFees;
|
||||
}
|
||||
}
|
||||
|
||||
contract AaveHelpers is Helper {
|
||||
function getBorrowAmount(address _token, address userAccount)
|
||||
internal
|
||||
view
|
||||
returns (uint256 stableBorrow, uint256 variableBorrow)
|
||||
{
|
||||
(
|
||||
,
|
||||
address stableDebtTokenAddress,
|
||||
address variableDebtTokenAddress
|
||||
) = aaveData.getReserveTokensAddresses(_token);
|
||||
|
||||
stableBorrow = ATokenInterface(stableDebtTokenAddress).balanceOf(
|
||||
userAccount
|
||||
);
|
||||
variableBorrow = ATokenInterface(variableDebtTokenAddress).balanceOf(
|
||||
userAccount
|
||||
);
|
||||
}
|
||||
|
||||
function getBorrowAmounts(
|
||||
address userAccount,
|
||||
AaveInterface aave,
|
||||
ImportInputData memory inputData,
|
||||
ImportData memory data
|
||||
) internal returns (ImportData memory) {
|
||||
if (inputData.borrowTokens.length > 0) {
|
||||
data._borrowTokens = new address[](inputData.borrowTokens.length);
|
||||
data.variableBorrowAmts = new uint256[](
|
||||
inputData.borrowTokens.length
|
||||
);
|
||||
data.variableBorrowAmtsWithFee = new uint256[](
|
||||
inputData.borrowTokens.length
|
||||
);
|
||||
data.stableBorrowAmts = new uint256[](
|
||||
inputData.borrowTokens.length
|
||||
);
|
||||
data.stableBorrowAmtsWithFee = new uint256[](
|
||||
inputData.borrowTokens.length
|
||||
);
|
||||
data.totalBorrowAmts = new uint256[](inputData.borrowTokens.length);
|
||||
data.totalBorrowAmtsWithFee = new uint256[](
|
||||
inputData.borrowTokens.length
|
||||
);
|
||||
for (uint256 i = 0; i < inputData.borrowTokens.length; i++) {
|
||||
for (uint256 j = i; j < inputData.borrowTokens.length; j++) {
|
||||
if (j != i) {
|
||||
require(
|
||||
inputData.borrowTokens[i] !=
|
||||
inputData.borrowTokens[j],
|
||||
"token-repeated"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (uint256 i = 0; i < inputData.borrowTokens.length; i++) {
|
||||
address _token = inputData.borrowTokens[i] == ethAddr
|
||||
? wethAddr
|
||||
: inputData.borrowTokens[i];
|
||||
data._borrowTokens[i] = _token;
|
||||
|
||||
(
|
||||
data.stableBorrowAmts[i],
|
||||
data.variableBorrowAmts[i]
|
||||
) = getBorrowAmount(_token, userAccount);
|
||||
|
||||
if (data.variableBorrowAmts[i] != 0) {
|
||||
data.variableBorrowAmtsWithFee[i] = add(
|
||||
data.variableBorrowAmts[i],
|
||||
inputData.flashLoanFees[i]
|
||||
);
|
||||
data.stableBorrowAmtsWithFee[i] = data.stableBorrowAmts[i];
|
||||
} else {
|
||||
data.stableBorrowAmtsWithFee[i] = add(
|
||||
data.stableBorrowAmts[i],
|
||||
inputData.flashLoanFees[i]
|
||||
);
|
||||
}
|
||||
|
||||
data.totalBorrowAmts[i] = add(
|
||||
data.stableBorrowAmts[i],
|
||||
data.variableBorrowAmts[i]
|
||||
);
|
||||
data.totalBorrowAmtsWithFee[i] = add(
|
||||
data.stableBorrowAmtsWithFee[i],
|
||||
data.variableBorrowAmtsWithFee[i]
|
||||
);
|
||||
|
||||
if (data.totalBorrowAmts[i] > 0) {
|
||||
uint256 _amt = data.totalBorrowAmts[i];
|
||||
TokenInterface(_token).approve(address(aave), _amt);
|
||||
}
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
function getSupplyAmounts(
|
||||
address userAccount,
|
||||
ImportInputData memory inputData,
|
||||
ImportData memory data
|
||||
) internal view returns (ImportData memory) {
|
||||
data.supplyAmts = new uint256[](inputData.supplyTokens.length);
|
||||
data._supplyTokens = new address[](inputData.supplyTokens.length);
|
||||
data.aTokens = new ATokenInterface[](inputData.supplyTokens.length);
|
||||
|
||||
for (uint256 i = 0; i < inputData.supplyTokens.length; i++) {
|
||||
for (uint256 j = i; j < inputData.supplyTokens.length; j++) {
|
||||
if (j != i) {
|
||||
require(
|
||||
inputData.supplyTokens[i] != inputData.supplyTokens[j],
|
||||
"token-repeated"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (uint256 i = 0; i < inputData.supplyTokens.length; i++) {
|
||||
address _token = inputData.supplyTokens[i] == ethAddr
|
||||
? wethAddr
|
||||
: inputData.supplyTokens[i];
|
||||
(address _aToken, , ) = aaveData.getReserveTokensAddresses(_token);
|
||||
data._supplyTokens[i] = _token;
|
||||
data.aTokens[i] = ATokenInterface(_aToken);
|
||||
data.supplyAmts[i] = data.aTokens[i].balanceOf(userAccount);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
function _paybackBehalfOne(
|
||||
AaveInterface aave,
|
||||
address token,
|
||||
uint256 amt,
|
||||
uint256 rateMode,
|
||||
address user
|
||||
) private {
|
||||
aave.repay(token, amt, rateMode, user);
|
||||
}
|
||||
|
||||
function _PaybackStable(
|
||||
uint256 _length,
|
||||
AaveInterface aave,
|
||||
address[] memory tokens,
|
||||
uint256[] memory amts,
|
||||
address user
|
||||
) internal {
|
||||
for (uint256 i = 0; i < _length; i++) {
|
||||
if (amts[i] > 0) {
|
||||
_paybackBehalfOne(aave, tokens[i], amts[i], 1, user);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _PaybackVariable(
|
||||
uint256 _length,
|
||||
AaveInterface aave,
|
||||
address[] memory tokens,
|
||||
uint256[] memory amts,
|
||||
address user
|
||||
) internal {
|
||||
for (uint256 i = 0; i < _length; i++) {
|
||||
if (amts[i] > 0) {
|
||||
_paybackBehalfOne(aave, tokens[i], amts[i], 2, user);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _TransferAtokens(
|
||||
uint256 _length,
|
||||
AaveInterface aave,
|
||||
ATokenInterface[] memory atokenContracts,
|
||||
uint256[] memory amts,
|
||||
address[] memory tokens,
|
||||
address userAccount
|
||||
) internal {
|
||||
for (uint256 i = 0; i < _length; i++) {
|
||||
if (amts[i] > 0) {
|
||||
uint256 _amt = amts[i];
|
||||
require(
|
||||
atokenContracts[i].transferFrom(
|
||||
userAccount,
|
||||
address(this),
|
||||
_amt
|
||||
),
|
||||
"allowance?"
|
||||
);
|
||||
|
||||
if (!getIsColl(tokens[i], address(this))) {
|
||||
aave.setUserUseReserveAsCollateral(tokens[i], true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _BorrowVariable(
|
||||
uint256 _length,
|
||||
AaveInterface aave,
|
||||
address[] memory tokens,
|
||||
uint256[] memory amts
|
||||
) internal {
|
||||
for (uint256 i = 0; i < _length; i++) {
|
||||
if (amts[i] > 0) {
|
||||
_borrowOne(aave, tokens[i], amts[i], 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _BorrowStable(
|
||||
uint256 _length,
|
||||
AaveInterface aave,
|
||||
address[] memory tokens,
|
||||
uint256[] memory amts
|
||||
) internal {
|
||||
for (uint256 i = 0; i < _length; i++) {
|
||||
if (amts[i] > 0) {
|
||||
_borrowOne(aave, tokens[i], amts[i], 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _borrowOne(
|
||||
AaveInterface aave,
|
||||
address token,
|
||||
uint256 amt,
|
||||
uint256 rateMode
|
||||
) private {
|
||||
aave.borrow(token, amt, rateMode, referalCode, address(this));
|
||||
}
|
||||
}
|
95
contracts/arbitrum/connectors/aave/v3-import/interface.sol
Normal file
95
contracts/arbitrum/connectors/aave/v3-import/interface.sol
Normal file
|
@ -0,0 +1,95 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
interface AaveInterface {
|
||||
function supply(
|
||||
address asset,
|
||||
uint256 amount,
|
||||
address onBehalfOf,
|
||||
uint16 referralCode
|
||||
) external;
|
||||
|
||||
function withdraw(
|
||||
address _asset,
|
||||
uint256 _amount,
|
||||
address _to
|
||||
) external;
|
||||
|
||||
function borrow(
|
||||
address _asset,
|
||||
uint256 _amount,
|
||||
uint256 _interestRateMode,
|
||||
uint16 _referralCode,
|
||||
address _onBehalfOf
|
||||
) external;
|
||||
|
||||
function repay(
|
||||
address _asset,
|
||||
uint256 _amount,
|
||||
uint256 _rateMode,
|
||||
address _onBehalfOf
|
||||
) external;
|
||||
|
||||
function setUserUseReserveAsCollateral(
|
||||
address _asset,
|
||||
bool _useAsCollateral
|
||||
) external;
|
||||
|
||||
function swapBorrowRateMode(address _asset, uint256 _rateMode) external;
|
||||
}
|
||||
|
||||
interface ATokenInterface {
|
||||
function scaledBalanceOf(address _user) external view returns (uint256);
|
||||
|
||||
function isTransferAllowed(address _user, uint256 _amount)
|
||||
external
|
||||
view
|
||||
returns (bool);
|
||||
|
||||
function balanceOf(address _user) external view returns (uint256);
|
||||
|
||||
function transferFrom(
|
||||
address,
|
||||
address,
|
||||
uint256
|
||||
) external returns (bool);
|
||||
|
||||
function allowance(address, address) external returns (uint256);
|
||||
}
|
||||
|
||||
interface AavePoolProviderInterface {
|
||||
function getPool() external view returns (address);
|
||||
}
|
||||
|
||||
interface AaveDataProviderInterface {
|
||||
function getReserveTokensAddresses(address _asset)
|
||||
external
|
||||
view
|
||||
returns (
|
||||
address aTokenAddress,
|
||||
address stableDebtTokenAddress,
|
||||
address variableDebtTokenAddress
|
||||
);
|
||||
|
||||
function getUserReserveData(address _asset, address _user)
|
||||
external
|
||||
view
|
||||
returns (
|
||||
uint256 currentATokenBalance,
|
||||
uint256 currentStableDebt,
|
||||
uint256 currentVariableDebt,
|
||||
uint256 principalStableDebt,
|
||||
uint256 scaledVariableDebt,
|
||||
uint256 stableBorrowRate,
|
||||
uint256 liquidityRate,
|
||||
uint40 stableRateLastUpdated,
|
||||
bool usageAsCollateralEnabled
|
||||
);
|
||||
}
|
||||
|
||||
interface AaveAddressProviderRegistryInterface {
|
||||
function getAddressesProvidersList()
|
||||
external
|
||||
view
|
||||
returns (address[] memory);
|
||||
}
|
111
contracts/arbitrum/connectors/aave/v3-import/main.sol
Normal file
111
contracts/arbitrum/connectors/aave/v3-import/main.sol
Normal file
|
@ -0,0 +1,111 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
pragma experimental ABIEncoderV2;
|
||||
/**
|
||||
* @title Aave v3 import connector .
|
||||
* @dev Import EOA's aave V3 position to DSA's aave v3 position
|
||||
*/
|
||||
import { TokenInterface, AccountInterface } from "../../../common/interfaces.sol";
|
||||
import { AaveInterface, ATokenInterface } from "./interface.sol";
|
||||
import "./helpers.sol";
|
||||
import "./events.sol";
|
||||
|
||||
contract AaveV3ImportResolver is AaveHelpers {
|
||||
function _importAave(address userAccount, ImportInputData memory inputData)
|
||||
internal
|
||||
returns (string memory _eventName, bytes memory _eventParam)
|
||||
{
|
||||
require(
|
||||
AccountInterface(address(this)).isAuth(userAccount),
|
||||
"user-account-not-auth"
|
||||
);
|
||||
|
||||
require(inputData.supplyTokens.length > 0, "0-length-not-allowed");
|
||||
|
||||
ImportData memory data;
|
||||
|
||||
AaveInterface aave = AaveInterface(aaveProvider.getPool());
|
||||
|
||||
data = getBorrowAmounts(userAccount, aave, inputData, data);
|
||||
data = getSupplyAmounts(userAccount, inputData, data);
|
||||
|
||||
// payback borrowed amount;
|
||||
_PaybackStable(
|
||||
data._borrowTokens.length,
|
||||
aave,
|
||||
data._borrowTokens,
|
||||
data.stableBorrowAmts,
|
||||
userAccount
|
||||
);
|
||||
_PaybackVariable(
|
||||
data._borrowTokens.length,
|
||||
aave,
|
||||
data._borrowTokens,
|
||||
data.variableBorrowAmts,
|
||||
userAccount
|
||||
);
|
||||
|
||||
// transfer atokens to this address;
|
||||
_TransferAtokens(
|
||||
data._supplyTokens.length,
|
||||
aave,
|
||||
data.aTokens,
|
||||
data.supplyAmts,
|
||||
data._supplyTokens,
|
||||
userAccount
|
||||
);
|
||||
|
||||
// borrow assets after migrating position
|
||||
if (data.convertStable) {
|
||||
_BorrowVariable(
|
||||
data._borrowTokens.length,
|
||||
aave,
|
||||
data._borrowTokens,
|
||||
data.totalBorrowAmtsWithFee
|
||||
);
|
||||
} else {
|
||||
_BorrowStable(
|
||||
data._borrowTokens.length,
|
||||
aave,
|
||||
data._borrowTokens,
|
||||
data.stableBorrowAmtsWithFee
|
||||
);
|
||||
_BorrowVariable(
|
||||
data._borrowTokens.length,
|
||||
aave,
|
||||
data._borrowTokens,
|
||||
data.variableBorrowAmtsWithFee
|
||||
);
|
||||
}
|
||||
|
||||
_eventName = "LogAaveV3Import(address,bool,address[],address[],uint256[],uint256[],uint256[],uint256[])";
|
||||
_eventParam = abi.encode(
|
||||
userAccount,
|
||||
inputData.convertStable,
|
||||
inputData.supplyTokens,
|
||||
inputData.borrowTokens,
|
||||
inputData.flashLoanFees,
|
||||
data.supplyAmts,
|
||||
data.stableBorrowAmts,
|
||||
data.variableBorrowAmts
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Import aave V3 position .
|
||||
* @notice Import EOA's aave V3 position to DSA's aave v3 position
|
||||
* @param userAccount The address of the EOA from which aave position will be imported
|
||||
* @param inputData The struct containing all the neccessary input data
|
||||
*/
|
||||
function importAave(address userAccount, ImportInputData memory inputData)
|
||||
external
|
||||
payable
|
||||
returns (string memory _eventName, bytes memory _eventParam)
|
||||
{
|
||||
(_eventName, _eventParam) = _importAave(userAccount, inputData);
|
||||
}
|
||||
}
|
||||
|
||||
contract ConnectV2AaveV3ImportArbitrum is AaveV3ImportResolver {
|
||||
string public constant name = "Aave-v3-import-v1";
|
||||
}
|
34
contracts/arbitrum/connectors/aave/v3/events.sol
Normal file
34
contracts/arbitrum/connectors/aave/v3/events.sol
Normal file
|
@ -0,0 +1,34 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
contract Events {
|
||||
event LogDeposit(
|
||||
address indexed token,
|
||||
uint256 tokenAmt,
|
||||
uint256 getId,
|
||||
uint256 setId
|
||||
);
|
||||
event LogWithdraw(
|
||||
address indexed token,
|
||||
uint256 tokenAmt,
|
||||
uint256 getId,
|
||||
uint256 setId
|
||||
);
|
||||
event LogBorrow(
|
||||
address indexed token,
|
||||
uint256 tokenAmt,
|
||||
uint256 indexed rateMode,
|
||||
uint256 getId,
|
||||
uint256 setId
|
||||
);
|
||||
event LogPayback(
|
||||
address indexed token,
|
||||
uint256 tokenAmt,
|
||||
uint256 indexed rateMode,
|
||||
uint256 getId,
|
||||
uint256 setId
|
||||
);
|
||||
event LogEnableCollateral(address[] tokens);
|
||||
event LogSwapRateMode(address indexed token, uint256 rateMode);
|
||||
event LogSetUserEMode(uint8 categoryId);
|
||||
}
|
67
contracts/arbitrum/connectors/aave/v3/helpers.sol
Normal file
67
contracts/arbitrum/connectors/aave/v3/helpers.sol
Normal file
|
@ -0,0 +1,67 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
import { DSMath } from "../../../common/math.sol";
|
||||
import { Basic } from "../../../common/basic.sol";
|
||||
import { AavePoolProviderInterface, AaveDataProviderInterface } from "./interface.sol";
|
||||
|
||||
abstract contract Helpers is DSMath, Basic {
|
||||
/**
|
||||
* @dev Aave Pool Provider
|
||||
*/
|
||||
AavePoolProviderInterface internal constant aaveProvider =
|
||||
AavePoolProviderInterface(0xa97684ead0e402dC232d5A977953DF7ECBaB3CDb); // Arbitrum address - PoolAddressesProvider
|
||||
|
||||
/**
|
||||
* @dev Aave Pool Data Provider
|
||||
*/
|
||||
AaveDataProviderInterface internal constant aaveData =
|
||||
AaveDataProviderInterface(0x69FA688f1Dc47d4B5d8029D5a35FB7a548310654); //Arbitrum address - PoolDataProvider
|
||||
|
||||
/**
|
||||
* @dev Aave Referral Code
|
||||
*/
|
||||
uint16 internal constant referralCode = 3228;
|
||||
|
||||
/**
|
||||
* @dev Checks if collateral is enabled for an asset
|
||||
* @param token token address of the asset.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
|
||||
*/
|
||||
|
||||
function getIsColl(address token) internal view returns (bool isCol) {
|
||||
(, , , , , , , , isCol) = aaveData.getUserReserveData(
|
||||
token,
|
||||
address(this)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Get total debt balance & fee for an asset
|
||||
* @param token token address of the debt.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
|
||||
* @param rateMode Borrow rate mode (Stable = 1, Variable = 2)
|
||||
*/
|
||||
function getPaybackBalance(address token, uint256 rateMode)
|
||||
internal
|
||||
view
|
||||
returns (uint256)
|
||||
{
|
||||
(, uint256 stableDebt, uint256 variableDebt, , , , , , ) = aaveData
|
||||
.getUserReserveData(token, address(this));
|
||||
return rateMode == 1 ? stableDebt : variableDebt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Get total collateral balance for an asset
|
||||
* @param token token address of the collateral.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
|
||||
*/
|
||||
function getCollateralBalance(address token)
|
||||
internal
|
||||
view
|
||||
returns (uint256 bal)
|
||||
{
|
||||
(bal, , , , , , , , ) = aaveData.getUserReserveData(
|
||||
token,
|
||||
address(this)
|
||||
);
|
||||
}
|
||||
}
|
92
contracts/arbitrum/connectors/aave/v3/interface.sol
Normal file
92
contracts/arbitrum/connectors/aave/v3/interface.sol
Normal file
|
@ -0,0 +1,92 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
interface AaveInterface {
|
||||
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 swapBorrowRateMode(address asset, uint256 interestRateMode)
|
||||
external;
|
||||
|
||||
function setUserEMode(uint8 categoryId) external;
|
||||
}
|
||||
|
||||
interface AavePoolProviderInterface {
|
||||
function getPool() external view returns (address);
|
||||
}
|
||||
|
||||
interface AaveDataProviderInterface {
|
||||
function getReserveTokensAddresses(address _asset)
|
||||
external
|
||||
view
|
||||
returns (
|
||||
address aTokenAddress,
|
||||
address stableDebtTokenAddress,
|
||||
address variableDebtTokenAddress
|
||||
);
|
||||
|
||||
function getUserReserveData(address _asset, address _user)
|
||||
external
|
||||
view
|
||||
returns (
|
||||
uint256 currentATokenBalance,
|
||||
uint256 currentStableDebt,
|
||||
uint256 currentVariableDebt,
|
||||
uint256 principalStableDebt,
|
||||
uint256 scaledVariableDebt,
|
||||
uint256 stableBorrowRate,
|
||||
uint256 liquidityRate,
|
||||
uint40 stableRateLastUpdated,
|
||||
bool usageAsCollateralEnabled
|
||||
);
|
||||
|
||||
function getReserveEModeCategory(address asset)
|
||||
external
|
||||
view
|
||||
returns (uint256);
|
||||
}
|
||||
|
||||
interface AaveAddressProviderRegistryInterface {
|
||||
function getAddressesProvidersList()
|
||||
external
|
||||
view
|
||||
returns (address[] memory);
|
||||
}
|
||||
|
||||
interface ATokenInterface {
|
||||
function balanceOf(address _user) external view returns (uint256);
|
||||
}
|
297
contracts/arbitrum/connectors/aave/v3/main.sol
Normal file
297
contracts/arbitrum/connectors/aave/v3/main.sol
Normal file
|
@ -0,0 +1,297 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
/**
|
||||
* @title Aave v3.
|
||||
* @dev Lending & Borrowing.
|
||||
*/
|
||||
|
||||
import { TokenInterface } from "../../../common/interfaces.sol";
|
||||
import { Stores } from "../../../common/stores.sol";
|
||||
import { Helpers } from "./helpers.sol";
|
||||
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)
|
||||
{
|
||||
uint256 _amt = getUint(getId, amt);
|
||||
|
||||
AaveInterface aave = AaveInterface(aaveProvider.getPool());
|
||||
|
||||
bool isEth = token == ethAddr;
|
||||
address _token = isEth ? wethAddr : token;
|
||||
|
||||
TokenInterface tokenContract = TokenInterface(_token);
|
||||
|
||||
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);
|
||||
|
||||
aave.supply(_token, _amt, address(this), referralCode);
|
||||
|
||||
if (!getIsColl(_token)) {
|
||||
aave.setUserUseReserveAsCollateral(_token, true);
|
||||
}
|
||||
|
||||
setUint(setId, _amt);
|
||||
|
||||
_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)
|
||||
{
|
||||
uint256 _amt = getUint(getId, amt);
|
||||
|
||||
AaveInterface aave = AaveInterface(aaveProvider.getPool());
|
||||
bool isEth = token == ethAddr;
|
||||
address _token = isEth ? wethAddr : token;
|
||||
|
||||
TokenInterface tokenContract = TokenInterface(_token);
|
||||
|
||||
uint256 initialBal = tokenContract.balanceOf(address(this));
|
||||
aave.withdraw(_token, _amt, address(this));
|
||||
uint256 finalBal = tokenContract.balanceOf(address(this));
|
||||
|
||||
_amt = sub(finalBal, initialBal);
|
||||
|
||||
convertWethToEth(isEth, tokenContract, _amt);
|
||||
|
||||
setUint(setId, _amt);
|
||||
|
||||
_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)
|
||||
{
|
||||
uint256 _amt = getUint(getId, amt);
|
||||
|
||||
AaveInterface aave = AaveInterface(aaveProvider.getPool());
|
||||
|
||||
bool isEth = token == ethAddr;
|
||||
address _token = isEth ? wethAddr : token;
|
||||
|
||||
aave.borrow(_token, _amt, rateMode, referralCode, address(this));
|
||||
convertWethToEth(isEth, TokenInterface(_token), _amt);
|
||||
|
||||
setUint(setId, _amt);
|
||||
|
||||
_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)
|
||||
{
|
||||
uint256 _amt = getUint(getId, amt);
|
||||
|
||||
AaveInterface aave = AaveInterface(aaveProvider.getPool());
|
||||
|
||||
bool isEth = token == ethAddr;
|
||||
address _token = isEth ? wethAddr : token;
|
||||
|
||||
TokenInterface tokenContract = TokenInterface(_token);
|
||||
|
||||
_amt = _amt == uint256(-1) ? getPaybackBalance(_token, rateMode) : _amt;
|
||||
|
||||
if (isEth) convertEthToWeth(isEth, tokenContract, _amt);
|
||||
|
||||
approve(tokenContract, address(aave), _amt);
|
||||
|
||||
aave.repay(_token, _amt, rateMode, address(this));
|
||||
|
||||
setUint(setId, _amt);
|
||||
|
||||
_eventName = "LogPayback(address,uint256,uint256,uint256,uint256)";
|
||||
_eventParam = abi.encode(token, _amt, rateMode, getId, setId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Payback borrowed ETH/ERC20_Token using aTokens.
|
||||
* @notice Repays a borrowed `amount` on a specific reserve using the reserve aTokens, burning the equivalent debt tokens.
|
||||
* @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 paybackWithATokens(
|
||||
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.getPool());
|
||||
|
||||
bool isEth = token == ethAddr;
|
||||
address _token = isEth ? wethAddr : token;
|
||||
|
||||
TokenInterface tokenContract = TokenInterface(_token);
|
||||
|
||||
_amt = _amt == uint256(-1) ? getPaybackBalance(_token, rateMode) : _amt;
|
||||
|
||||
if (isEth) convertEthToWeth(isEth, tokenContract, _amt);
|
||||
|
||||
approve(tokenContract, address(aave), _amt);
|
||||
|
||||
aave.repayWithATokens(_token, _amt, rateMode);
|
||||
|
||||
setUint(setId, _amt);
|
||||
|
||||
_eventName = "LogPayback(address,uint256,uint256,uint256,uint256)";
|
||||
_eventParam = abi.encode(token, _amt, rateMode, 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)
|
||||
{
|
||||
uint256 _length = tokens.length;
|
||||
require(_length > 0, "0-tokens-not-allowed");
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
_eventName = "LogEnableCollateral(address[])";
|
||||
_eventParam = abi.encode(tokens);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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, uint256 rateMode)
|
||||
external
|
||||
payable
|
||||
returns (string memory _eventName, bytes memory _eventParam)
|
||||
{
|
||||
AaveInterface aave = AaveInterface(aaveProvider.getPool());
|
||||
|
||||
uint256 currentRateMode = rateMode == 1 ? 2 : 1;
|
||||
|
||||
if (getPaybackBalance(token, currentRateMode) > 0) {
|
||||
aave.swapBorrowRateMode(token, rateMode);
|
||||
}
|
||||
|
||||
_eventName = "LogSwapRateMode(address,uint256)";
|
||||
_eventParam = abi.encode(token, rateMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Set user e-mode
|
||||
* @notice Updates the user's e-mode category
|
||||
* @param categoryId The category Id of the e-mode user want to set
|
||||
*/
|
||||
function setUserEMode(uint8 categoryId)
|
||||
external
|
||||
returns (string memory _eventName, bytes memory _eventParam)
|
||||
{
|
||||
AaveInterface aave = AaveInterface(aaveProvider.getPool());
|
||||
|
||||
aave.setUserEMode(categoryId);
|
||||
|
||||
_eventName = "LogSetUserEMode(uint8)";
|
||||
_eventParam = abi.encode(categoryId);
|
||||
}
|
||||
}
|
||||
|
||||
contract ConnectV2AaveV3Arbitrum is AaveResolver {
|
||||
string public constant name = "AaveV3-v1.0";
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
contract Events {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
contract Events {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
contract Events {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
contract Events {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity >=0.7.0;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity >=0.7.0;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
contract Events {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.6;
|
||||
pragma abicoder v2;
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.6;
|
||||
pragma abicoder v2;
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.6;
|
||||
pragma abicoder v2;
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
contract Events {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.6;
|
||||
pragma abicoder v2;
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.6;
|
||||
pragma abicoder v2;
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.6;
|
||||
pragma abicoder v2;
|
||||
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
contract Events {
|
||||
event LogSwap(
|
||||
address indexed buyToken,
|
||||
address indexed sellToken,
|
||||
uint256 buyAmt,
|
||||
uint256 sellAmt,
|
||||
uint256 getId,
|
||||
uint256 setId
|
||||
);
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
import { TokenInterface } from "../../../common/interfaces.sol";
|
||||
import { DSMath } from "../../../common/math.sol";
|
||||
import { Basic } from "../../../common/basic.sol";
|
||||
import { SwapData } from "./interface.sol";
|
||||
|
||||
abstract contract Helpers is DSMath, Basic {
|
||||
/**
|
||||
* @dev UniswapV3 Swap Router Address
|
||||
*/
|
||||
address internal constant V3_SWAP_ROUTER_ADDRESS =
|
||||
0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45;
|
||||
|
||||
/**
|
||||
* @dev UniswapV3 swapHelper
|
||||
* @param swapData - Struct defined in interfaces.sol
|
||||
*/
|
||||
function _swapHelper(SwapData memory swapData)
|
||||
internal
|
||||
returns (uint256 buyAmt)
|
||||
{
|
||||
(uint256 _buyDec, uint256 _sellDec) = getTokensDec(
|
||||
swapData.buyToken,
|
||||
swapData.sellToken
|
||||
);
|
||||
uint256 _sellAmt18 = convertTo18(_sellDec, swapData._sellAmt);
|
||||
uint256 _slippageAmt = convert18ToDec(
|
||||
_buyDec,
|
||||
wmul(swapData.unitAmt, _sellAmt18)
|
||||
);
|
||||
|
||||
uint256 initalBal = getTokenBal(swapData.buyToken);
|
||||
|
||||
// solium-disable-next-line security/no-call-value
|
||||
(bool success, ) = V3_SWAP_ROUTER_ADDRESS.call(swapData.callData);
|
||||
if (!success) revert("uniswapV3-swap-failed");
|
||||
|
||||
uint256 finalBal = getTokenBal(swapData.buyToken);
|
||||
|
||||
buyAmt = sub(finalBal, initalBal);
|
||||
require(_slippageAmt <= buyAmt, "Too much slippage");
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Gets the swapping data from auto router sdk
|
||||
* @param swapData Struct with multiple swap data defined in interfaces.sol
|
||||
* @param setId Set token amount at this ID in `InstaMemory` Contract.
|
||||
*/
|
||||
function _swap(SwapData memory swapData, uint256 setId)
|
||||
internal
|
||||
returns (SwapData memory)
|
||||
{
|
||||
bool isEthSellToken = address(swapData.sellToken) == ethAddr;
|
||||
bool isEthBuyToken = address(swapData.buyToken) == ethAddr;
|
||||
|
||||
swapData.sellToken = isEthSellToken
|
||||
? TokenInterface(wethAddr)
|
||||
: swapData.sellToken;
|
||||
swapData.buyToken = isEthBuyToken
|
||||
? TokenInterface(wethAddr)
|
||||
: swapData.buyToken;
|
||||
|
||||
convertEthToWeth(isEthSellToken, swapData.sellToken, swapData._sellAmt);
|
||||
|
||||
approve(
|
||||
TokenInterface(swapData.sellToken),
|
||||
V3_SWAP_ROUTER_ADDRESS,
|
||||
swapData._sellAmt
|
||||
);
|
||||
|
||||
swapData._buyAmt = _swapHelper(swapData);
|
||||
|
||||
convertWethToEth(isEthBuyToken, swapData.buyToken, swapData._buyAmt);
|
||||
|
||||
setUint(setId, swapData._buyAmt);
|
||||
|
||||
return swapData;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
import { TokenInterface } from "../../../common/interfaces.sol";
|
||||
|
||||
struct SwapData {
|
||||
TokenInterface sellToken;
|
||||
TokenInterface buyToken;
|
||||
uint256 _sellAmt;
|
||||
uint256 _buyAmt;
|
||||
uint256 unitAmt;
|
||||
bytes callData;
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
/**
|
||||
* @title UniswapV3_autoRouter.
|
||||
* @dev DEX.
|
||||
*/
|
||||
|
||||
// import files from common directory
|
||||
import { TokenInterface, MemoryInterface } from "../../../common/interfaces.sol";
|
||||
import { Stores } from "../../../common/stores.sol";
|
||||
import { SwapData } from "./interface.sol";
|
||||
import { Helpers } from "./helpers.sol";
|
||||
import { Events } from "./events.sol";
|
||||
|
||||
abstract contract AutoRouter is Helpers, Events {
|
||||
/**
|
||||
* @dev Sell ETH/ERC20_Token using uniswap v3 auto router.
|
||||
* @notice Swap tokens from getting an optimized trade routes
|
||||
* @param buyAddr The address of the token to buy.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
|
||||
* @param sellAddr The address of the token to sell.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
|
||||
* @param sellAmt The amount of the token to sell.
|
||||
* @param unitAmt The amount of buyAmt/sellAmt with slippage.
|
||||
* @param callData Data from Uniswap V3 auto router SDK.
|
||||
* @param setId ID stores the amount of token brought.
|
||||
*/
|
||||
function sell(
|
||||
address buyAddr,
|
||||
address sellAddr,
|
||||
uint256 sellAmt,
|
||||
uint256 unitAmt,
|
||||
bytes calldata callData,
|
||||
uint256 setId
|
||||
)
|
||||
external
|
||||
payable
|
||||
returns (string memory _eventName, bytes memory _eventParam)
|
||||
{
|
||||
SwapData memory swapData = SwapData({
|
||||
buyToken: TokenInterface(buyAddr),
|
||||
sellToken: TokenInterface(sellAddr),
|
||||
unitAmt: unitAmt,
|
||||
callData: callData,
|
||||
_sellAmt: sellAmt,
|
||||
_buyAmt: 0
|
||||
});
|
||||
|
||||
swapData = _swap(swapData, setId);
|
||||
|
||||
_eventName = "LogSwap(address,address,uint256,uint256,uint256,uint256)";
|
||||
_eventParam = abi.encode(
|
||||
buyAddr,
|
||||
sellAddr,
|
||||
swapData._buyAmt,
|
||||
swapData._sellAmt,
|
||||
0,
|
||||
setId
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
contract ConnectV2UniswapV3AutoRouterArbitrum is AutoRouter {
|
||||
string public name = "UniswapV3-Auto-Router-v1";
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
contract Events {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.6;
|
||||
pragma abicoder v2;
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.6;
|
||||
pragma abicoder v2;
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
contract Events {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
import { TokenInterface } from "../../common/interfaces.sol";
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
import { TokenInterface } from "./interfaces.sol";
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
interface TokenInterface {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol";
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
import { MemoryInterface } from "./interfaces.sol";
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
contract Events {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
import {TokenInterface} from "../../common/interfaces.sol";
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
import {TokenInterface} from "../../common/interfaces.sol";
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
contract Events {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
import { TokenInterface } from "../../common/interfaces.sol";
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
import { TokenInterface } from "../../common/interfaces.sol";
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
contract Events {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
import { DSMath } from "../../../common/math.sol";
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
interface AaveIncentivesInterface {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
contract Events {
|
||||
event LogAaveImportV2ToV3(
|
||||
address indexed user,
|
||||
bool doImport,
|
||||
bool convertStable,
|
||||
address[] supplyTokensV2,
|
||||
address[] supplyTokensV3,
|
||||
address[] borrowTokensV2,
|
||||
address[] borrowTokensV3,
|
||||
uint256[] flashLoanFees,
|
||||
uint256[] supplyAmts,
|
||||
uint256[] stableBorrowAmts,
|
||||
uint256[] variableBorrowAmts
|
||||
);
|
||||
}
|
361
contracts/avalanche/connectors/aave/v2-to-v3-import/helpers.sol
Normal file
361
contracts/avalanche/connectors/aave/v2-to-v3-import/helpers.sol
Normal file
|
@ -0,0 +1,361 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
import { DSMath } from "../../../common/math.sol";
|
||||
import { Basic } from "../../../common/basic.sol";
|
||||
import { TokenInterface, AccountInterface } from "../../../common/interfaces.sol";
|
||||
import "./events.sol";
|
||||
import "./interfaces.sol";
|
||||
|
||||
abstract contract Helper is DSMath, Basic {
|
||||
/**
|
||||
* @dev Aave referal code
|
||||
*/
|
||||
uint16 internal constant referalCode = 3228;
|
||||
|
||||
/**
|
||||
* @dev AaveV2 Lending Pool Provider
|
||||
*/
|
||||
AaveV2LendingPoolProviderInterface internal constant aaveV2Provider =
|
||||
AaveV2LendingPoolProviderInterface(
|
||||
0xb6A86025F0FE1862B372cb0ca18CE3EDe02A318f // v2 address: LendingPoolAddressProvider avax
|
||||
);
|
||||
|
||||
/**
|
||||
* @dev AaveV3 Lending Pool Provider
|
||||
*/
|
||||
AaveV3PoolProviderInterface internal constant aaveV3Provider =
|
||||
AaveV3PoolProviderInterface(
|
||||
0xa97684ead0e402dC232d5A977953DF7ECBaB3CDb // v3 - PoolAddressesProvider Avalanche
|
||||
);
|
||||
|
||||
/**
|
||||
* @dev Aave Protocol Data Provider
|
||||
*/
|
||||
AaveV2DataProviderInterface internal constant aaveV2Data =
|
||||
AaveV2DataProviderInterface(0x65285E9dfab318f57051ab2b139ccCf232945451); // aave v2 - avax
|
||||
|
||||
function getIsColl(address token, address user)
|
||||
internal
|
||||
view
|
||||
returns (bool isCol)
|
||||
{
|
||||
(, , , , , , , , isCol) = aaveV2Data.getUserReserveData(token, user);
|
||||
}
|
||||
|
||||
struct ImportData {
|
||||
address[] _supplyTokens;
|
||||
address[] _supplyTokensV3;
|
||||
address[] _borrowTokens;
|
||||
address[] _borrowTokensV3;
|
||||
ATokenV2Interface[] aTokens;
|
||||
uint256[] supplyAmts;
|
||||
uint256[] variableBorrowAmts;
|
||||
uint256[] variableBorrowAmtsWithFee;
|
||||
uint256[] stableBorrowAmts;
|
||||
uint256[] stableBorrowAmtsWithFee;
|
||||
uint256[] totalBorrowAmts;
|
||||
uint256[] totalBorrowAmtsWithFee;
|
||||
bool convertStable;
|
||||
}
|
||||
|
||||
struct ImportInputData {
|
||||
address[] supplyTokens;
|
||||
address[] borrowTokens;
|
||||
bool convertStable;
|
||||
uint256[] flashLoanFees;
|
||||
}
|
||||
}
|
||||
|
||||
contract _AaveHelper is Helper {
|
||||
/*
|
||||
** Convert Avalanche Bridge tokens to Offical tokens. Like USDC.e to USDC
|
||||
*/
|
||||
function convertABTokens(address _token) internal pure returns (address) {
|
||||
if (_token == 0xc7198437980c041c805A1EDcbA50c1Ce5db95118) {
|
||||
// USDT.e => USDT
|
||||
return 0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7;
|
||||
} else if (_token == 0xA7D7079b0FEaD91F3e65f86E8915Cb59c1a4C664) {
|
||||
// USDC.e => USDC
|
||||
return 0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E;
|
||||
} else {
|
||||
return _token;
|
||||
}
|
||||
}
|
||||
|
||||
function getBorrowAmountV2(address _token, address userAccount)
|
||||
internal
|
||||
view
|
||||
returns (uint256 stableBorrow, uint256 variableBorrow)
|
||||
{
|
||||
(
|
||||
,
|
||||
address stableDebtTokenAddress,
|
||||
address variableDebtTokenAddress
|
||||
) = aaveV2Data.getReserveTokensAddresses(_token);
|
||||
|
||||
stableBorrow = ATokenV2Interface(stableDebtTokenAddress).balanceOf(
|
||||
userAccount
|
||||
);
|
||||
variableBorrow = ATokenV2Interface(variableDebtTokenAddress).balanceOf(
|
||||
userAccount
|
||||
);
|
||||
}
|
||||
|
||||
function getBorrowAmountsV2(
|
||||
address userAccount,
|
||||
AaveV2Interface aaveV2,
|
||||
ImportInputData memory inputData,
|
||||
ImportData memory data
|
||||
) internal returns (ImportData memory) {
|
||||
if (inputData.borrowTokens.length > 0) {
|
||||
data._borrowTokens = new address[](inputData.borrowTokens.length);
|
||||
data._borrowTokensV3 = new address[](inputData.borrowTokens.length);
|
||||
data.variableBorrowAmts = new uint256[](
|
||||
inputData.borrowTokens.length
|
||||
);
|
||||
data.stableBorrowAmts = new uint256[](
|
||||
inputData.borrowTokens.length
|
||||
);
|
||||
data.variableBorrowAmtsWithFee = new uint256[](
|
||||
inputData.borrowTokens.length
|
||||
);
|
||||
data.stableBorrowAmtsWithFee = new uint256[](
|
||||
inputData.borrowTokens.length
|
||||
);
|
||||
data.totalBorrowAmtsWithFee = new uint256[](
|
||||
inputData.borrowTokens.length
|
||||
);
|
||||
data.totalBorrowAmts = new uint256[](inputData.borrowTokens.length);
|
||||
|
||||
for (uint256 i = 0; i < inputData.borrowTokens.length; i++) {
|
||||
for (uint256 j = i; j < inputData.borrowTokens.length; j++) {
|
||||
if (j != i) {
|
||||
require(
|
||||
inputData.borrowTokens[i] !=
|
||||
inputData.borrowTokens[j],
|
||||
"token-repeated"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (uint256 i = 0; i < inputData.borrowTokens.length; i++) {
|
||||
address _token = inputData.borrowTokens[i] == avaxAddr
|
||||
? wavaxAddr
|
||||
: inputData.borrowTokens[i];
|
||||
data._borrowTokens[i] = _token;
|
||||
data._borrowTokensV3[i] = convertABTokens(_token);
|
||||
|
||||
(
|
||||
data.stableBorrowAmts[i],
|
||||
data.variableBorrowAmts[i]
|
||||
) = getBorrowAmountV2(_token, userAccount);
|
||||
|
||||
if (data.variableBorrowAmts[i] != 0) {
|
||||
data.variableBorrowAmtsWithFee[i] = add(
|
||||
data.variableBorrowAmts[i],
|
||||
inputData.flashLoanFees[i]
|
||||
);
|
||||
data.stableBorrowAmtsWithFee[i] = data.stableBorrowAmts[i];
|
||||
} else {
|
||||
data.stableBorrowAmtsWithFee[i] = add(
|
||||
data.stableBorrowAmts[i],
|
||||
inputData.flashLoanFees[i]
|
||||
);
|
||||
}
|
||||
|
||||
data.totalBorrowAmts[i] = add(
|
||||
data.stableBorrowAmts[i],
|
||||
data.variableBorrowAmts[i]
|
||||
);
|
||||
data.totalBorrowAmtsWithFee[i] = add(
|
||||
data.stableBorrowAmtsWithFee[i],
|
||||
data.variableBorrowAmtsWithFee[i]
|
||||
);
|
||||
|
||||
if (data.totalBorrowAmts[i] > 0) {
|
||||
uint256 _amt = data.totalBorrowAmts[i];
|
||||
TokenInterface(_token).approve(address(aaveV2), _amt);
|
||||
}
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
function getSupplyAmountsV2(
|
||||
address userAccount,
|
||||
ImportInputData memory inputData,
|
||||
ImportData memory data
|
||||
) internal view returns (ImportData memory) {
|
||||
data.supplyAmts = new uint256[](inputData.supplyTokens.length);
|
||||
data._supplyTokens = new address[](inputData.supplyTokens.length);
|
||||
data._supplyTokensV3 = new address[](inputData.supplyTokens.length);
|
||||
data.aTokens = new ATokenV2Interface[](inputData.supplyTokens.length);
|
||||
|
||||
for (uint256 i = 0; i < inputData.supplyTokens.length; i++) {
|
||||
for (uint256 j = i; j < inputData.supplyTokens.length; j++) {
|
||||
if (j != i) {
|
||||
require(
|
||||
inputData.supplyTokens[i] != inputData.supplyTokens[j],
|
||||
"token-repeated"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (uint256 i = 0; i < inputData.supplyTokens.length; i++) {
|
||||
address _token = inputData.supplyTokens[i] == avaxAddr
|
||||
? wavaxAddr
|
||||
: inputData.supplyTokens[i];
|
||||
(address _aToken, , ) = aaveV2Data.getReserveTokensAddresses(
|
||||
_token
|
||||
);
|
||||
data._supplyTokens[i] = _token;
|
||||
data._supplyTokensV3[i] = convertABTokens(_token);
|
||||
|
||||
data.aTokens[i] = ATokenV2Interface(_aToken);
|
||||
data.supplyAmts[i] = data.aTokens[i].balanceOf(userAccount);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
function _paybackBehalfOneV2(
|
||||
AaveV2Interface aaveV2,
|
||||
address token,
|
||||
uint256 amt,
|
||||
uint256 rateMode,
|
||||
address user
|
||||
) private {
|
||||
aaveV2.repay(token, amt, rateMode, user);
|
||||
}
|
||||
|
||||
function _PaybackStableV2(
|
||||
uint256 _length,
|
||||
AaveV2Interface aaveV2,
|
||||
address[] memory tokens,
|
||||
uint256[] memory amts,
|
||||
address user
|
||||
) internal {
|
||||
for (uint256 i = 0; i < _length; i++) {
|
||||
if (amts[i] > 0) {
|
||||
_paybackBehalfOneV2(aaveV2, tokens[i], amts[i], 1, user);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _PaybackVariableV2(
|
||||
uint256 _length,
|
||||
AaveV2Interface aaveV2,
|
||||
address[] memory tokens,
|
||||
uint256[] memory amts,
|
||||
address user
|
||||
) internal {
|
||||
for (uint256 i = 0; i < _length; i++) {
|
||||
if (amts[i] > 0) {
|
||||
_paybackBehalfOneV2(aaveV2, tokens[i], amts[i], 2, user);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _TransferAtokensV2(
|
||||
uint256 _length,
|
||||
AaveV2Interface aaveV2,
|
||||
ATokenV2Interface[] memory atokenContracts,
|
||||
uint256[] memory amts,
|
||||
address[] memory tokens,
|
||||
address userAccount
|
||||
) internal {
|
||||
for (uint256 i = 0; i < _length; i++) {
|
||||
if (amts[i] > 0) {
|
||||
uint256 _amt = amts[i];
|
||||
require(
|
||||
atokenContracts[i].transferFrom(
|
||||
userAccount,
|
||||
address(this),
|
||||
_amt
|
||||
),
|
||||
"allowance?"
|
||||
);
|
||||
|
||||
if (!getIsColl(tokens[i], address(this))) {
|
||||
aaveV2.setUserUseReserveAsCollateral(tokens[i], true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _WithdrawTokensFromV2(
|
||||
uint256 _length,
|
||||
AaveV2Interface aaveV2,
|
||||
uint256[] memory amts,
|
||||
address[] memory tokens
|
||||
) internal {
|
||||
for (uint256 i = 0; i < _length; i++) {
|
||||
if (amts[i] > 0) {
|
||||
uint256 _amt = amts[i];
|
||||
address _token = tokens[i];
|
||||
aaveV2.withdraw(_token, _amt, address(this));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _depositTokensV3(
|
||||
uint256 _length,
|
||||
AaveV3Interface aaveV3,
|
||||
uint256[] memory amts,
|
||||
address[] memory tokens
|
||||
) internal {
|
||||
for (uint256 i = 0; i < _length; i++) {
|
||||
if (amts[i] > 0) {
|
||||
uint256 _amt = amts[i];
|
||||
address _token = tokens[i];
|
||||
TokenInterface tokenContract = TokenInterface(_token);
|
||||
require(
|
||||
tokenContract.balanceOf(address(this)) >= _amt,
|
||||
"Insufficient funds to deposit in v3"
|
||||
);
|
||||
approve(tokenContract, address(aaveV3), _amt);
|
||||
aaveV3.supply(_token, _amt, address(this), referalCode);
|
||||
|
||||
if (!getIsColl(_token, address(this))) {
|
||||
aaveV3.setUserUseReserveAsCollateral(_token, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _BorrowVariableV3(
|
||||
uint256 _length,
|
||||
AaveV3Interface aaveV3,
|
||||
address[] memory tokens,
|
||||
uint256[] memory amts
|
||||
) internal {
|
||||
for (uint256 i = 0; i < _length; i++) {
|
||||
if (amts[i] > 0) {
|
||||
_borrowOneV3(aaveV3, tokens[i], amts[i], 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _BorrowStableV3(
|
||||
uint256 _length,
|
||||
AaveV3Interface aaveV3,
|
||||
address[] memory tokens,
|
||||
uint256[] memory amts
|
||||
) internal {
|
||||
for (uint256 i = 0; i < _length; i++) {
|
||||
if (amts[i] > 0) {
|
||||
_borrowOneV3(aaveV3, tokens[i], amts[i], 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _borrowOneV3(
|
||||
AaveV3Interface aaveV3,
|
||||
address token,
|
||||
uint256 amt,
|
||||
uint256 rateMode
|
||||
) private {
|
||||
aaveV3.borrow(token, amt, rateMode, referalCode, address(this));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,151 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
// aave v2
|
||||
interface AaveV2Interface {
|
||||
function withdraw(
|
||||
address _asset,
|
||||
uint256 _amount,
|
||||
address _to
|
||||
) external;
|
||||
|
||||
function borrow(
|
||||
address _asset,
|
||||
uint256 _amount,
|
||||
uint256 _interestRateMode,
|
||||
uint16 _referralCode,
|
||||
address _onBehalfOf
|
||||
) external;
|
||||
|
||||
function repay(
|
||||
address _asset,
|
||||
uint256 _amount,
|
||||
uint256 _rateMode,
|
||||
address _onBehalfOf
|
||||
) external;
|
||||
|
||||
function setUserUseReserveAsCollateral(
|
||||
address _asset,
|
||||
bool _useAsCollateral
|
||||
) external;
|
||||
|
||||
function getUserAccountData(address user)
|
||||
external
|
||||
view
|
||||
returns (
|
||||
uint256 totalCollateralETH,
|
||||
uint256 totalDebtETH,
|
||||
uint256 availableBorrowsETH,
|
||||
uint256 currentLiquidationThreshold,
|
||||
uint256 ltv,
|
||||
uint256 healthFactor
|
||||
);
|
||||
}
|
||||
|
||||
interface AaveV2LendingPoolProviderInterface {
|
||||
function getLendingPool() external view returns (address);
|
||||
}
|
||||
|
||||
// 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
|
||||
);
|
||||
|
||||
// function getReserveConfigurationData(address asset)
|
||||
// external
|
||||
// view
|
||||
// returns (
|
||||
// uint256 decimals,
|
||||
// uint256 ltv,
|
||||
// uint256 liquidationThreshold,
|
||||
// uint256 liquidationBonus,
|
||||
// uint256 reserveFactor,
|
||||
// bool usageAsCollateralEnabled,
|
||||
// bool borrowingEnabled,
|
||||
// bool stableBorrowRateEnabled,
|
||||
// bool isActive,
|
||||
// bool isFrozen
|
||||
// );
|
||||
|
||||
function getReserveTokensAddresses(address asset)
|
||||
external
|
||||
view
|
||||
returns (
|
||||
address aTokenAddress,
|
||||
address stableDebtTokenAddress,
|
||||
address variableDebtTokenAddress
|
||||
);
|
||||
}
|
||||
|
||||
interface ATokenV2Interface {
|
||||
function scaledBalanceOf(address _user) external view returns (uint256);
|
||||
|
||||
function isTransferAllowed(address _user, uint256 _amount)
|
||||
external
|
||||
view
|
||||
returns (bool);
|
||||
|
||||
function balanceOf(address _user) external view returns (uint256);
|
||||
|
||||
function transferFrom(
|
||||
address,
|
||||
address,
|
||||
uint256
|
||||
) external returns (bool);
|
||||
|
||||
function allowance(address, address) external returns (uint256);
|
||||
}
|
||||
|
||||
// aave v3
|
||||
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 setUserUseReserveAsCollateral(address asset, bool useAsCollateral)
|
||||
external;
|
||||
|
||||
function swapBorrowRateMode(address asset, uint256 interestRateMode)
|
||||
external;
|
||||
}
|
||||
|
||||
interface AaveV3PoolProviderInterface {
|
||||
function getPool() external view returns (address);
|
||||
}
|
157
contracts/avalanche/connectors/aave/v2-to-v3-import/main.sol
Normal file
157
contracts/avalanche/connectors/aave/v2-to-v3-import/main.sol
Normal file
|
@ -0,0 +1,157 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import { TokenInterface, AccountInterface } from "../../../common/interfaces.sol";
|
||||
import "./interfaces.sol";
|
||||
import "./helpers.sol";
|
||||
import "./events.sol";
|
||||
|
||||
/**
|
||||
* @title Aave v2 to v3 import connector .
|
||||
* @dev migrate aave V2 position to aave v3 position
|
||||
*/
|
||||
contract _AaveV2ToV3MigrationResolver is _AaveHelper {
|
||||
function _importAave(
|
||||
address userAccount,
|
||||
ImportInputData memory inputData,
|
||||
bool doImport
|
||||
) internal returns (string memory _eventName, bytes memory _eventParam) {
|
||||
if (doImport) {
|
||||
// check only when we are importing from user's address
|
||||
require(
|
||||
AccountInterface(address(this)).isAuth(userAccount),
|
||||
"user-account-not-auth"
|
||||
);
|
||||
}
|
||||
require(inputData.supplyTokens.length > 0, "0-length-not-allowed");
|
||||
|
||||
ImportData memory data;
|
||||
|
||||
AaveV2Interface aaveV2 = AaveV2Interface(
|
||||
aaveV2Provider.getLendingPool()
|
||||
);
|
||||
AaveV3Interface aaveV3 = AaveV3Interface(aaveV3Provider.getPool());
|
||||
|
||||
data = getBorrowAmountsV2(userAccount, aaveV2, inputData, data);
|
||||
data = getSupplyAmountsV2(userAccount, inputData, data);
|
||||
|
||||
// payback borrowed amount;
|
||||
_PaybackStableV2(
|
||||
data._borrowTokens.length,
|
||||
aaveV2,
|
||||
data._borrowTokens,
|
||||
data.stableBorrowAmts,
|
||||
userAccount
|
||||
);
|
||||
_PaybackVariableV2(
|
||||
data._borrowTokens.length,
|
||||
aaveV2,
|
||||
data._borrowTokens,
|
||||
data.variableBorrowAmts,
|
||||
userAccount
|
||||
);
|
||||
|
||||
if (doImport) {
|
||||
// transfer atokens to this address;
|
||||
_TransferAtokensV2(
|
||||
data._supplyTokens.length,
|
||||
aaveV2,
|
||||
data.aTokens,
|
||||
data.supplyAmts,
|
||||
data._supplyTokens,
|
||||
userAccount
|
||||
);
|
||||
}
|
||||
// withdraw v2 supplied tokens
|
||||
_WithdrawTokensFromV2(
|
||||
data._supplyTokens.length,
|
||||
aaveV2,
|
||||
data.supplyAmts,
|
||||
data._supplyTokens
|
||||
);
|
||||
// deposit tokens in v3
|
||||
_depositTokensV3(
|
||||
data._supplyTokensV3.length,
|
||||
aaveV3,
|
||||
data.supplyAmts,
|
||||
data._supplyTokensV3
|
||||
);
|
||||
|
||||
// borrow assets in aave v3 after migrating position
|
||||
if (data.convertStable) {
|
||||
_BorrowVariableV3(
|
||||
data._borrowTokensV3.length,
|
||||
aaveV3,
|
||||
data._borrowTokensV3,
|
||||
data.totalBorrowAmtsWithFee
|
||||
);
|
||||
} else {
|
||||
_BorrowStableV3(
|
||||
data._borrowTokensV3.length,
|
||||
aaveV3,
|
||||
data._borrowTokensV3,
|
||||
data.stableBorrowAmtsWithFee
|
||||
);
|
||||
_BorrowVariableV3(
|
||||
data._borrowTokensV3.length,
|
||||
aaveV3,
|
||||
data._borrowTokensV3,
|
||||
data.variableBorrowAmtsWithFee
|
||||
);
|
||||
}
|
||||
|
||||
_eventName = "LogAaveImportV2ToV3(address,bool,bool,address[],address[],address[],address[],uint256[],uint256[],uint256[],uint256[])";
|
||||
_eventParam = abi.encode(
|
||||
userAccount,
|
||||
doImport,
|
||||
inputData.convertStable,
|
||||
inputData.supplyTokens,
|
||||
data._supplyTokensV3,
|
||||
inputData.borrowTokens,
|
||||
data._borrowTokensV3,
|
||||
inputData.flashLoanFees,
|
||||
data.supplyAmts,
|
||||
data.stableBorrowAmts,
|
||||
data.variableBorrowAmts
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Import aave position .
|
||||
* @notice Import EOA's aave V2 position to DSA's aave v3 position
|
||||
* @param userAccount The address of the EOA from which aave position will be imported
|
||||
* @param inputData The struct containing all the neccessary input data
|
||||
*/
|
||||
function importAaveV2ToV3(
|
||||
address userAccount,
|
||||
ImportInputData memory inputData
|
||||
)
|
||||
external
|
||||
payable
|
||||
returns (string memory _eventName, bytes memory _eventParam)
|
||||
{
|
||||
(_eventName, _eventParam) = _importAave(userAccount, inputData, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Migrate aave position .
|
||||
* @notice Migrate DSA's aave V2 position to DSA's aave v3 position
|
||||
* @param inputData The struct containing all the neccessary input data
|
||||
*/
|
||||
function migrateAaveV2ToV3(ImportInputData memory inputData)
|
||||
external
|
||||
payable
|
||||
returns (string memory _eventName, bytes memory _eventParam)
|
||||
{
|
||||
(_eventName, _eventParam) = _importAave(
|
||||
address(this),
|
||||
inputData,
|
||||
false
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
contract ConnectV2AaveV2ToV3MigrationAvalanche is _AaveV2ToV3MigrationResolver {
|
||||
string public constant name = "Aave-Import-v2-to-v3";
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
contract Events {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
import { DSMath } from "../../../common/math.sol";
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
interface AaveInterface {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
/**
|
||||
|
|
15
contracts/avalanche/connectors/aave/v3-import/events.sol
Normal file
15
contracts/avalanche/connectors/aave/v3-import/events.sol
Normal file
|
@ -0,0 +1,15 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
contract Events {
|
||||
event LogAaveV3Import(
|
||||
address indexed user,
|
||||
address[] ctokens,
|
||||
string[] supplyIds,
|
||||
string[] borrowIds,
|
||||
uint256[] flashLoanFees,
|
||||
uint256[] supplyAmts,
|
||||
uint256[] borrowAmts
|
||||
);
|
||||
}
|
289
contracts/avalanche/connectors/aave/v3-import/helpers.sol
Normal file
289
contracts/avalanche/connectors/aave/v3-import/helpers.sol
Normal file
|
@ -0,0 +1,289 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
import { DSMath } from "../../../common/math.sol";
|
||||
import { Basic } from "../../../common/basic.sol";
|
||||
import { TokenInterface, AccountInterface } from "../../../common/interfaces.sol";
|
||||
import { AaveInterface, AavePoolProviderInterface, AaveDataProviderInterface } from "./interface.sol";
|
||||
import "./events.sol";
|
||||
import "./interface.sol";
|
||||
|
||||
abstract contract Helper is DSMath, Basic {
|
||||
/**
|
||||
* @dev Aave referal code
|
||||
*/
|
||||
uint16 internal constant referalCode = 3228;
|
||||
|
||||
/**
|
||||
* @dev Aave Pool Provider
|
||||
*/
|
||||
AavePoolProviderInterface internal constant aaveProvider =
|
||||
AavePoolProviderInterface(0xa97684ead0e402dC232d5A977953DF7ECBaB3CDb);
|
||||
|
||||
/**
|
||||
* @dev Aave Protocol Data Provider
|
||||
*/
|
||||
AaveDataProviderInterface internal constant aaveData =
|
||||
AaveDataProviderInterface(0x69FA688f1Dc47d4B5d8029D5a35FB7a548310654);
|
||||
|
||||
function getIsColl(address token, address user)
|
||||
internal
|
||||
view
|
||||
returns (bool isCol)
|
||||
{
|
||||
(, , , , , , , , isCol) = aaveData.getUserReserveData(token, user);
|
||||
}
|
||||
|
||||
struct ImportData {
|
||||
address[] _supplyTokens;
|
||||
address[] _borrowTokens;
|
||||
ATokenInterface[] aTokens;
|
||||
uint256[] supplyAmts;
|
||||
uint256[] variableBorrowAmts;
|
||||
uint256[] variableBorrowAmtsWithFee;
|
||||
uint256[] stableBorrowAmts;
|
||||
uint256[] stableBorrowAmtsWithFee;
|
||||
uint256[] totalBorrowAmts;
|
||||
uint256[] totalBorrowAmtsWithFee;
|
||||
bool convertStable;
|
||||
}
|
||||
|
||||
struct ImportInputData {
|
||||
address[] supplyTokens;
|
||||
address[] borrowTokens;
|
||||
bool convertStable;
|
||||
uint256[] flashLoanFees;
|
||||
}
|
||||
}
|
||||
|
||||
contract AaveHelpers is Helper {
|
||||
function getBorrowAmount(address _token, address userAccount)
|
||||
internal
|
||||
view
|
||||
returns (uint256 stableBorrow, uint256 variableBorrow)
|
||||
{
|
||||
(
|
||||
,
|
||||
address stableDebtTokenAddress,
|
||||
address variableDebtTokenAddress
|
||||
) = aaveData.getReserveTokensAddresses(_token);
|
||||
|
||||
stableBorrow = ATokenInterface(stableDebtTokenAddress).balanceOf(
|
||||
userAccount
|
||||
);
|
||||
variableBorrow = ATokenInterface(variableDebtTokenAddress).balanceOf(
|
||||
userAccount
|
||||
);
|
||||
}
|
||||
|
||||
function getBorrowAmounts(
|
||||
address userAccount,
|
||||
AaveInterface aave,
|
||||
ImportInputData memory inputData,
|
||||
ImportData memory data
|
||||
) internal returns (ImportData memory) {
|
||||
if (inputData.borrowTokens.length > 0) {
|
||||
data._borrowTokens = new address[](inputData.borrowTokens.length);
|
||||
data.variableBorrowAmts = new uint256[](
|
||||
inputData.borrowTokens.length
|
||||
);
|
||||
data.variableBorrowAmtsWithFee = new uint256[](
|
||||
inputData.borrowTokens.length
|
||||
);
|
||||
data.stableBorrowAmts = new uint256[](
|
||||
inputData.borrowTokens.length
|
||||
);
|
||||
data.stableBorrowAmtsWithFee = new uint256[](
|
||||
inputData.borrowTokens.length
|
||||
);
|
||||
data.totalBorrowAmts = new uint256[](inputData.borrowTokens.length);
|
||||
data.totalBorrowAmtsWithFee = new uint256[](
|
||||
inputData.borrowTokens.length
|
||||
);
|
||||
for (uint256 i = 0; i < inputData.borrowTokens.length; i++) {
|
||||
for (uint256 j = i; j < inputData.borrowTokens.length; j++) {
|
||||
if (j != i) {
|
||||
require(
|
||||
inputData.borrowTokens[i] !=
|
||||
inputData.borrowTokens[j],
|
||||
"token-repeated"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (uint256 i = 0; i < inputData.borrowTokens.length; i++) {
|
||||
address _token = inputData.borrowTokens[i] == avaxAddr
|
||||
? wavaxAddr
|
||||
: inputData.borrowTokens[i];
|
||||
data._borrowTokens[i] = _token;
|
||||
|
||||
(
|
||||
data.stableBorrowAmts[i],
|
||||
data.variableBorrowAmts[i]
|
||||
) = getBorrowAmount(_token, userAccount);
|
||||
|
||||
if (data.variableBorrowAmts[i] != 0) {
|
||||
data.variableBorrowAmtsWithFee[i] = add(
|
||||
data.variableBorrowAmts[i],
|
||||
inputData.flashLoanFees[i]
|
||||
);
|
||||
data.stableBorrowAmtsWithFee[i] = data.stableBorrowAmts[i];
|
||||
} else {
|
||||
data.stableBorrowAmtsWithFee[i] = add(
|
||||
data.stableBorrowAmts[i],
|
||||
inputData.flashLoanFees[i]
|
||||
);
|
||||
data.variableBorrowAmtsWithFee[i] = data.variableBorrowAmts[
|
||||
i
|
||||
];
|
||||
}
|
||||
|
||||
data.totalBorrowAmts[i] = add(
|
||||
data.stableBorrowAmts[i],
|
||||
data.variableBorrowAmts[i]
|
||||
);
|
||||
data.totalBorrowAmtsWithFee[i] = add(
|
||||
data.stableBorrowAmtsWithFee[i],
|
||||
data.variableBorrowAmtsWithFee[i]
|
||||
);
|
||||
|
||||
if (data.totalBorrowAmts[i] > 0) {
|
||||
uint256 _amt = data.totalBorrowAmts[i];
|
||||
TokenInterface(_token).approve(address(aave), _amt);
|
||||
}
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
function getSupplyAmounts(
|
||||
address userAccount,
|
||||
ImportInputData memory inputData,
|
||||
ImportData memory data
|
||||
) internal view returns (ImportData memory) {
|
||||
data.supplyAmts = new uint256[](inputData.supplyTokens.length);
|
||||
data._supplyTokens = new address[](inputData.supplyTokens.length);
|
||||
data.aTokens = new ATokenInterface[](inputData.supplyTokens.length);
|
||||
|
||||
for (uint256 i = 0; i < inputData.supplyTokens.length; i++) {
|
||||
for (uint256 j = i; j < inputData.supplyTokens.length; j++) {
|
||||
if (j != i) {
|
||||
require(
|
||||
inputData.supplyTokens[i] != inputData.supplyTokens[j],
|
||||
"token-repeated"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (uint256 i = 0; i < inputData.supplyTokens.length; i++) {
|
||||
address _token = inputData.supplyTokens[i] == avaxAddr
|
||||
? wavaxAddr
|
||||
: inputData.supplyTokens[i];
|
||||
(address _aToken, , ) = aaveData.getReserveTokensAddresses(_token);
|
||||
data._supplyTokens[i] = _token;
|
||||
data.aTokens[i] = ATokenInterface(_aToken);
|
||||
data.supplyAmts[i] = data.aTokens[i].balanceOf(userAccount);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
function _paybackBehalfOne(
|
||||
AaveInterface aave,
|
||||
address token,
|
||||
uint256 amt,
|
||||
uint256 rateMode,
|
||||
address user
|
||||
) private {
|
||||
aave.repay(token, amt, rateMode, user);
|
||||
}
|
||||
|
||||
function _PaybackStable(
|
||||
uint256 _length,
|
||||
AaveInterface aave,
|
||||
address[] memory tokens,
|
||||
uint256[] memory amts,
|
||||
address user
|
||||
) internal {
|
||||
for (uint256 i = 0; i < _length; i++) {
|
||||
if (amts[i] > 0) {
|
||||
_paybackBehalfOne(aave, tokens[i], amts[i], 1, user);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _PaybackVariable(
|
||||
uint256 _length,
|
||||
AaveInterface aave,
|
||||
address[] memory tokens,
|
||||
uint256[] memory amts,
|
||||
address user
|
||||
) internal {
|
||||
for (uint256 i = 0; i < _length; i++) {
|
||||
if (amts[i] > 0) {
|
||||
_paybackBehalfOne(aave, tokens[i], amts[i], 2, user);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _TransferAtokens(
|
||||
uint256 _length,
|
||||
AaveInterface aave,
|
||||
ATokenInterface[] memory atokenContracts,
|
||||
uint256[] memory amts,
|
||||
address[] memory tokens,
|
||||
address userAccount
|
||||
) internal {
|
||||
for (uint256 i = 0; i < _length; i++) {
|
||||
if (amts[i] > 0) {
|
||||
uint256 _amt = amts[i];
|
||||
require(
|
||||
atokenContracts[i].transferFrom(
|
||||
userAccount,
|
||||
address(this),
|
||||
_amt
|
||||
),
|
||||
"allowance?"
|
||||
);
|
||||
|
||||
if (!getIsColl(tokens[i], address(this))) {
|
||||
aave.setUserUseReserveAsCollateral(tokens[i], true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _BorrowVariable(
|
||||
uint256 _length,
|
||||
AaveInterface aave,
|
||||
address[] memory tokens,
|
||||
uint256[] memory amts
|
||||
) internal {
|
||||
for (uint256 i = 0; i < _length; i++) {
|
||||
if (amts[i] > 0) {
|
||||
_borrowOne(aave, tokens[i], amts[i], 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _BorrowStable(
|
||||
uint256 _length,
|
||||
AaveInterface aave,
|
||||
address[] memory tokens,
|
||||
uint256[] memory amts
|
||||
) internal {
|
||||
for (uint256 i = 0; i < _length; i++) {
|
||||
if (amts[i] > 0) {
|
||||
_borrowOne(aave, tokens[i], amts[i], 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _borrowOne(
|
||||
AaveInterface aave,
|
||||
address token,
|
||||
uint256 amt,
|
||||
uint256 rateMode
|
||||
) private {
|
||||
aave.borrow(token, amt, rateMode, referalCode, address(this));
|
||||
}
|
||||
}
|
95
contracts/avalanche/connectors/aave/v3-import/interface.sol
Normal file
95
contracts/avalanche/connectors/aave/v3-import/interface.sol
Normal file
|
@ -0,0 +1,95 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
interface AaveInterface {
|
||||
function supply(
|
||||
address _asset,
|
||||
uint256 _amount,
|
||||
address _onBehalfOf,
|
||||
uint16 _referralCode
|
||||
) external;
|
||||
|
||||
function withdraw(
|
||||
address _asset,
|
||||
uint256 _amount,
|
||||
address _to
|
||||
) external;
|
||||
|
||||
function borrow(
|
||||
address _asset,
|
||||
uint256 _amount,
|
||||
uint256 _interestRateMode,
|
||||
uint16 _referralCode,
|
||||
address _onBehalfOf
|
||||
) external;
|
||||
|
||||
function repay(
|
||||
address _asset,
|
||||
uint256 _amount,
|
||||
uint256 _rateMode,
|
||||
address _onBehalfOf
|
||||
) external;
|
||||
|
||||
function setUserUseReserveAsCollateral(
|
||||
address _asset,
|
||||
bool _useAsCollateral
|
||||
) external;
|
||||
|
||||
function swapBorrowRateMode(address _asset, uint256 _rateMode) external;
|
||||
}
|
||||
|
||||
interface ATokenInterface {
|
||||
function scaledBalanceOf(address _user) external view returns (uint256);
|
||||
|
||||
function isTransferAllowed(address _user, uint256 _amount)
|
||||
external
|
||||
view
|
||||
returns (bool);
|
||||
|
||||
function balanceOf(address _user) external view returns (uint256);
|
||||
|
||||
function transferFrom(
|
||||
address,
|
||||
address,
|
||||
uint256
|
||||
) external returns (bool);
|
||||
|
||||
function allowance(address, address) external returns (uint256);
|
||||
}
|
||||
|
||||
interface AavePoolProviderInterface {
|
||||
function getPool() external view returns (address);
|
||||
}
|
||||
|
||||
interface AaveDataProviderInterface {
|
||||
function getReserveTokensAddresses(address _asset)
|
||||
external
|
||||
view
|
||||
returns (
|
||||
address aTokenAddress,
|
||||
address stableDebtTokenAddress,
|
||||
address variableDebtTokenAddress
|
||||
);
|
||||
|
||||
function getUserReserveData(address _asset, address _user)
|
||||
external
|
||||
view
|
||||
returns (
|
||||
uint256 currentATokenBalance,
|
||||
uint256 currentStableDebt,
|
||||
uint256 currentVariableDebt,
|
||||
uint256 principalStableDebt,
|
||||
uint256 scaledVariableDebt,
|
||||
uint256 stableBorrowRate,
|
||||
uint256 liquidityRate,
|
||||
uint40 stableRateLastUpdated,
|
||||
bool usageAsCollateralEnabled
|
||||
);
|
||||
}
|
||||
|
||||
interface AaveAddressProviderRegistryInterface {
|
||||
function getAddressesProvidersList()
|
||||
external
|
||||
view
|
||||
returns (address[] memory);
|
||||
}
|
111
contracts/avalanche/connectors/aave/v3-import/main.sol
Normal file
111
contracts/avalanche/connectors/aave/v3-import/main.sol
Normal file
|
@ -0,0 +1,111 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
pragma experimental ABIEncoderV2;
|
||||
/**
|
||||
* @title Aave v3 import connector .
|
||||
* @dev Import EOA's aave V3 position to DSA's aave v3 position
|
||||
*/
|
||||
import { TokenInterface, AccountInterface } from "../../../common/interfaces.sol";
|
||||
import { AaveInterface, ATokenInterface } from "./interface.sol";
|
||||
import "./helpers.sol";
|
||||
import "./events.sol";
|
||||
|
||||
contract AaveV3ImportResolver is AaveHelpers {
|
||||
function _importAave(address userAccount, ImportInputData memory inputData)
|
||||
internal
|
||||
returns (string memory _eventName, bytes memory _eventParam)
|
||||
{
|
||||
require(
|
||||
AccountInterface(address(this)).isAuth(userAccount),
|
||||
"user-account-not-auth"
|
||||
);
|
||||
|
||||
require(inputData.supplyTokens.length > 0, "0-length-not-allowed");
|
||||
|
||||
ImportData memory data;
|
||||
|
||||
AaveInterface aave = AaveInterface(aaveProvider.getPool());
|
||||
|
||||
data = getBorrowAmounts(userAccount, aave, inputData, data);
|
||||
data = getSupplyAmounts(userAccount, inputData, data);
|
||||
|
||||
// payback borrowed amount;
|
||||
_PaybackStable(
|
||||
data._borrowTokens.length,
|
||||
aave,
|
||||
data._borrowTokens,
|
||||
data.stableBorrowAmts,
|
||||
userAccount
|
||||
);
|
||||
_PaybackVariable(
|
||||
data._borrowTokens.length,
|
||||
aave,
|
||||
data._borrowTokens,
|
||||
data.variableBorrowAmts,
|
||||
userAccount
|
||||
);
|
||||
|
||||
// transfer atokens to this address;
|
||||
_TransferAtokens(
|
||||
data._supplyTokens.length,
|
||||
aave,
|
||||
data.aTokens,
|
||||
data.supplyAmts,
|
||||
data._supplyTokens,
|
||||
userAccount
|
||||
);
|
||||
|
||||
// borrow assets after migrating position
|
||||
if (data.convertStable) {
|
||||
_BorrowVariable(
|
||||
data._borrowTokens.length,
|
||||
aave,
|
||||
data._borrowTokens,
|
||||
data.totalBorrowAmtsWithFee
|
||||
);
|
||||
} else {
|
||||
_BorrowStable(
|
||||
data._borrowTokens.length,
|
||||
aave,
|
||||
data._borrowTokens,
|
||||
data.stableBorrowAmtsWithFee
|
||||
);
|
||||
_BorrowVariable(
|
||||
data._borrowTokens.length,
|
||||
aave,
|
||||
data._borrowTokens,
|
||||
data.variableBorrowAmtsWithFee
|
||||
);
|
||||
}
|
||||
|
||||
_eventName = "LogAaveV3Import(address,bool,address[],address[],uint256[],uint256[],uint256[],uint256[])";
|
||||
_eventParam = abi.encode(
|
||||
userAccount,
|
||||
inputData.convertStable,
|
||||
inputData.supplyTokens,
|
||||
inputData.borrowTokens,
|
||||
inputData.flashLoanFees,
|
||||
data.supplyAmts,
|
||||
data.stableBorrowAmts,
|
||||
data.variableBorrowAmts
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Import aave V3 position .
|
||||
* @notice Import EOA's aave V3 position to DSA's aave v3 position
|
||||
* @param userAccount The address of the EOA from which aave position will be imported
|
||||
* @param inputData The struct containing all the neccessary input data
|
||||
*/
|
||||
function importAave(address userAccount, ImportInputData memory inputData)
|
||||
external
|
||||
payable
|
||||
returns (string memory _eventName, bytes memory _eventParam)
|
||||
{
|
||||
(_eventName, _eventParam) = _importAave(userAccount, inputData);
|
||||
}
|
||||
}
|
||||
|
||||
contract ConnectV2AaveV3ImportAvalanche is AaveV3ImportResolver {
|
||||
string public constant name = "Aave-v3-import-v1";
|
||||
}
|
34
contracts/avalanche/connectors/aave/v3/events.sol
Normal file
34
contracts/avalanche/connectors/aave/v3/events.sol
Normal file
|
@ -0,0 +1,34 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
contract Events {
|
||||
event LogDeposit(
|
||||
address indexed token,
|
||||
uint256 tokenAmt,
|
||||
uint256 getId,
|
||||
uint256 setId
|
||||
);
|
||||
event LogWithdraw(
|
||||
address indexed token,
|
||||
uint256 tokenAmt,
|
||||
uint256 getId,
|
||||
uint256 setId
|
||||
);
|
||||
event LogBorrow(
|
||||
address indexed token,
|
||||
uint256 tokenAmt,
|
||||
uint256 indexed rateMode,
|
||||
uint256 getId,
|
||||
uint256 setId
|
||||
);
|
||||
event LogPayback(
|
||||
address indexed token,
|
||||
uint256 tokenAmt,
|
||||
uint256 indexed rateMode,
|
||||
uint256 getId,
|
||||
uint256 setId
|
||||
);
|
||||
event LogEnableCollateral(address[] tokens);
|
||||
event LogSwapRateMode(address indexed token, uint256 rateMode);
|
||||
event LogSetUserEMode(uint8 categoryId);
|
||||
}
|
67
contracts/avalanche/connectors/aave/v3/helpers.sol
Normal file
67
contracts/avalanche/connectors/aave/v3/helpers.sol
Normal file
|
@ -0,0 +1,67 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
import { DSMath } from "../../../common/math.sol";
|
||||
import { Basic } from "../../../common/basic.sol";
|
||||
import { AavePoolProviderInterface, AaveDataProviderInterface } from "./interface.sol";
|
||||
|
||||
abstract contract Helpers is DSMath, Basic {
|
||||
/**
|
||||
* @dev Aave Pool Provider
|
||||
*/
|
||||
AavePoolProviderInterface internal constant aaveProvider =
|
||||
AavePoolProviderInterface(0xa97684ead0e402dC232d5A977953DF7ECBaB3CDb); // Avalanche address - PoolAddressesProvider
|
||||
|
||||
/**
|
||||
* @dev Aave Pool Data Provider
|
||||
*/
|
||||
AaveDataProviderInterface internal constant aaveData =
|
||||
AaveDataProviderInterface(0x69FA688f1Dc47d4B5d8029D5a35FB7a548310654); // Avalanche address - PoolDataProvider
|
||||
|
||||
/**
|
||||
* @dev Aave Referral Code
|
||||
*/
|
||||
uint16 internal constant referralCode = 3228;
|
||||
|
||||
/**
|
||||
* @dev Checks if collateral is enabled for an asset
|
||||
* @param token token address of the asset.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
|
||||
*/
|
||||
|
||||
function getIsColl(address token) internal view returns (bool isCol) {
|
||||
(, , , , , , , , isCol) = aaveData.getUserReserveData(
|
||||
token,
|
||||
address(this)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Get total debt balance & fee for an asset
|
||||
* @param token token address of the debt.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
|
||||
* @param rateMode Borrow rate mode (Stable = 1, Variable = 2)
|
||||
*/
|
||||
function getPaybackBalance(address token, uint256 rateMode)
|
||||
internal
|
||||
view
|
||||
returns (uint256)
|
||||
{
|
||||
(, uint256 stableDebt, uint256 variableDebt, , , , , , ) = aaveData
|
||||
.getUserReserveData(token, address(this));
|
||||
return rateMode == 1 ? stableDebt : variableDebt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Get total collateral balance for an asset
|
||||
* @param token token address of the collateral.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
|
||||
*/
|
||||
function getCollateralBalance(address token)
|
||||
internal
|
||||
view
|
||||
returns (uint256 bal)
|
||||
{
|
||||
(bal, , , , , , , , ) = aaveData.getUserReserveData(
|
||||
token,
|
||||
address(this)
|
||||
);
|
||||
}
|
||||
}
|
92
contracts/avalanche/connectors/aave/v3/interface.sol
Normal file
92
contracts/avalanche/connectors/aave/v3/interface.sol
Normal file
|
@ -0,0 +1,92 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
interface AaveInterface {
|
||||
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 swapBorrowRateMode(address asset, uint256 interestRateMode)
|
||||
external;
|
||||
|
||||
function setUserEMode(uint8 categoryId) external;
|
||||
}
|
||||
|
||||
interface AavePoolProviderInterface {
|
||||
function getPool() external view returns (address);
|
||||
}
|
||||
|
||||
interface AaveDataProviderInterface {
|
||||
function getReserveTokensAddresses(address _asset)
|
||||
external
|
||||
view
|
||||
returns (
|
||||
address aTokenAddress,
|
||||
address stableDebtTokenAddress,
|
||||
address variableDebtTokenAddress
|
||||
);
|
||||
|
||||
function getUserReserveData(address _asset, address _user)
|
||||
external
|
||||
view
|
||||
returns (
|
||||
uint256 currentATokenBalance,
|
||||
uint256 currentStableDebt,
|
||||
uint256 currentVariableDebt,
|
||||
uint256 principalStableDebt,
|
||||
uint256 scaledVariableDebt,
|
||||
uint256 stableBorrowRate,
|
||||
uint256 liquidityRate,
|
||||
uint40 stableRateLastUpdated,
|
||||
bool usageAsCollateralEnabled
|
||||
);
|
||||
|
||||
function getReserveEModeCategory(address asset)
|
||||
external
|
||||
view
|
||||
returns (uint256);
|
||||
}
|
||||
|
||||
interface AaveAddressProviderRegistryInterface {
|
||||
function getAddressesProvidersList()
|
||||
external
|
||||
view
|
||||
returns (address[] memory);
|
||||
}
|
||||
|
||||
interface ATokenInterface {
|
||||
function balanceOf(address _user) external view returns (uint256);
|
||||
}
|
297
contracts/avalanche/connectors/aave/v3/main.sol
Normal file
297
contracts/avalanche/connectors/aave/v3/main.sol
Normal file
|
@ -0,0 +1,297 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
/**
|
||||
* @title Aave v3.
|
||||
* @dev Lending & Borrowing.
|
||||
*/
|
||||
|
||||
import { TokenInterface } from "../../../common/interfaces.sol";
|
||||
import { Stores } from "../../../common/stores.sol";
|
||||
import { Helpers } from "./helpers.sol";
|
||||
import { Events } from "./events.sol";
|
||||
import { AaveInterface } from "./interface.sol";
|
||||
|
||||
abstract contract AaveResolver is Events, Helpers {
|
||||
/**
|
||||
* @dev Deposit avax/ERC20_Token.
|
||||
* @notice Deposit a token to Aave v3 for lending / collaterization.
|
||||
* @param token The address of the token to deposit.(For avax: 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.getPool());
|
||||
|
||||
bool isAVAX = token == avaxAddr;
|
||||
address _token = isAVAX ? wavaxAddr : token;
|
||||
|
||||
TokenInterface tokenContract = TokenInterface(_token);
|
||||
|
||||
if (isAVAX) {
|
||||
_amt = _amt == uint256(-1) ? address(this).balance : _amt;
|
||||
convertAvaxToWavax(isAVAX, tokenContract, _amt);
|
||||
} else {
|
||||
_amt = _amt == uint256(-1)
|
||||
? tokenContract.balanceOf(address(this))
|
||||
: _amt;
|
||||
}
|
||||
|
||||
approve(tokenContract, address(aave), _amt);
|
||||
|
||||
aave.supply(_token, _amt, address(this), referralCode);
|
||||
|
||||
if (!getIsColl(_token)) {
|
||||
aave.setUserUseReserveAsCollateral(_token, true);
|
||||
}
|
||||
|
||||
setUint(setId, _amt);
|
||||
|
||||
_eventName = "LogDeposit(address,uint256,uint256,uint256)";
|
||||
_eventParam = abi.encode(token, _amt, getId, setId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Withdraw avax/ERC20_Token.
|
||||
* @notice Withdraw deposited token from Aave v3
|
||||
* @param token The address of the token to withdraw.(For avax: 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.getPool());
|
||||
bool isAVAX = token == avaxAddr;
|
||||
address _token = isAVAX ? wavaxAddr : token;
|
||||
|
||||
TokenInterface tokenContract = TokenInterface(_token);
|
||||
|
||||
uint256 initialBal = tokenContract.balanceOf(address(this));
|
||||
aave.withdraw(_token, _amt, address(this));
|
||||
uint256 finalBal = tokenContract.balanceOf(address(this));
|
||||
|
||||
_amt = sub(finalBal, initialBal);
|
||||
|
||||
convertWavaxToAvax(isAVAX, tokenContract, _amt);
|
||||
|
||||
setUint(setId, _amt);
|
||||
|
||||
_eventName = "LogWithdraw(address,uint256,uint256,uint256)";
|
||||
_eventParam = abi.encode(token, _amt, getId, setId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Borrow avax/ERC20_Token.
|
||||
* @notice Borrow a token using Aave v3
|
||||
* @param token The address of the token to borrow.(For avax: 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.getPool());
|
||||
|
||||
bool isAVAX = token == avaxAddr;
|
||||
address _token = isAVAX ? wavaxAddr : token;
|
||||
|
||||
aave.borrow(_token, _amt, rateMode, referralCode, address(this));
|
||||
convertWavaxToAvax(isAVAX, TokenInterface(_token), _amt);
|
||||
|
||||
setUint(setId, _amt);
|
||||
|
||||
_eventName = "LogBorrow(address,uint256,uint256,uint256,uint256)";
|
||||
_eventParam = abi.encode(token, _amt, rateMode, getId, setId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Payback borrowed avax/ERC20_Token.
|
||||
* @notice Payback debt owed.
|
||||
* @param token The address of the token to payback.(For avax: 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.getPool());
|
||||
|
||||
bool isAVAX = token == avaxAddr;
|
||||
address _token = isAVAX ? wavaxAddr : token;
|
||||
|
||||
TokenInterface tokenContract = TokenInterface(_token);
|
||||
|
||||
_amt = _amt == uint256(-1) ? getPaybackBalance(_token, rateMode) : _amt;
|
||||
|
||||
if (isAVAX) convertAvaxToWavax(isAVAX, tokenContract, _amt);
|
||||
|
||||
approve(tokenContract, address(aave), _amt);
|
||||
|
||||
aave.repay(_token, _amt, rateMode, address(this));
|
||||
|
||||
setUint(setId, _amt);
|
||||
|
||||
_eventName = "LogPayback(address,uint256,uint256,uint256,uint256)";
|
||||
_eventParam = abi.encode(token, _amt, rateMode, getId, setId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Payback borrowed avax/ERC20_Token using aTokens.
|
||||
* @notice Repays a borrowed `amount` on a specific reserve using the reserve aTokens, burning the equivalent debt tokens.
|
||||
* @param token The address of the token to payback.(For avax: 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 paybackWithATokens(
|
||||
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.getPool());
|
||||
|
||||
bool isAVAX = token == avaxAddr;
|
||||
address _token = isAVAX ? wavaxAddr : token;
|
||||
|
||||
TokenInterface tokenContract = TokenInterface(_token);
|
||||
|
||||
_amt = _amt == uint256(-1) ? getPaybackBalance(_token, rateMode) : _amt;
|
||||
|
||||
if (isAVAX) convertAvaxToWavax(isAVAX, tokenContract, _amt);
|
||||
|
||||
approve(tokenContract, address(aave), _amt);
|
||||
|
||||
aave.repayWithATokens(_token, _amt, rateMode);
|
||||
|
||||
setUint(setId, _amt);
|
||||
|
||||
_eventName = "LogPayback(address,uint256,uint256,uint256,uint256)";
|
||||
_eventParam = abi.encode(token, _amt, rateMode, 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)
|
||||
{
|
||||
uint256 _length = tokens.length;
|
||||
require(_length > 0, "0-tokens-not-allowed");
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
_eventName = "LogEnableCollateral(address[])";
|
||||
_eventParam = abi.encode(tokens);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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)
|
||||
*/
|
||||
function swapBorrowRateMode(address token, uint256 rateMode)
|
||||
external
|
||||
payable
|
||||
returns (string memory _eventName, bytes memory _eventParam)
|
||||
{
|
||||
AaveInterface aave = AaveInterface(aaveProvider.getPool());
|
||||
|
||||
uint256 currentRateMode = rateMode == 1 ? 2 : 1;
|
||||
|
||||
if (getPaybackBalance(token, currentRateMode) > 0) {
|
||||
aave.swapBorrowRateMode(token, rateMode);
|
||||
}
|
||||
|
||||
_eventName = "LogSwapRateMode(address,uint256)";
|
||||
_eventParam = abi.encode(token, rateMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Set user e-mode
|
||||
* @notice Updates the user's e-mode category
|
||||
* @param categoryId The category Id of the e-mode user want to set
|
||||
*/
|
||||
function setUserEMode(uint8 categoryId)
|
||||
external
|
||||
returns (string memory _eventName, bytes memory _eventParam)
|
||||
{
|
||||
AaveInterface aave = AaveInterface(aaveProvider.getPool());
|
||||
|
||||
aave.setUserEMode(categoryId);
|
||||
|
||||
_eventName = "LogSetUserEMode(uint8)";
|
||||
_eventParam = abi.encode(categoryId);
|
||||
}
|
||||
}
|
||||
|
||||
contract ConnectV2AaveV3Avalanche is AaveResolver {
|
||||
string public constant name = "AaveV3-v1.0";
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
contract Events {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
contract Events {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
contract Events {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
interface ComptrollerInterface {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
contract Events {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
import { DSMath } from "../../../common/math.sol";
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user