Closed sherlock-admin closed 6 months ago
1 comment(s) were left on this issue during the judging contest.
takarez commented:
valid: high(4)
I don't believe this is correct. If you look at this function being called by fundingAdjustedLongPnLTotal
when stableCollateralPerShare
is being called accounts for the new funding rate. The same happens when remainingMargin is being calculated using getPositionSummary.
If you could provide a PoC for the same, that would help us identify the issue. However, we will implement the suggestion of settling the funding fees when liquidation happens as this would make the funding rate changes smoother (the same reason we do when executing any order).
xiaoming90
high
Discrepancies in the data used during the invariant checks leading to liquidation issue
Summary
The liquidation might not execute as intended due to discrepancies in the data used during the invariant checks, leading to underwater positions and bad debt accumulated in the protocol, threatening the solvency of the protocol.
Vulnerability Detail
At Line 109 below, the
settledMargin
is greater than 0, a portion (or all) of the margin will be sent to the liquidator and LPs. If thesettledMargin
is negative, the LPs will bear the cost of the underwater position's loss.When the
liquidate
function is executed, theliquidationInvariantChecks
modifier will be triggered to perform invariant checks before and after the execution.https://github.com/sherlock-audit/2023-12-flatmoney/blob/main/flatcoin-v1/src/LiquidationModule.sol#L85
The
liquidationInvariantChecks
modifier will trigger the_stableCollateralPerShareLiquidation
function internally. This function will compute theexpectedStableCollateralPerShare
based on the remaining margin (also calledsettledMargin
), as shown in Line 130. Depending on whether the remaining margin is positive or negative, the logic for computing theexpectedStableCollateralPerShare
is different.If the remaining margin is positive, the LP will obtain whatever margin is left after sending the keeper fee. Thus, the
expectedStableCollateralPerShare
is likely to be the same or increase (First Branch). On the other hand, if the remaining margin is unhealthy, the LP will incur a loss, andexpectedStableCollateralPerShare
is likely to decrease (Second Branch).The condition and logic at Line 130-151 below within the
InvariantChecks._stableCollateralPerShareLiquidation
function must mirror exactly the code at Line 109-143 above within theLiquidationModule.liquidate
function. One slight discrepancy will cause the execution flow to switch to the wrong branch in the if-else statement. For instance, the`LiquidationModule.liquidate
function executes the branch where (settledMargin => 0
) while the invariant check executes the branch where (settledMargin < 0
).Thus, if there is any slight discrepancy or desync, the
expectedStableCollateralPerShare
computed will be inaccurate, leading to an unexpected revert during the check at Line 152 below during the liquidation process. It was found that there exists a discrepancy that led to this issue, and it will be described further below.https://github.com/sherlock-audit/2023-12-flatmoney/blob/main/flatcoin-v1/src/misc/InvariantChecks.sol#L118
It was found that the discrepancy between the remaining margin (
settledMargin
) used within these two functions.LiquidationModule.liquidate
function, thesettledMargin
is retrieved after thevault.settleFundingFees
is executed, which settles the funding fees. As such, when thesettledMargin
of the liquidated position is retrieved, it will take into comparison the funding fees earned or lost till now.InvariantChecks._stableCollateralPerShareLiquidation
function, thesettledMargin
is computed and store within theinvariantBefore
variable at Line 59 below before theliquidate
function is executed at Line 69 below. Thus, the funding fee is not settled yet when thesettledMargin
is computed. ThesettledMargin
without funding fee settlement will then be passed into the_stableCollateralPerShareLiquidation
for use later at Line 78 below after the liquidation execution is completed.https://github.com/sherlock-audit/2023-12-flatmoney/blob/main/flatcoin-v1/src/misc/InvariantChecks.sol#L56
Impact
Liquidation is the core component of the protocol and is important to the solvency of the protocol. If the liquidation does not execute as intended, such as in the scenario mentioned above where the invariant check will revert unexpectedly, underwater positions and bad debt accumulate in the protocol, threatening the solvency of the protocol.
Code Snippet
https://github.com/sherlock-audit/2023-12-flatmoney/blob/main/flatcoin-v1/src/LiquidationModule.sol#L85
https://github.com/sherlock-audit/2023-12-flatmoney/blob/main/flatcoin-v1/src/misc/InvariantChecks.sol#L118
https://github.com/sherlock-audit/2023-12-flatmoney/blob/main/flatcoin-v1/src/misc/InvariantChecks.sol#L56
Tool used
Manual Review
Recommendation
Ensure that
settledMargin
calculated withinLiquidationModule.liquidate
andInvariantChecks._stableCollateralPerShareLiquidation
function are consistent.One possible solution is to settle the funding fee at the start of the
liquidationInvariantChecks
modifier.