Skip to content

Commit

Permalink
docs: 3.3 docs & GHO improvements (aave-dao#84)
Browse files Browse the repository at this point in the history
- refactor to assume the umbrella never has debt

Co-authored-by: Ernesto Boado <[email protected]>
  • Loading branch information
sakulstra and eboadom authored Oct 22, 2024
1 parent f910b01 commit dd00c6a
Show file tree
Hide file tree
Showing 15 changed files with 1,843 additions and 81 deletions.
6 changes: 4 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ test-contract :; forge test --match-contract ${filter} -vvv
test-watch :; forge test --watch -vvv --no-match-contract DeploymentsGasLimits

# Coverage
coverage-base :; forge coverage --report lcov --no-match-coverage "(scripts|tests|deployments|mocks)"
coverage-base :; forge coverage --fuzz-runs 50 --report lcov --no-match-coverage "(scripts|tests|deployments|mocks)"
coverage-clean :; lcov --rc derive_function_end_line=0 --remove ./lcov.info -o ./lcov.info.p \
'src/contracts/extensions/v3-config-engine/*' \
'src/contracts/treasury/*' \
Expand All @@ -37,7 +37,7 @@ coverage :
download :; cast etherscan-source --chain ${chain} -d src/etherscan/${chain}_${address} ${address}
git-diff :
@mkdir -p diffs
@npx prettier ${before} ${after} --write
# @npx prettier ${before} ${after} --write
@printf '%s\n%s\n%s\n' "\`\`\`diff" "$$(git diff --no-index --ignore-space-at-eol ${before} ${after})" "\`\`\`" > diffs/${out}.md

# Deploy
Expand All @@ -51,3 +51,5 @@ deploy-libs :
npx catapulta-verify -b broadcast/LibraryPreCompileOne.sol/${chainId}/run-latest.json
make deploy-libs-two chain=${chain}
npx catapulta-verify -b broadcast/LibraryPreCompileTwo.sol/${chainId}/run-latest.json

gas-report :; forge test --fuzz-runs 50 --gas-report
61 changes: 48 additions & 13 deletions docs/3.3/Aave-v3.3-features.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ On Aave v3, some liquidation scenarios can result in a permanent "bad debt" on t
This occurs when the total collateral liquidated is insufficient to cover the repayment of all debt, leaving the account with zero collateral and some remaining debt.
We understand that such debt is unlikely to be repaid and adversely affects the protocol by continuing to accrue interest.

To mitigate the creation of new bad debt accounts post-liquidation and to halt further interest accrual on such liabilities, the bad debt feature introduces a new verification step during liquidation.
The bad debt feature introduces a new verification step during liquidation to mitigate the creation of new bad debt accounts post-liquidation and halt further interest accrual on such liabilities.
This step checks the total collateral and total debt values of the account post-liquidation and repayment:
If an account ends up with zero collateral and non-zero debt, any remaining debt in the account is burned and the new deficit created is accounted to the reserve.

Expand All @@ -20,21 +20,26 @@ If the total borrower’s debt exceeds the debt repaid in base currency, the var
The new `deficit` data is introduced to the `ReserveData` struct by re-utilizing the deprecated stableBorrowRate (`__deprecatedStableBorrowRate`) storage, and can be fetched via the new `getReserveDeficit` function in the Pool contract.

The deficit reduction of a reserve is introduced via the `eliminateReserveDeficit` function in the Pool contract, where a permissioned entity (the registered `Umbrella` on the PoolAddressesProvider) can burn aTokens to decrease the deficit of the respective reserve.
This function only allows burning up to the currently existing deficit and validates the callers health factor and LTV before reducing the deficit.
This function only allows burning aTokens(and in the case of GHO underlying) up to the currently existing deficit and validates the caller's health factor and LTV before reducing the deficit.

**Misc considerations**

- For positions already in bad debt, this upgrade does not offer any solution, but recommends the DAO to clean up these positions via a `repayOnBehalf`.
- `eliminateReserveDeficit` assumes for umbrella to have the tokens to be burned. In case of assets having virtual accounting enabled, aTokens will be burned. In case of virtual accounting being disabled, the underlying will be disposed of.
Depending on the coverage asset and reserve configuration(e.g. if coverage is done via underlying, and caps don't allow depositing) it might be that it us not possible to receive the aToken.
This is expected and considered a non-issue as the elimination of the deficit has no strict time constraint.

**Acknowledged limitations**

- For the scope of this feature we define a bad debt situation as an account that has zero collateral, in base currency, but retains some level of debt, in base currency.
Accounts with any remaining collateral potentially can be overcollateralized again.

### 2. Liquidation: 50% close factor re-design
### 2. Liquidation logic changes

#### 2.1 Liquidation: 50% close factor re-design

The Aave protocol currently implements a so-called "Close Factor" which determines how much of a debt position can be repaid in a single liquidation.
While in Aave v2, this parameter was a constant 50%, in Aave v3 there is an alteration between the default 50% and a max close factor of 100%, currently applied when a user health factor deteriorates below a certain threshold.
While in Aave v2, this parameter was a constant 50%, in Aave v3 there is an alteration between the default 50% and a max close factor of 100%, currently applied when a user health-factor deteriorates below a certain threshold.

The 50% close factor has always been applied on a per reserve basis, so if a user has e.g. the following positions:

Expand All @@ -44,39 +49,69 @@ The 50% close factor has always been applied on a per reserve basis, so if a use
- 9k $ ETH Collateral
A liquidation would only be able to liquidate 1.5k $ GHO/USDC or DAI per liquidation.

While being by design, it's also rather unintuitive and can even be problematic on smaller positions.
While being by design, it's also rather unintuitive and can even be problematic in smaller positions.
If the overall position value falls below a certain threshold it might no longer be economically sound to liquidate that position - by applying the close factor to each specific reserve, this problem scope is increased unnecessarily.

Therefore in Aave v3.3 the Close Factor is altered to apply for the whole position, which on the above example would allow to liquidate the whole 3k $ GHO/USDC or DAI in a single liquidation.
Therefore in Aave v3.3 the Close Factor is altered to apply for the whole position, which in the above example would allow to liquidate the whole 3k $ GHO/USDC or DAI in a single liquidation.

### 3. Liquidation: Position size dependent 100% close factor
#### 2.2 Liquidation: Position size dependent 100% close factor

For the aave protocol it is problematic to have dust debt positions, as there is no incentive to liquidate them, while on the other hand they create an ever increasing liability to the protocol.
Most of these dust debt positions are caused by the 50% close factor being applied to already small positions.
In this liquidators can only liquidate 50% of a position which will decrease the overall position value to a point where the gas cost no longer outweights the liquidation bonus.
In this liquidators can only liquidate 50% of a position which will decrease the overall position value to a point where the gas cost no longer outweighs the liquidation bonus.

Therefore in order to reduce the accumulation of minor debt positions, a new mechanism is introduced:
Liquidations up to a 100% close factor are now allowed whenever the total principal or the total debt of the user on the specific reserve being liquidated is below a `MIN_BASE_MAX_CLOSE_FACTOR_THRESHOLD`

**Example**:
Assuming a `MIN_BASE_MAX_CLOSE_FACTOR_THRESHOLD` of 1_000e8 and a position composed as:

- 2_300e8 collateral A
- 800e8 collateral B
- 900e8 debt A
- 1_100e8 debt B
- a health-factor at 0.96

In the previous system, a liquidation could have taken up to 50% of one of the two debt positions.
With the new system the `collateral B` and the `debt A` are below the `MIN_BASE_MAX_CLOSE_FACTOR_THRESHOLD`.
Therefore a liquidation could liquidate 100% of `debt A` for any principal and/or receive 100% of `collateral B` while liquidating any debt.

**Acknowledged limitations**
Liquidations are still highly influenced by gas price, liquidation bonus and secondary market liquidity.
Liquidations are still highly influenced by gas prices, liquidation-bonus and secondary market liquidity.
`MIN_BASE_MAX_CLOSE_FACTOR_THRESHOLD` has to be chosen in a "best effort" way to allow for liquidations on "average" network conditions.
A threshold of 2000$ for example would mean that, at a 1% bonus a liquidation cannot cost more then 20$ before no longer being liquidated by a economically reasonable liquidator.

### 4. Liquidation: Forced position cleanup
#### 2.3 Liquidation: Forced position cleanup

A problem that exists with current liquidations is that for one or another reason, liquidators sometimes chose to not clean up a full positions but leave some minor dust.
As elaborated before, small debt positions can be problmatic already, but they are especially problematic with the newly introduced bad debt cleanup:
As elaborated before, small debt positions can be a burden already, but they are especially problematic with the newly introduced bad debt cleanup:

- when leaving dust, the bad debt cleanup will **not** clean up debt, as it only triggers when the collateral is zero
- as the bad debt cleanup slightly increases gas, for liquidators there is an incentive to leave dust

To counter these problems a new mechanism is introduced to now allow any debt or collateral below `MIN_LEFTOVER_BASE` to remain after a liquidation.
If debt or collateral after the liquidation would be below `MIN_LEFTOVER_BASE`, but non of the two is exact zero, the transaction reverts.
If debt or collateral after the liquidation would be below `MIN_LEFTOVER_BASE`, but non of the two is exactly zero, the transaction reverts.
To achieve that, `MIN_LEFTOVER_BASE` is defined as `MIN_BASE_MAX_CLOSE_FACTOR_THRESHOLD/2`.
This way it is ensured that int he range of `[0, MIN_BASE_MAX_CLOSE_FACTOR_THRESHOLD]` you can perform a full liquidation (via close Factor 100%).
This way it is ensured that in the range of `[0, MIN_BASE_MAX_CLOSE_FACTOR_THRESHOLD]` you can perform a full liquidation (via close Factor 100%).
On the other hand a 50% liquidation in the range of `[MIN_BASE_MAX_CLOSE_FACTOR_THRESHOLD, Infinity]` will always leave at least `MIN_BASE_MAX_CLOSE_FACTOR_THRESHOLD/2`.

**Example**
Assuming a `MIN_BASE_MAX_CLOSE_FACTOR_THRESHOLD` of 1_000e8, `MIN_LEFTOVER_BASE` of 500e8 and a position composed as:

- 400e8 collateral A
- 1000e8 collateral B
- 900e8 debt A
- 400e8 debt B
- a healthFactor at 0.94

In the previous system it would have been possible to liquidate any amount of debt for any respective amount of collateral.
With the new system you have to either:

- liquidate 100% of `debt B`
- liquidate 100% of `collateral A`
- liquidate up to 400e8 of `debt A` or liquidate 100% of `debt A`
- liquidate up to 500e8 of `collateral B` or liquidate 100% of `collateral B`

**Acknowledged limitations**
This feature is highly dependent on `MIN_BASE_MAX_CLOSE_FACTOR_THRESHOLD` and therefore relies on choosing a reasonably high `MIN_BASE_MAX_CLOSE_FACTOR_THRESHOLD`.

Expand Down
Loading

0 comments on commit dd00c6a

Please sign in to comment.