Open sherlock-admin4 opened 2 weeks ago
1 comment(s) were left on this issue during the judging contest.
Hash01011122 commented:
Low/Medium Vuln, Chances of occurrence of mentioned edge case is nearly zero.
The protocol team fixed this issue in the following PRs/commits: https://github.com/SYMM-IO/protocol-core/pull/48
Escalate
This issue should be at least a Medium Risk due to its significant impact (Loss of assets) if the risk is realized.
Per the protocol’s source code, there is nothing to prevent a liquidator from also being a user (PartyA) since the protocol allows anyone to trade on its system. The PartyA role is permissionless and open to anyone. Also, no rules state on the contest page that a liquidator cannot be a PartyA or trade on the system.
Thus, it is entirely a valid scenario where a user is a liquidator and a PartyA simultaneously, leading to the issue mentioned in the report.
Per Sherlock’s judging rules (https://docs.sherlock.xyz/audits/judging/judging#v.-how-to-identify-a-medium-issue)
V. How to identify a medium issue: Causes a loss of funds but requires certain external conditions or specific states, or a loss is highly constrained. The losses must exceed small, finite amount of funds, and any amount relevant based on the precision or significance of the loss.
Thus, it meets Sherlock's requirement of a Medium Risk, where it causes a loss of funds but requires certain external conditions or specific states.
Escalate
This issue should be at least a Medium Risk due to its significant impact (Loss of assets) if the risk is realized.
Per the protocol’s source code, there is nothing to prevent a liquidator from also being a user (PartyA) since the protocol allows anyone to trade on its system. The PartyA role is permissionless and open to anyone. Also, no rules state on the contest page that a liquidator cannot be a PartyA or trade on the system.
Thus, it is entirely a valid scenario where a user is a liquidator and a PartyA simultaneously, leading to the issue mentioned in the report.
Per Sherlock’s judging rules (https://docs.sherlock.xyz/audits/judging/judging#v.-how-to-identify-a-medium-issue)
V. How to identify a medium issue: Causes a loss of funds but requires certain external conditions or specific states, or a loss is highly constrained. The losses must exceed small, finite amount of funds, and any amount relevant based on the precision or significance of the loss.
Thus, it meets Sherlock's requirement of a Medium Risk, where it causes a loss of funds but requires certain external conditions or specific states.
You've created a valid escalation!
To remove the escalation from consideration: Delete your comment.
You may delete or edit your escalation comment anytime before the 48-hour escalation window closes. After that, the escalation becomes final.
Possibility of this issue is near to zero so it should be low since it's not viable
Possibility of this issue is near to zero so it should be low since it's not viable
Disagree. As mentioned in the report and escalation's comment, it is entirely a valid scenario where a user is a liquidator and a PartyA simultaneously, leading to the issue mentioned in the report.
In Sherlock, edge cases that have an impact that could potentially lead to a loss of assets are always judged as H/M. This view is derived with Sherlock's judging rule (https://docs.sherlock.xyz/audits/judging/judging#v.-how-to-identify-a-medium-issue) below:
Causes a loss of funds but requires certain external conditions or specific states, or a loss is highly constrained.
I think I need clarification on the attack path. I'll show how I see it and please correct me if it's wrong or not:
deferredSetSymbolsPrice
and after that Alice receives all the liquidation fees that Bob received above +- PnL, correct?If we simplify the attack path as much as possible, is it correct?
I think I need clarification on the attack path. I'll show how I see it and please correct me if it's wrong or not:
- Bob is partyA.
- Bob is liquidated by Alice and his balance is set at 0.
- Bob does some liquidations himself and gets a liquidation fee of $1000 in total.
- Alice calls
deferredSetSymbolsPrice
and after that Alice receives all the liquidation fees that Bob received above +- PnL, correct?- Bob loses these funds and Alice gets them (as I understand, doesn't even steal them necessarily).
If we simplify the attack path as much as possible, is it correct?
@WangSecurity
Each PartyA's account has a liquidation fee (LF) component, which is reserved and locked.
The PartyA's locked liquidation fee (LF) is the prize that will be paid to the liquidator. In my scenario, the locked LF of Bob's PartyA account is \$100. Thus, any liquidator that liquidates Bob's PartyA is entitled to a maximum of $100, as per the protocol's specification. This liquidator fee was agreed upon by both the PartyA (maker) and PartyB (taker) when they opened the position and finalized within the protocol.
The protocol specification already clearly dictates that any liquidator who liquidates Bob's PartyA is entitled to a maximum of \$100, which is PartyA's locked liquidation fee (LF). However, in the scenario mentioned in the report, the liquidator (Alice) received \$900 instead of \$100, which deviates from the protocol specification.
The liquidator (Alice) took more than what was expected from Bob's account. When a liquidator liquidates Bob's account, they are not entitled to all the assets left in the account. They are only entitled to \$100 and not anything more than that.
Thank you for that clarification, but there's still one part I might be missing. In your scenario, after Alice liquidates Bob (PartyA), and before she receives these $100 of LF, Bob also gets $1000. Is it because he liquidated the previous PartyA or other users?
Thank you for that clarification, but there's still one part I might be missing. In your scenario, after Alice liquidates Bob (PartyA), and before she receives these $100 of LF, Bob also gets $1000. Is it because he liquidated the previous PartyA or other users?
@WangSecurity
Firstly, the term "PartyA" is the same as "User/Other Users". Users are normal people who trade on Symm platform and anyone with a blockchain wallet can do so (permissionless).
Secondly, Alice did not receive $100 in my scenario. Instead, she receives $900, which is incorrect and much more than expected. This amount exceeds the maximum allowed liquidation fee of $100 she is entitled. Effectively, $800 is "stolen" from Bob and Bob lost $800.
Following are the timeline of the events for reference:
Thank you, but I'm not sure if it answers my question.
In T3, it says "Some liquidations have settled and Bob receives 1000 as a liquidation fee". It's Bob liquidating other users correct? Just need to clarify where these funds come from.
Thank you, but I'm not sure if it answers my question.
In T3, it says "Some liquidations have settled and Bob receives 1000 as a liquidation fee". It's Bob liquidating other users correct? Just need to clarify where these funds come from.
@WangSecurity
Thank you very much. I agree that this scenario is viable, even though it's very unlikely to occur, it's still possible with high constraints. Planning to accept the escalation and validate the issue with medium severity.
Result: Medium Unique
The Lead Senior Watson signed off on the fix.
xiaoming90
High
PartyA's allocated balance could increase after
deferredLiquidatePartyA
is executedSummary
PartyA's allocated balance could increase after
deferredLiquidatePartyA
is executed in an edge case, which could result in loss of assets.Vulnerability Detail
When the
deferredLiquidatePartyA
function is executed, if there is any excess allocated balance inaccountLayout.allocatedBalances[partyA]
, they will be transferred to theaccountLayout.partyAReimbursement[partyA]
at Line 42 below. Afterwards, theaccountLayout.allocatedBalances[partyA]
should not increase under any circumstance. Otherwise, an accounting error will occur.https://github.com/sherlock-audit/2024-06-symmetrical-update-2/blob/main/protocol-core/contracts/facets/liquidation/DeferredLiquidationFacetImpl.sol#L22
However, there is an edge case where the
accountLayout.allocatedBalances[partyA]
can increase after thedeferredLiquidatePartyA
function is executed.Assume Bob is a liquidator and a PartyA at the same time. As PartyA is permissionless, anyone can be a PartyA. There is no validation check in the codebase that prevents a liquidator from also being a PartyA AND no rules stated on the contest page that a liquidator cannot be a PartyA. Thus, it is fair to assume that some liquidators might use the same wallet to trade on the Symm App simultaneously (Users of Symm App = PartyA).
deferredLiquidatePartyA
function (Step 1 of liquidation process), and hisaccountLayout.allocatedBalances[Bob]
has been set to zero at Line 41 above.accountLayout.allocatedBalances[Bob]
as per the code at Line 297-298 below. Assume that 1000 is paid out as a liquidation fee to Bob. Thus,accountLayout.allocatedBalances[Bob] = 1000
now.https://github.com/sherlock-audit/2024-06-symmetrical-update-2/blob/main/protocol-core/contracts/facets/liquidation/LiquidationFacetImpl.sol#L297
accountLayout.allocatedBalances[Bob] = 1000
at this point. Next, thedeferredSetSymbolsPrice
function (Step 2 of liquidation process) will called against Bob's PartyA account.deferredSetSymbolsPrice
is designed to always expect theavailableBalance
at Line 76 to be zero or negative to work properly. IfavailableBalance
is positive, the logic and accounting will be incorrect. Because theaccountLayout.allocatedBalances[Bob] = 1000
, theavailableBalance
will become a positive value. Let's assume thatavailableBalance
returned fromLibAccount.partyAAvailableBalanceForLiquidation
function at Line 76 is 800 after factoring the PnL (loss and/or deficit)remainingLf
will be evaluated as 900. The liquidation fee of PartyA account will unexpectedly increase from 100 to 900, which is incorrect regarding the system's accounting. The liquidators should only receive up toaccountLayout.lockedBalances[partyA].lf
(100) of liquidation and not more than that amount. However, in this case, the liquidators received more than expected (900 instead of 100).https://github.com/sherlock-audit/2024-06-symmetrical-update-2/blob/main/protocol-core/contracts/facets/liquidation/DeferredLiquidationFacetImpl.sol#L62
Impact
Loss of assets as shown in the above scenario.
Code Snippet
https://github.com/sherlock-audit/2024-06-symmetrical-update-2/blob/main/protocol-core/contracts/facets/liquidation/DeferredLiquidationFacetImpl.sol#L22
https://github.com/sherlock-audit/2024-06-symmetrical-update-2/blob/main/protocol-core/contracts/facets/liquidation/LiquidationFacetImpl.sol#L297
https://github.com/sherlock-audit/2024-06-symmetrical-update-2/blob/main/protocol-core/contracts/facets/liquidation/DeferredLiquidationFacetImpl.sol#L62
Tool used
Manual Review
Recommendation
Implement the following additional logic to handle any edge case where PartyA's allocated balance could increase after
deferredLiquidatePartyA
(Step 1 of the liquidation process) is executed.