Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: attempting to redeem while AAVE fully borrowed #219

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions src/interfaces/aave/IPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,22 @@ interface IPool {
*
*/
function withdraw(address asset, uint256 amount, address to) external returns (uint256);

/**
* @notice Allows users to borrow a specific `amount` of the reserve underlying asset, provided that the borrower
* already supplied enough collateral, or he was given enough allowance by a credit delegator on the
* corresponding debt token (StableDebtToken or VariableDebtToken)
* - E.g. User borrows 100 USDC passing as `onBehalfOf` his own address, receiving the 100 USDC in his wallet
* and 100 stable/variable debt tokens, depending on the `interestRateMode`
* @param asset The address of the underlying asset to borrow
* @param amount The amount to be borrowed
* @param interestRateMode The interest rate mode at which the user wants to borrow: 1 for Stable, 2 for Variable
* @param referralCode The code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
* @param onBehalfOf The address of the user who will receive the debt. Should be the address of the borrower itself
* calling the function if he wants to borrow against his own collateral, or the address of the credit delegator
* if he has been given credit delegation allowance
*/
function borrow(address asset, uint256 amount, uint256 interestRateMode, uint16 referralCode, address onBehalfOf)
external;
}
106 changes: 106 additions & 0 deletions src/interfaces/aave/IUiPoolDataProviderV3.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.10;

import { IPoolAddressesProvider } from "./IPoolAddressesProvider.sol";

interface IUiPoolDataProviderV3 {
struct InterestRates {
uint256 variableRateSlope1;
uint256 variableRateSlope2;
uint256 stableRateSlope1;
uint256 stableRateSlope2;
uint256 baseStableBorrowRate;
uint256 baseVariableBorrowRate;
uint256 optimalUsageRatio;
}

struct AggregatedReserveData {
address underlyingAsset;
string name;
string symbol;
uint256 decimals;
uint256 baseLTVasCollateral;
uint256 reserveLiquidationThreshold;
uint256 reserveLiquidationBonus;
uint256 reserveFactor;
bool usageAsCollateralEnabled;
bool borrowingEnabled;
bool stableBorrowRateEnabled;
bool isActive;
bool isFrozen;
// base data
uint128 liquidityIndex;
uint128 variableBorrowIndex;
uint128 liquidityRate;
uint128 variableBorrowRate;
uint128 stableBorrowRate;
uint40 lastUpdateTimestamp;
address aTokenAddress;
address stableDebtTokenAddress;
address variableDebtTokenAddress;
address interestRateStrategyAddress;
//
uint256 availableLiquidity;
uint256 totalPrincipalStableDebt;
uint256 averageStableRate;
uint256 stableDebtLastUpdateTimestamp;
uint256 totalScaledVariableDebt;
uint256 priceInMarketReferenceCurrency;
address priceOracle;
uint256 variableRateSlope1;
uint256 variableRateSlope2;
uint256 stableRateSlope1;
uint256 stableRateSlope2;
uint256 baseStableBorrowRate;
uint256 baseVariableBorrowRate;
uint256 optimalUsageRatio;
// v3 only
bool isPaused;
bool isSiloedBorrowing;
uint128 accruedToTreasury;
uint128 unbacked;
uint128 isolationModeTotalDebt;
//
uint256 debtCeiling;
uint256 debtCeilingDecimals;
uint8 eModeCategoryId;
uint256 borrowCap;
uint256 supplyCap;
// eMode
uint16 eModeLtv;
uint16 eModeLiquidationThreshold;
uint16 eModeLiquidationBonus;
address eModePriceSource;
string eModeLabel;
bool borrowableInIsolation;
}

struct UserReserveData {
address underlyingAsset;
uint256 scaledATokenBalance;
bool usageAsCollateralEnabledOnUser;
uint256 stableBorrowRate;
uint256 scaledVariableDebt;
uint256 principalStableDebt;
uint256 stableBorrowLastUpdateTimestamp;
}

struct BaseCurrencyInfo {
uint256 marketReferenceCurrencyUnit;
int256 marketReferenceCurrencyPriceInUsd;
int256 networkBaseTokenPriceInUsd;
uint8 networkBaseTokenPriceDecimals;
}

function getReservesList(IPoolAddressesProvider provider) external view returns (address[] memory);

function getReservesData(IPoolAddressesProvider provider)
external
view
returns (AggregatedReserveData[] memory, BaseCurrencyInfo memory);

function getUserReservesData(IPoolAddressesProvider provider, address user)
external
view
returns (UserReserveData[] memory, uint8);
}
59 changes: 57 additions & 2 deletions test/integration/Aave.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@ import { FactoryStoreLib } from "src/libraries/FactoryStore.sol";
import { MathUtils } from "src/libraries/MathUtils.sol";
import { AaveManager, IAssetManager } from "src/asset-management/AaveManager.sol";
import { GenericFactory, IERC20 } from "src/GenericFactory.sol";
import { IUiPoolDataProviderV3 } from "../../src/interfaces/aave/IUiPoolDataProviderV3.sol";

