Liquidation can be blocked by incrementing the nonce
Malicious users could block liquidators from liquidating their accounts, which creates unfairness in the system and lead to a loss of profits to the counterparty.\\nInstance 1 - Blocking liquidation of PartyA\\nA liquidatable PartyA can block liquidators from liquidating its account.\\n```\\nFile: LiquidationFacetImpl.sol\\n    function liquidatePartyA(address partyA, SingleUpnlSig memory upnlSig) internal {\\n        MAStorage.Layout storage maLayout = MAStorage.layout();\\n\\n        LibMuon.verifyPartyAUpnl(upnlSig, partyA);\\n        int256 availableBalance = LibAccount.partyAAvailableBalanceForLiquidation(\\n            upnlSig.upnl,\\n            partyA\\n        );\\n        require(availableBalance < 0, "LiquidationFacet: PartyA is solvent");\\n        maLayout.liquidationStatus[partyA] = true;\\n        maLayout.liquidationTimestamp[partyA] = upnlSig.timestamp;\\n        AccountStorage.layout().liquidators[partyA].push(msg.sender);\\n    }\\n```\\n\\nWithin the `liquidatePartyA` function, it calls the `LibMuon.verifyPartyAUpnl` function.\\n```\\nFile: LibMuon.sol\\n    function verifyPartyAUpnl(SingleUpnlSig memory upnlSig, address partyA) internal view {\\n        MuonStorage.Layout storage muonLayout = MuonStorage.layout();\\n//        require(\\n//            block.timestamp <= upnlSig.timestamp + muonLayout.upnlValidTime,\\n//            "LibMuon: Expired signature"\\n//        );\\n        bytes32 hash = keccak256(\\n            abi.encodePacked(\\n                muonLayout.muonAppId,\\n                upnlSig.reqId,\\n                address(this),\\n                partyA,\\n                AccountStorage.layout().partyANonces[partyA],\\n                upnlSig.upnl,\\n                upnlSig.timestamp,\\n                getChainId()\\n            )\\n        );\\n        verifyTSSAndGateway(hash, upnlSig.sigs, upnlSig.gatewaySignature);\\n    }\\n```\\n\\nThe `verifyPartyAUpnl` function will take the current nonce of PartyA (AccountStorage.layout().partyANonces[partyA]) to build the hash needed for verification.\\nWhen the PartyA becomes liquidatable or near to becoming liquidatable, it could start to monitor the mempool for any transaction that attempts to liquidate their accounts. Whenever a liquidator submits a `liquidatePartyA` transaction to liquidate their accounts, they could front-run it and submit a transaction to increment their nonce. When the liquidator's transaction is executed, the on-chain PartyA's nonce will differ from the nonce in the signature, and the liquidation transaction will revert.\\nFor those chains that do not have a public mempool, they can possibly choose to submit a transaction that increments their nonce in every block as long as it is economically feasible to obtain the same result.\\nGas fees that PartyA spent might be cheap compared to the number of assets they will lose if their account is liquidated. Additionally, gas fees are cheap on L2 or side-chain (The protocol intended to support Arbitrum One, Arbitrum Nova, Fantom, Optimism, BNB chain, Polygon, Avalanche as per the contest details).\\nThere are a number of methods for PartyA to increment their nonce, this includes but not limited to the following:\\nAllocate or deallocate dust amount\\nLock and unlock the dummy position\\nCalls `requestToClosePosition` followed by `requestToCancelCloseRequest` immediately\\nInstance 2 - Blocking liquidation of PartyB\\nThe same exploit can be used to block the liquidation of PartyB since the `liquidatePartyB` function also relies on the `LibMuon.verifyPartyBUpnl,` which uses the on-chain nonce of PartyB for signature verification.\\n```\\nFile: LiquidationFacetImpl.sol\\n    function liquidatePartyB(\\n..SNIP..\\n        LibMuon.verifyPartyBUpnl(upnlSig, partyB, partyA);\\n```\\n
In most protocols, whether an account is liquidatable is determined on-chain, and this issue will not surface. However, the architecture of Symmetrical protocol relies on off-chain and on-chain components to determine if an account is liquidatable, which can introduce a number of race conditions such as the one mentioned in this report.\\nConsider reviewing the impact of malicious users attempting to increment the nonce in order to block certain actions in the protocols since most functions rely on the fact that the on-chain nonce must be in sync with the signature's nonce and update the architecture/contracts of the protocol accordingly.
PartyA can block their accounts from being liquidated by liquidators. With the ability to liquidate the insolvent PartyA, the unrealized profits of all PartyBs cannot be realized, and thus they will not be able to withdraw the profits.\\nPartyA could also exploit this issue to block their account from being liquidated to:\\nWait for their positions to recover to reduce their losses\\nBuy time to obtain funds from elsewhere to inject into their accounts to bring the account back to a healthy level\\nSince this is a zero-sum game, the above-mentioned create unfairness to PartyB and reduce their profits.\\nThe impact is the same for the blocking of PartyB liquidation.
```\\nFile: LiquidationFacetImpl.sol\\n    function liquidatePartyA(address partyA, SingleUpnlSig memory upnlSig) internal {\\n        MAStorage.Layout storage maLayout = MAStorage.layout();\\n\\n        LibMuon.verifyPartyAUpnl(upnlSig, partyA);\\n        int256 availableBalance = LibAccount.partyAAvailableBalanceForLiquidation(\\n            upnlSig.upnl,\\n            partyA\\n        );\\n        require(availableBalance < 0, "LiquidationFacet: PartyA is solvent");\\n        maLayout.liquidationStatus[partyA] = true;\\n        maLayout.liquidationTimestamp[partyA] = upnlSig.timestamp;\\n        AccountStorage.layout().liquidators[partyA].push(msg.sender);\\n    }\\n```\\n