Omniscia Euler Finance Audit
Liquidation Manual Review Findings
Liquidation Manual Review Findings
LNO-01M: Improper Liquidation Incentive Calculations
Type | Severity | Location |
---|---|---|
Logical Fault | Liquidation.sol:L158-L161 |
Description:
The Liquidation::calculateMaxLiquidation
mechanism will artificially create bad debt due to the discountFactor
for low LTV configurations. Specifically, a liquidate-able position may be able to recover fully with the collateral available yet can be liquidated to force the discounted collateral-attached debt to be socialized.
As an example configuration using simplistic terms:
- Asset LTV: 0.5
- Asset Balance: 100 USD
- Asset Liquidity Collateral Value: 50 USD
- Asset Liquidity Liability Value: 100 USD
In the above example, the discountFactor
will be maximized (i.e. 80%
) and thus the maxYieldValue
will exceed the available balance of the asset (i.e. 100 USD / 80% = 125 USD
).
As a result, the ensuing if
conditional will lower the maxRepayValue
to 80 USD
even though the position has sufficient collateral to fulfil its liability obligations.
Impact:
Under certain conditions, the liquidation incentives offered by the Liquidation::calculateMaxLiquidation
function can be capitalized by liquidators to create bad debt by forcing a position into insolvency even though value-wise the position would be solvent.
Additionally, the present system effectively incentivizes users to liquidate their own collateral via a secondary account thus repaying their position at a discount.
Example:
112function calculateMaxLiquidation(LiquidationCache memory liqCache, VaultCache memory vaultCache)113 private114 view115 returns (LiquidationCache memory)116{117 // Check account health118
119 (uint256 liquidityCollateralValue, uint256 liquidityLiabilityValue) =120 calculateLiquidity(vaultCache, liqCache.violator, liqCache.collaterals, LTVType.LIQUIDATION);121
122 // no violation123 if (liquidityCollateralValue > liquidityLiabilityValue) return liqCache;124
125 // Compute discount126
127 uint256 discountFactor = liquidityCollateralValue * 1e18 / liquidityLiabilityValue; // health score = 1 - discount128
129 if (discountFactor < 1e18 - MAXIMUM_LIQUIDATION_DISCOUNT) {130 discountFactor = 1e18 - MAXIMUM_LIQUIDATION_DISCOUNT;131 }132
133 // Compute maximum yield134
135 uint256 collateralBalance = IERC20(liqCache.collateral).balanceOf(liqCache.violator);136 uint256 collateralValue =137 vaultCache.oracle.getQuote(collateralBalance, liqCache.collateral, vaultCache.unitOfAccount);138
139 if (collateralValue == 0) {140 // worthless collateral can be claimed with no repay141 liqCache.yieldBalance = collateralBalance;142 return liqCache;143 }144
145 uint256 liabilityValue = liqCache.owed.toUint();146 if (address(vaultCache.asset) != vaultCache.unitOfAccount) {147 // liquidation, in contrast to liquidity calculation, uses mid-point pricing instead of bid/ask148 liabilityValue =149 vaultCache.oracle.getQuote(liabilityValue, address(vaultCache.asset), vaultCache.unitOfAccount);150 }151
152 uint256 maxRepayValue = liabilityValue;153 uint256 maxYieldValue = maxRepayValue * 1e18 / discountFactor;154
155 // Limit yield to borrower's available collateral, and reduce repay if necessary156 // This can happen when borrower has multiple collaterals and seizing all of this one won't bring the violator back to solvency157
158 if (collateralValue < maxYieldValue) {159 maxRepayValue = collateralValue * discountFactor / 1e18;160 maxYieldValue = collateralValue;161 }162
163 liqCache.repay = (maxRepayValue * liqCache.owed.toUint() / liabilityValue).toAssets();164 liqCache.yieldBalance = maxYieldValue * collateralBalance / collateralValue;165
166 return liqCache;167}
Recommendation:
We advise the discountFactor
to solely be applied if the collateralValue
exceeds the liabilityValue
as otherwise toxic debt will be created at the expense of the system.
To note, the documentation line that precedes the referenced if
conditional should be corrected as the conditional can trigger under the aforementioned conditions which do not fall under the "insolvency" category.
Alleviation (fb2dd77a6f):
The Euler Finance team evaluated this exhibit and has opted to acknowledge it as an inherent economical risk to lending protocols. Additionally, the Euler Finance team maintained that the proposed mitigation would cause toxic debt to be further exacerbated as no one would desire to liquidate it.
To clarify the exhibit's original intentions, the proposed mechanism is to offer a discount on excess collateralValue
that exceeds the liabilityValue
solely when that case is applicable. Specifically, we propose that a position that is able to be liquidated while recovering fully should offer a discount on the extra collateral the user holds.
Toxic liquidations (i.e. under-collateralized positions) should retain their present behaviour and impose a discount unconditionally, as at that point toxic debt is unavoidable. The exhibit's focus is toxic debt that is avoidable without an expense to the protocol, simply by reducing the incentive of the liquidator rather than eliminating it.
We invite the Euler Finance team to re-visit this exhibit, as well as adjust the documentation line outlined in the last sentence of the "Recommendation" chapter regardless of their action.
Alleviation (0f2192ac81):
We engaged in extensive discussions with the Euler Finance team debating the proposed liquidation incentive mechanism, the outputs of which have been reflected in the Dutch Liquidation Analysis authored by the Euler Finance team.
In summary, we consider the proposed mechanism sufficiently deliberated within the paper and we are aligned with all criticism levied; especially in relation to partial liquidations and their impact on the overall game-theory mechanics that surround liquidations.
As a result of these efforts, we consider this exhibit to be informational in nature and to be nullified as the original incentive model employed by the Euler Finance team does not lead to any active vulnerability and has been considered the optimal approach based on the business requirements of the Euler Finance team.