Open sherlock-admin3 opened 1 month ago
Out-of-Bounds Array Access in settleUpnl Function Leading to Transaction Revert.
In the settleUpnl function of the LibSettlement contract, the value of data.partyBUpnlIndex is not properly validated before it is used to index into the settleSig.upnlPartyBs array. If data.partyBUpnlIndex is equal to or greater than the length of settleSig.upnlPartyBs, this results in an out-of-bounds access and causes the transaction to revert.
Impact: If data.partyBUpnlIndex exceeds the bounds of settleSig.upnlPartyBs, the transaction will revert. This can be exploited as a Denial of Service (DoS) attack by submitting manipulated signatures with invalid partyBUpnlIndex values, preventing settlements from occurring correctly.
Attack Scenario: An attacker can manipulate the partyBUpnlIndex in the SettlementSig to create a situation where the settleUpnl function always reverts. This can be done by crafting a signature with an invalid index, thus preventing settlements from completing and disrupting the system.
The transaction fails with a revert due to the out-of-bounds access as partyBUpnlIndex is invalid, causing a denial of service for any subsequent transactions trying to settle upnl.
This can be exploited as a DoS attack, where the attacker can repeatedly submit manipulated signatures to keep the service in a state of failure, ultimately disrupting user activity and trust in the system.
danyilbalko
High
Service stopped due to incorrect judgment of array length and index in settleUpnl function error. (DoS)
Summary
In the settleUpnl function,
If the values of data.partyBUpnlIndex and settleSig.upnlPartyBs.length are the same, the following error occurs.
address[] memory partyBs = new address; ... .... ...
partyBs[data.partyBUpnlIndex] = quote.partyB; .... .... ....
The value is assigned to a place where the partyBs array index is not assigned.
This causes a memory error in the service and causes the service to stop.
Root Cause
https://github.com/sherlock-audit/2024-09-symmio-v0-8-4-update-contest/blob/main/protocol-core/contracts/libraries/LibSettlement.sol#L50
Internal pre-conditions
No response
External pre-conditions
Scenario Bob (Party A) has three open positions and zero allocated balance:
Position 1 with Rasa Hedger (Party B1): Unrealized Profit: $300 Quote ID: 1
Position 2 with PerpsHub Hedger (Party B2): Unrealized Profit: $100 Quote ID: 2
Position 3 with PerpsHub Hedger (Party B2): Unrealized Loss: $250 Quote ID: 3
Bob wants to close Position 3, which has an unrealized loss of $250.
Attack Path
No response
Impact
SettlementSig memory settleSig = SettlementSig({ reqId: bytes("uniqueRequestId"), timestamp: block.timestamp, quotesSettlementsData: [ QuoteSettlementData({quoteId: 1, currentPrice: currentPricePos1, partyBUpnlIndex: 1}), QuoteSettlementData({quoteId: 2, currentPrice: currentPricePos2, partyBUpnlIndex: 2}) ], upnlPartyBs: [-300, 150], // Rasa's upnl change, PerpsHub's upnl change upnlPartyA: 150, // Bob's total upnl being settled gatewaySignature: muonSignature, sigs: schnorrSignature });
uint256[] memory updatedPrices = [newPricePos1, newPricePos2];
perpsHubHedger.settleUpnl(settleSig, updatedPrices, bobAddress);
This is the case where the value of partyBUpnlIndex is set to 2 due to a mistake by a malicious user or a general user.
The following problem occurs in the settleUpnl function:
address[] memory partyBs = new address; .. ... partyBs[2] = quote.partyB;
PoC
No response
Mitigation
require(data.partyBUpnlIndex <= settleSig.upnlPartyBs.length, "LibSettlement: Invalid partyBUpnlIndex in signature");
modify the above code to the code below.
require(data.partyBUpnlIndex < settleSig.upnlPartyBs.length, "LibSettlement: Invalid partyBUpnlIndex in signature");