Skip to content

Commit 4cc61ba

Browse files
authored
fix: informal issues
1 parent 61bb283 commit 4cc61ba

9 files changed

Lines changed: 20 additions & 19 deletions

File tree

docs/3.5/Aave-v3.5-features.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ When calculating a user's health factor, the protocol must convert their asset a
5454
- **Collateral (aToken) Value:** The value of a user's supplied assets in the base currency is always rounded **down**. This ensures the protocol never overestimates the value of a user's collateral.
5555
- **Debt (vToken) Value:** The value of a user's borrowed assets in the base currency is always rounded **up**. This ensures the protocol never underestimates a user's debt. A key consequence of this is that any non-zero debt, no matter how small, will be valued as at least 1 wei in the base currency. This prevents situations where tiny "dust" debts could round down to zero after conversion, making them invisible to Health Factor calculations.
5656

57-
This approach of always rounding in favor of the protocol during health factor calculations is a critical security measure that protects it from potential insolvencies arising from rounding discrepancies.
57+
This approach of always rounding in favor of the protocol during health factor calculations is a critical security measure that protects it from potential insolvencies arising from rounding discrepancies. As a result of this change, the health factor of a user may be lower than in previous versions of the protocol.
5858

5959
### Internal scaledAccounting
6060

@@ -88,5 +88,5 @@ In Aave versions `< 3.5` this action would always result in burning `100` allowa
8888
- `repayWithAToken` is only allowed when the user is still healthy **after** the repayment. This is done in order to prevent some edge cases where the user would have debt, but no collateral or now with the adjustments on rounding, bringing himself into liquidation area through selfRepayment.
8989
- `eliminateReserveDeficit` return value: The `eliminateReserveDeficit` function has been updated to return the `uint256` amount of deficit that was actually covered. This returned value represents the lesser of the input `amount` and the actual `deficit` of the reserve at the time of the call. This provides clarity to the caller on the exact amount that was successfully written off.
9090
- Note: This is a non-breaking change. The migration from no return value to a `uint256` return value is not expected to break any existing integrations.
91-
- In previous versions of the protocol, `Mint` and `Burn` events did not always perfectly reflect the amount minted and burned due to imprecision in the calculation of the `amountToMint` and `amountToBurn` variables. In v3.5, the amount emitted now always accurately reflects the difference between the previous upscaled balance and the new upscaled balance.
91+
- In previous versions of the protocol, `Mint` and `Burn` events on `AToken` and `VariableDebtToken` did not always perfectly reflect the amount minted and burned due to imprecision in the calculation of the `amountToMint` and `amountToBurn` variables. In v3.5, the `value` emitted in `Mint` and `Burn` events now always accurately reflects the difference between the previous upscaled balance and the new upscaled balance. For `AToken` transfers, the `Transfer` event emits the input amount, while the `BalanceTransfer` event emits the precise scaled amount being transferred. Due to the new rounding logic, the actual change in unscaled balance might differ slightly from the input amount.
9292
- The control flow of `borrow` has been altered. While in previous versions of the protocol the `borrow` function would first check the hf limitations, from v3.5.0 the healthfactor check is performed at the end. Moving the check allows to de-duplicate the healthfactor related calculations and avoids issues due to non-equivalence in some edge cases.