struct Network {
string rpcUrl;
address USDC;
address WETH;
}

struct Fork {
Expand Down Expand Up @@ -50,6 +52,7 @@ contract AaveIntegrationTest is BaseTest {
mapping(string => Fork) private _forks;
// network specific variables
IERC20 private USDC;
IERC20 private WETH;
address private _aaveAdmin;
IPoolAddressesProvider private _poolAddressesProvider;
IAaveProtocolDataProvider private _dataProvider;
Expand Down Expand Up @@ -92,6 +95,7 @@ contract AaveIntegrationTest is BaseTest {

_manager = new AaveManager(IPoolAddressesProvider(AAVE_POOL_ADDRESS_PROVIDER));
USDC = IERC20(aNetwork.USDC);
WETH = IERC20(aNetwork.WETH);
_poolAddressesProvider = IPoolAddressesProvider(AAVE_POOL_ADDRESS_PROVIDER);
_aaveAdmin = _poolAddressesProvider.getACLAdmin();
_dataProvider = IAaveProtocolDataProvider(_poolAddressesProvider.getPoolDataProvider());
Expand All @@ -118,8 +122,20 @@ contract AaveIntegrationTest is BaseTest {
}

function setUp() external {
_networks.push(Network(getChain("avalanche").rpcUrl, 0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E));
_networks.push(Network(getChain("polygon").rpcUrl, 0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174));
_networks.push(
Network(
getChain("avalanche").rpcUrl,
0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E,
0x49D5c2BdFfac6CE2BFdB6640F4F80f226bc10bAB
)
);
_networks.push(
Network(
getChain("polygon").rpcUrl,
0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174,
0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619
)
);

vm.makePersistent(address(_tokenA));
vm.makePersistent(address(_tokenB));
Expand Down Expand Up @@ -1124,4 +1140,43 @@ contract AaveIntegrationTest is BaseTest {
assertEq(_manager.shares(lOtherPair, USDC), 0);
assertEq(_manager.shares(lThirdPair, USDC), 0);
}

function testAaveReserves_AllLentOut() external allNetworks allPairs {
// assume
uint256 lAmtWETHToDeal = 4000e18;

// arrange
_increaseManagementOneToken(10e6);

deal(address(WETH), _alice, lAmtWETHToDeal);
IPool lPool = _manager.pool();
vm.startPrank(_alice);
WETH.approve(address(lPool), type(uint256).max);
lPool.supply(address(WETH), lAmtWETHToDeal, _alice, 0);
vm.stopPrank();

// sanity
(address lRawAaveTokenWETH,,) = _dataProvider.getReserveTokensAddresses(address(WETH));
assertEq(WETH.balanceOf(_alice), 0);
assertEq(IERC20(lRawAaveTokenWETH).balanceOf(_alice), lAmtWETHToDeal);

// Alice takes out all the USDC as loans in AAVE
(address lRawAaveTokenUSDC,,address lVarDebtTokenUSDC) = _dataProvider.getReserveTokensAddresses(address(USDC));
uint256 lAvailableLiqUSDC = USDC.balanceOf(lRawAaveTokenUSDC);
vm.prank(_alice);
lPool.borrow(address(USDC), lAvailableLiqUSDC, 2, 0, _alice);

// ensure that all USDC in the pool has been borrowed
assertEq(USDC.balanceOf(lRawAaveTokenUSDC), 0);
assertGt(IERC20(lVarDebtTokenUSDC).balanceOf(_alice), 0);

// act & assert - our pair tries to redeem
IERC20 lToken0 = _pair.token0();
vm.expectRevert();
_manager.adjustManagement(
_pair,
lToken0 == USDC ? int256(-10e6) : int(0),
lToken0 == USDC ? int(0) : int256(-10e6)
);
}
}
Loading