From 8f914720c63812ff8eda7ddfd26a1aeb0f1dedd2 Mon Sep 17 00:00:00 2001 From: pedrovalido Date: Sun, 29 Jan 2023 08:50:09 +0100 Subject: [PATCH] feat(protocol): aavev3 on mainnet and tests --- .../protocol/src/providers/mainnet/AaveV3.sol | 111 ++++++++++++++++++ .../test/forking/mainnet/AaveV3.t.sol | 73 ++++++++++++ 2 files changed, 184 insertions(+) create mode 100644 packages/protocol/src/providers/mainnet/AaveV3.sol create mode 100644 packages/protocol/test/forking/mainnet/AaveV3.t.sol diff --git a/packages/protocol/src/providers/mainnet/AaveV3.sol b/packages/protocol/src/providers/mainnet/AaveV3.sol new file mode 100644 index 000000000..311f3de79 --- /dev/null +++ b/packages/protocol/src/providers/mainnet/AaveV3.sol @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity 0.8.15; + +import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; +import {IVault} from "../../interfaces/IVault.sol"; +import {ILendingProvider} from "../../interfaces/ILendingProvider.sol"; +import {IV3Pool} from "../../interfaces/aaveV3/IV3Pool.sol"; + +/** + * @title AaveV3 + * @author Fujidao Labs + * @notice This contract allows interaction with AaveV3. + */ +contract AaveV3 is ILendingProvider { + function _getPool() internal pure returns (IV3Pool) { + return IV3Pool(0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2); + } + + /// inheritdoc ILendingProvider + function providerName() public pure override returns (string memory) { + return "Aave_V3"; + } + + /// inheritdoc ILendingProvider + function approvedOperator( + address, + address, + address + ) + external + pure + override + returns (address operator) + { + operator = address(_getPool()); + } + + /// inheritdoc ILendingProvider + function deposit(uint256 amount, IVault vault) external override returns (bool success) { + IV3Pool aave = _getPool(); + address asset = vault.asset(); + aave.supply(asset, amount, address(vault), 0); + aave.setUserUseReserveAsCollateral(asset, true); + success = true; + } + + /// inheritdoc ILendingProvider + function borrow(uint256 amount, IVault vault) external override returns (bool success) { + IV3Pool aave = _getPool(); + aave.borrow(vault.debtAsset(), amount, 2, 0, address(vault)); + success = true; + } + + /// inheritdoc ILendingProvider + function withdraw(uint256 amount, IVault vault) external override returns (bool success) { + IV3Pool aave = _getPool(); + aave.withdraw(vault.asset(), amount, address(vault)); + success = true; + } + + /// inheritdoc ILendingProvider + function payback(uint256 amount, IVault vault) external override returns (bool success) { + IV3Pool aave = _getPool(); + aave.repay(vault.debtAsset(), amount, 2, address(vault)); + success = true; + } + + /// inheritdoc ILendingProvider + function getDepositRateFor(IVault vault) external view override returns (uint256 rate) { + IV3Pool aaveData = _getPool(); + IV3Pool.ReserveData memory rdata = aaveData.getReserveData(vault.asset()); + rate = rdata.currentLiquidityRate; + } + + /// inheritdoc ILendingProvider + function getBorrowRateFor(IVault vault) external view override returns (uint256 rate) { + IV3Pool aaveData = _getPool(); + IV3Pool.ReserveData memory rdata = aaveData.getReserveData(vault.debtAsset()); + rate = rdata.currentVariableBorrowRate; + } + + /// inheritdoc ILendingProvider + function getDepositBalance( + address user, + IVault vault + ) + external + view + override + returns (uint256 balance) + { + IV3Pool aaveData = _getPool(); + IV3Pool.ReserveData memory rdata = aaveData.getReserveData(vault.asset()); + balance = IERC20(rdata.aTokenAddress).balanceOf(user); + } + + /// inheritdoc ILendingProvider + function getBorrowBalance( + address user, + IVault vault + ) + external + view + override + returns (uint256 balance) + { + IV3Pool aaveData = _getPool(); + IV3Pool.ReserveData memory rdata = aaveData.getReserveData(vault.debtAsset()); + balance = IERC20(rdata.variableDebtTokenAddress).balanceOf(user); + } +} diff --git a/packages/protocol/test/forking/mainnet/AaveV3.t.sol b/packages/protocol/test/forking/mainnet/AaveV3.t.sol new file mode 100644 index 000000000..a1e05f569 --- /dev/null +++ b/packages/protocol/test/forking/mainnet/AaveV3.t.sol @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.15; + +import "forge-std/console.sol"; +import {Routines} from "../../utils/Routines.sol"; +import {ForkingSetup} from "../ForkingSetup.sol"; +import {AaveV3} from "../../../src/providers/mainnet/AaveV3.sol"; +import {ILendingProvider} from "../../../src/interfaces/ILendingProvider.sol"; +import {BorrowingVault} from "../../../src/vaults/borrowing/BorrowingVault.sol"; +import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; + +contract AaveV3ForkingTest is Routines, ForkingSetup { + ILendingProvider public aaveV3; + + uint256 public constant DEPOSIT_AMOUNT = 0.5 ether; + uint256 public constant BORROW_AMOUNT = 200 * 1e6; + + function setUp() public { + setUpFork(MAINNET_DOMAIN); + + aaveV3 = new AaveV3(); + ILendingProvider[] memory providers = new ILendingProvider[](1); + providers[0] = aaveV3; + + deploy(providers); + } + + function test_depositAndBorrow() public { + do_deposit(DEPOSIT_AMOUNT, vault, ALICE); + do_borrow(BORROW_AMOUNT, vault, ALICE); + } + + function test_paybackAndWithdraw() public { + deal(address(vault.asset()), ALICE, DEPOSIT_AMOUNT); + + do_depositAndBorrow(DEPOSIT_AMOUNT, BORROW_AMOUNT, vault, ALICE); + + vm.warp(block.timestamp + 13 seconds); + vm.roll(block.number + 1); + + uint256 aliceDebt = vault.balanceOfDebt(ALICE); + do_payback(aliceDebt, vault, ALICE); + + assertEq(vault.balanceOfDebt(ALICE), 0); + + uint256 maxAmount = vault.maxWithdraw(ALICE); + do_withdraw(maxAmount, vault, ALICE); + + assertGe(IERC20(vault.asset()).balanceOf(ALICE), DEPOSIT_AMOUNT); + } + + function test_getBalances() public { + do_depositAndBorrow(DEPOSIT_AMOUNT, BORROW_AMOUNT, vault, ALICE); + + uint256 depositBalance = vault.totalAssets(); + uint256 borrowBalance = vault.totalDebt(); + assertGe(depositBalance, DEPOSIT_AMOUNT); + assertGe(borrowBalance, BORROW_AMOUNT); + } + + function test_getInterestRates() public { + uint256 depositRate = aaveV3.getDepositRateFor(vault); + assertGt(depositRate, 0); // Should be greater than zero. + + uint256 borrowRate = aaveV3.getBorrowRateFor(vault); + assertGt(borrowRate, 0); // Should be greater than zero. + } + + function test_twoDeposits() public { + do_deposit(DEPOSIT_AMOUNT, vault, ALICE); + do_deposit(DEPOSIT_AMOUNT, vault, BOB); + } +}