docs/3.5/Aave-v3.5-properties.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ In the following properties `shares` refers to the `scaled balance`, while `asse
1616
- when evaluating the vToken balance of a user, the balance should be calculated as `balance = ceil(shares * index)`
1717
- when calculating the `liquidationProtocolFeeAmount` and the fee distributed to the treasury, the received shares should be rounded up
1818
- the flashLoanPremium is always rounded up, meaning that even when flashing just 1 wei of an asset, you will pay 1 wei of fee (where in previous versions of the protocol, the fee would be rounded to zero)
19-
- when calculating the value of a user's collateral (aTokens) in the base currency, the result of `(balanceInAssetUnits * assetPrice) / assetUnit` is rounded down.
19+
- when calculating the value of a user's collateral (aTokens) in the base currency, the result of `(balanceInAssetUnits * assetPrice) / assetUnit` is rounded down. (this was already the case in previous versions of the protocol for `GenericLogic._getUserBalanceInBaseCurrency`)
2020
- when calculating the totalSupply of the aToken, `totalScaledSupply * index` is rounded down.
2121
- when calculating the value of a user's total debt (vTokens) in the base currency, the result of `(debtInAssetUnits * assetPrice) / assetUnit` is rounded up.
2222
- when calculating the totalSupply of the vToken, `totalScaledSupply * index` is rounded up.

src/contracts/protocol/libraries/logic/BorrowLogic.sol

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ library BorrowLogic {
7373
})
7474
);
7575

76-
// As vDebt.mint rounds up, we ensure an equivalent of >= params.amount debt is created.
7776
reserveCache.nextScaledVariableDebt = IVariableDebtToken(reserveCache.variableDebtTokenAddress)
7877
.mint(
7978
params.user,

src/contracts/protocol/libraries/logic/GenericLogic.sol

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,10 +153,10 @@ library GenericLogic {
153153

154154
// @note At this point, `avgLiquidationThreshold` represents
155155
// `SUM(collateral_base_value_i * liquidation_threshold_i)` for all collateral assets.
156-
// It has 8 decimals (base currency) + 4 decimals (percentage) = 12 decimals.
156+
// It has 8 decimals (base currency) + 2 decimals (percentage) = 10 decimals.
157157
// healthFactor has 18 decimals
158158
// healthFactor = (avgLiquidationThreshold * WAD / totalDebtInBaseCurrency) / 100_00
159-
// 18 decimals = (12 decimals * 18 decimals / 8 decimals) / 4 decimals = 18 decimals
159+
// 18 decimals = (10 decimals * 18 decimals / 8 decimals) / 2 decimals = 18 decimals
160160
vars.healthFactor = (vars.totalDebtInBaseCurrency == 0)
161161
? type(uint256).max
162162
: vars.avgLiquidationThreshold.wadDiv(vars.totalDebtInBaseCurrency) / 100_00;
@@ -220,7 +220,6 @@ library GenericLogic {
220220
uint256 assetPrice,
221221
uint256 assetUnit
222222
) private view returns (uint256) {
223-
// Replicate vDebt.balanceOf (round up), to always overestimate the debt.
224223
uint256 userTotalDebt = IScaledBalanceToken(reserve.variableDebtTokenAddress)
225224
.scaledBalanceOf(user)
226225
.getVTokenBalance(reserve.getNormalizedDebt());

src/contracts/protocol/libraries/logic/LiquidationLogic.sol

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ library LiquidationLogic {
7272
* @param reservesData The state of all the reserves
7373
* @param userConfig The user configuration mapping that tracks the supplied/borrowed assets
7474
* @param params The additional parameters needed to execute the eliminateDeficit function
75+
* @return The amount of deficit covered
7576
*/
7677
function executeEliminateDeficit(
7778
mapping(address => DataTypes.ReserveData) storage reservesData,
@@ -108,7 +109,6 @@ library LiquidationLogic {
108109
userConfig.setUsingAsCollateral(reserve.id, params.asset, params.user, false);
109110
}
110111

111-
// As aToken.burn rounds up the burned shares, we ensure at least an equivalent of >= balanceWriteOff is burned.
112112
IAToken(reserveCache.aTokenAddress).burn({
113113
from: params.user,
114114
receiverOfUnderlying: reserveCache.aTokenAddress,
@@ -200,11 +200,9 @@ library LiquidationLogic {
200200
})
201201
);
202202

203-
// Replicate aToken.balanceOf (round down), to always underestimate the collateral.
204203
vars.borrowerCollateralBalance = IAToken(vars.collateralReserveCache.aTokenAddress)
205204
.scaledBalanceOf(params.borrower)
206205
.getATokenBalance(vars.collateralReserveCache.nextLiquidityIndex);
207-
// Replicate vDebt.balanceOf (round up), to always overestimate the debt.
208206
vars.borrowerReserveDebt = IVariableDebtToken(vars.debtReserveCache.variableDebtTokenAddress)
209207
.scaledBalanceOf(params.borrower)
210208
.getVTokenBalance(vars.debtReserveCache.nextVariableBorrowIndex);

src/contracts/protocol/libraries/logic/ValidationLogic.sol

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,6 @@ library ValidationLogic {
177177
}
178178

179179
if (vars.borrowCap != 0) {
180-
// Replicate vDebt.totalSupply (round up), to always overestimate the debt.
181180
vars.totalDebt = (params.reserveCache.currScaledVariableDebt + params.amountScaled)
182181
.getVTokenBalance(params.reserveCache.nextVariableBorrowIndex);
183182

@@ -457,8 +456,8 @@ library ValidationLogic {
457456
* @param userConfig The state of the user for the specific reserve
458457
* @param asset The asset for which the ltv will be validated
459458
* @param from The user from which the aTokens are being transferred
460-
* @param userEModeCategory The users active efficiency mode category
461459
* @param oracle The price oracle
460+
* @param userEModeCategory The users active efficiency mode category
462461
*/
463462
function validateHFAndLtvzero(
464463
mapping(address => DataTypes.ReserveData) storage reservesData,

src/contracts/protocol/tokenization/AToken.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ abstract contract AToken is VersionedInitializable, ScaledBalanceTokenBase, EIP7
203203
// As an example: transferFrom(..., 1) at a liquidity index of 1.1 where the recipient has a "scaled up" balance of `9 * 1.1 = 9.9 = 9` before the transfer, will have a balance of `10 * 1.1. = 11` after the Transfer.
204204
// While this problem is not solvable without introducing breaking changes, on Aave v3.5 the situation is improved in the following way:
205205
// - The `correct` amount to be deducted is considered to be `scaledUpFloor(scaledDownCeil(input.amount))`. This replicates the behavior on transfer, followed by a balanceOf.
206-
// - In order to not introduce a breaking change for existing integrations, the deducted allowance is based on the available allowance as `Max(availableAllowance, (amount, correctAmount))`
206+
// - To avoid breaking existing integrations, the amount deducted from the allowance is the minimum of the available allowance and the actual up-scaled asset amount.
207207
amount.getATokenTransferScaledAmount(index).getATokenBalance(index)
208208
);
209209
_transfer(sender, recipient, amount.toUint120());

src/contracts/protocol/tokenization/VariableDebtToken.sol

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,16 @@ abstract contract VariableDebtToken is DebtTokenBase, ScaledBalanceTokenBase, IV
2323
using TokenMath for uint256;
2424
using SafeCast for uint256;
2525

26-
// @note This gap is made only to add the `__deprecated_ghoUserState` variable
26+
// @note This gap is made only to add the `__DEPRECATED_AND_NEVER_TO_BE_REUSED` variable
2727
// The length of this gap can be decreased in order to add new variables
28-
uint[3] private __unusedGap;
28+
uint256[3] private __unusedGap;
2929

3030
// @note deprecated in v3.4.0 upgrade in the GHO vToken.
3131
// This storage slot can't be used in all vTokens, because the GHO vToken
3232
// had a mapping here (before v3.4.0) and right now has some non-zero mapping values in this slot.
3333
// old version: mapping(address => GhoUserState) internal _ghoUserState
34-
bytes32 private __deprecated_ghoUserState;
34+
// This storage slot MUST NOT be reused to avoid storage layout conflicts.
35+
bytes32 private __DEPRECATED_AND_NEVER_TO_BE_REUSED;
3536

3637
/**
3738
* @dev Constructor.
@@ -66,7 +67,10 @@ abstract contract VariableDebtToken is DebtTokenBase, ScaledBalanceTokenBase, IV
6667

6768
/// @inheritdoc IERC20
6869
function balanceOf(address user) public view virtual override returns (uint256) {
69-
return super.balanceOf(user).getVTokenBalance(POOL.getReserveNormalizedVariableDebt(_underlyingAsset));
70+
return
71+
super.balanceOf(user).getVTokenBalance(
72+
POOL.getReserveNormalizedVariableDebt(_underlyingAsset)
73+
);
7074
}
7175

7276
/// @inheritdoc IVariableDebtToken
@@ -88,7 +92,7 @@ abstract contract VariableDebtToken is DebtTokenBase, ScaledBalanceTokenBase, IV
8892
// Similar to the aToken `transferFrom` function, handling this scenario exactly is impossible.
8993
// While this problem is not solvable without introducing breaking changes, on Aave v3.5 the situation is improved in the following way:
9094
// - The `correct` amount to be deducted is considered to be `scaledUpCeil(scaledAmount)`. This replicates the behavior on borrow followed by a balanceOf.
91-
// - In order to not introduce a breaking change for existing integrations, the deducted allowance is based on the available allowance as `Max(availableAllowance, (amount, correctAmount))`
95+
// - To avoid breaking existing integrations, the amount deducted from the allowance is the minimum of the available allowance and the actual up-scaled debt amount.
9296
uint256 scaledUp = scaledAmount.getVTokenBalance(index);
9397
_decreaseBorrowAllowance(
9498
onBehalfOf,

src/contracts/protocol/tokenization/base/IncentivizedERC20.sol

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,8 +208,10 @@ abstract contract IncentivizedERC20 is Context, IERC20Detailed {
208208
uint256 correctedAmount
209209
) internal virtual {
210210
uint256 currentAllowance = _allowances[owner][spender];
211-
if (currentAllowance < amount)
211+
if (currentAllowance < amount) {
212212
revert ERC20InsufficientAllowance(spender, currentAllowance, amount);
213+
}
214+
213215
uint256 consumption = currentAllowance >= correctedAmount ? correctedAmount : currentAllowance;
214216
_approve(owner, spender, currentAllowance - consumption);
215217
}

0 commit comments

Comments
 (0)