mirror of
https://github.com/Instadapp/aave-protocol-v2.git
synced 2024-07-29 21:47:30 +00:00
updated rebalance conditions,tests
This commit is contained in:
parent
a960e43dcf
commit
07db321b4d
|
@ -10,9 +10,13 @@ interface IReserveInterestRateStrategy {
|
|||
/**
|
||||
* @dev returns the base variable borrow rate, in rays
|
||||
*/
|
||||
|
||||
function baseVariableBorrowRate() external view returns (uint256);
|
||||
|
||||
/**
|
||||
* @dev returns the maximum variable borrow rate
|
||||
*/
|
||||
function getMaxVariableBorrowRate() external view returns (uint256);
|
||||
|
||||
/**
|
||||
* @dev calculates the liquidity, stable, and variable rates depending on the current utilization rate
|
||||
* and the base parameters
|
||||
|
|
|
@ -89,6 +89,10 @@ contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy {
|
|||
return _baseVariableBorrowRate;
|
||||
}
|
||||
|
||||
function getMaxVariableBorrowRate() external override view returns (uint256) {
|
||||
return _baseVariableBorrowRate.add(_variableRateSlope1).add(_variableRateSlope2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev calculates the interest rates depending on the available liquidity and the total borrowed.
|
||||
* @param reserve the address of the reserve
|
||||
|
|
|
@ -12,6 +12,7 @@ import {IAToken} from '../tokenization/interfaces/IAToken.sol';
|
|||
import {Helpers} from '../libraries/helpers/Helpers.sol';
|
||||
import {Errors} from '../libraries/helpers/Errors.sol';
|
||||
import {WadRayMath} from '../libraries/math/WadRayMath.sol';
|
||||
import {PercentageMath} from '../libraries/math/PercentageMath.sol';
|
||||
import {ReserveLogic} from '../libraries/logic/ReserveLogic.sol';
|
||||
import {GenericLogic} from '../libraries/logic/GenericLogic.sol';
|
||||
import {ValidationLogic} from '../libraries/logic/ValidationLogic.sol';
|
||||
|
@ -26,6 +27,7 @@ import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol';
|
|||
import {SafeERC20} from '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';
|
||||
import {ILendingPool} from '../interfaces/ILendingPool.sol';
|
||||
import {LendingPoolStorage} from './LendingPoolStorage.sol';
|
||||
import {IReserveInterestRateStrategy} from '../interfaces/IReserveInterestRateStrategy.sol';
|
||||
|
||||
/**
|
||||
* @title LendingPool contract
|
||||
|
@ -36,10 +38,12 @@ import {LendingPoolStorage} from './LendingPoolStorage.sol';
|
|||
contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage {
|
||||
using SafeMath for uint256;
|
||||
using WadRayMath for uint256;
|
||||
using PercentageMath for uint256;
|
||||
using SafeERC20 for IERC20;
|
||||
|
||||
//main configuration parameters
|
||||
uint256 public constant REBALANCE_DOWN_RATE_DELTA = (1e27) / 5;
|
||||
uint256 public constant REBALANCE_UP_LIQUIDITY_RATE_THRESHOLD = 4000;
|
||||
uint256 public constant REBALANCE_UP_USAGE_RATIO_THRESHOLD = 0.95 * 1e27; //usage ratio of 95%
|
||||
uint256 public constant MAX_STABLE_RATE_BORROW_SIZE_PERCENT = 25;
|
||||
uint256 public constant FLASHLOAN_PREMIUM_TOTAL = 9;
|
||||
|
||||
|
@ -354,26 +358,39 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
|||
whenNotPaused();
|
||||
ReserveLogic.ReserveData storage reserve = _reserves[asset];
|
||||
|
||||
IStableDebtToken stableDebtToken = IStableDebtToken(reserve.stableDebtTokenAddress);
|
||||
IERC20 stableDebtToken = IERC20(reserve.stableDebtTokenAddress);
|
||||
IERC20 variableDebtToken = IERC20(reserve.variableDebtTokenAddress);
|
||||
|
||||
uint256 stableBorrowBalance = IERC20(address(stableDebtToken)).balanceOf(user);
|
||||
uint256 stableBorrowBalance = IERC20(stableDebtToken).balanceOf(user);
|
||||
|
||||
// user must be borrowing on asset at a stable rate
|
||||
require(stableBorrowBalance > 0, Errors.NOT_ENOUGH_STABLE_BORROW_BALANCE);
|
||||
|
||||
uint256 rebalanceDownRateThreshold = WadRayMath.ray().add(REBALANCE_DOWN_RATE_DELTA).rayMul(
|
||||
reserve.currentStableBorrowRate
|
||||
);
|
||||
|
||||
//1. user stable borrow rate is below the current liquidity rate. The loan needs to be rebalanced,
|
||||
//as this situation can be abused (user putting back the borrowed liquidity in the same reserve to earn on it)
|
||||
//2. user stable rate is above the market avg borrow rate of a certain delta, and utilization rate is low.
|
||||
//In this case, the user is paying an interest that is too high, and needs to be rescaled down.
|
||||
|
||||
uint256 userStableRate = stableDebtToken.getUserStableRate(user);
|
||||
//if the utilization rate is below 95%, no rebalances are needed
|
||||
uint256 totalBorrows = stableDebtToken.totalSupply().add(variableDebtToken.totalSupply());
|
||||
uint256 availableLiquidity = IERC20(reserve.aTokenAddress).totalSupply();
|
||||
uint256 utilizationRate = totalBorrows == 0
|
||||
? 0
|
||||
: totalBorrows.rayDiv(availableLiquidity.add(totalBorrows));
|
||||
|
||||
require(
|
||||
userStableRate < reserve.currentLiquidityRate || userStableRate > rebalanceDownRateThreshold,
|
||||
utilizationRate >= REBALANCE_UP_USAGE_RATIO_THRESHOLD,
|
||||
Errors.INTEREST_RATE_REBALANCE_CONDITIONS_NOT_MET
|
||||
);
|
||||
|
||||
//if the liquidity rate is below REBALANCE_UP_THRESHOLD of the max variable APR at 95% usage,
|
||||
//then we allow rebalancing of the stable rate positions.
|
||||
|
||||
uint256 currentLiquidityRate = reserve.currentLiquidityRate;
|
||||
uint256 maxVariableBorrowRate = IReserveInterestRateStrategy(
|
||||
reserve
|
||||
.interestRateStrategyAddress
|
||||
)
|
||||
.getMaxVariableBorrowRate();
|
||||
|
||||
require(
|
||||
currentLiquidityRate <=
|
||||
maxVariableBorrowRate.percentMul(REBALANCE_UP_LIQUIDITY_RATE_THRESHOLD),
|
||||
Errors.INTEREST_RATE_REBALANCE_CONDITIONS_NOT_MET
|
||||
);
|
||||
|
||||
|
@ -381,8 +398,8 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
|||
|
||||
reserve.updateCumulativeIndexesAndTimestamp();
|
||||
|
||||
stableDebtToken.burn(user, stableBorrowBalance);
|
||||
stableDebtToken.mint(user, stableBorrowBalance, reserve.currentStableBorrowRate);
|
||||
IStableDebtToken(address(stableDebtToken)).burn(user, stableBorrowBalance);
|
||||
IStableDebtToken(address(stableDebtToken)).mint(user, stableBorrowBalance, reserve.currentStableBorrowRate);
|
||||
|
||||
reserve.updateInterestRates(asset, reserve.aTokenAddress, 0, 0);
|
||||
|
||||
|
@ -507,7 +524,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
|||
_flashLiquidationLocked = false;
|
||||
}
|
||||
|
||||
struct FlashLoanLocalVars {
|
||||
struct FlashLoanLocalVars {
|
||||
uint256 premium;
|
||||
uint256 amountPlusPremium;
|
||||
IFlashLoanReceiver receiver;
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"description": "User 0 deposits 1000 DAI, user 1 deposits 1 ETH, borrows 100 DAI at a variable rate, user 0 rebalances user 1 (revert expected)",
|
||||
"description": "User 0 deposits 1000 DAI, user 1 deposits 5 ETH, borrows 600 DAI at a variable rate, user 0 rebalances user 1 (revert expected)",
|
||||
"actions": [
|
||||
{
|
||||
"name": "mint",
|
||||
|
@ -51,7 +51,7 @@
|
|||
"name": "mint",
|
||||
"args": {
|
||||
"reserve": "WETH",
|
||||
"amount": "1",
|
||||
"amount": "5",
|
||||
"user": "1"
|
||||
},
|
||||
"expected": "success"
|
||||
|
@ -69,7 +69,7 @@
|
|||
"args": {
|
||||
"reserve": "WETH",
|
||||
|
||||
"amount": "1",
|
||||
"amount": "5",
|
||||
"user": "1"
|
||||
},
|
||||
"expected": "success"
|
||||
|
@ -78,7 +78,7 @@
|
|||
"name": "borrow",
|
||||
"args": {
|
||||
"reserve": "DAI",
|
||||
"amount": "100",
|
||||
"amount": "600",
|
||||
"borrowRateMode": "variable",
|
||||
"user": "1",
|
||||
"timeTravel": "365"
|
||||
|
@ -122,7 +122,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"description": "User 2 deposits ETH and borrows the remaining DAI, causing the stable rates to rise (liquidity rate < user 1 borrow rate). User 0 tries to rebalance user 1 (revert expected)",
|
||||
"description": "User 2 deposits ETH and borrows the remaining DAI, causing the stable rates to rise (usage ratio = 94%). User 0 tries to rebalance user 1 (revert expected)",
|
||||
"actions": [
|
||||
{
|
||||
"name": "mint",
|
||||
|
@ -155,7 +155,7 @@
|
|||
"name": "borrow",
|
||||
"args": {
|
||||
"reserve": "DAI",
|
||||
"amount": "100",
|
||||
"amount": "340",
|
||||
"borrowRateMode": "variable",
|
||||
"user": "2"
|
||||
},
|
||||
|
@ -174,40 +174,13 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"description": "User 2 borrows more DAI, causing the liquidity rate to rise above user 1 stable borrow rate User 0 rebalances user 1",
|
||||
"description": "User 2 borrows the remaining DAI (usage ratio = 100%). User 0 rebalances user 1",
|
||||
"actions": [
|
||||
{
|
||||
"name": "mint",
|
||||
"args": {
|
||||
"reserve": "WETH",
|
||||
"amount": "3",
|
||||
"user": "2"
|
||||
},
|
||||
"expected": "success"
|
||||
},
|
||||
{
|
||||
"name": "approve",
|
||||
"args": {
|
||||
"reserve": "WETH",
|
||||
"user": "2"
|
||||
},
|
||||
"expected": "success"
|
||||
},
|
||||
{
|
||||
"name": "deposit",
|
||||
"args": {
|
||||
"reserve": "WETH",
|
||||
|
||||
"amount": "3",
|
||||
"user": "2"
|
||||
},
|
||||
"expected": "success"
|
||||
},
|
||||
{
|
||||
"name": "borrow",
|
||||
"args": {
|
||||
"reserve": "DAI",
|
||||
"amount": "700",
|
||||
"amount": "60",
|
||||
"borrowRateMode": "variable",
|
||||
"user": "2"
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue
Block a user