# Malicious PartyB can block unfavorable close position requests causing a loss of profits for PartyB

PartyB resets quote.modifyTimestamp by partially filling dust close amounts, perpetually blocking PartyA's forceClosePosition cooldown and denying profit-taking.

- Payout: Contest reward
- Severity: medium
- Program: Symmetrical
- Credited: Kose
- Disclosed: 2023-06-05
- Write-up quality: 6/10
- Original: https://github.com/sherlock-audit/2023-06-symmetrical-judging/issues/224
- Library page: https://bugbountylibrary.com/r/sherlock%3A2023-06-symmetrical%3AM-11
- Tags: domain:web3 impact:funds-loss kind:contest platform:sherlock sev:medium tech:solidity technique:source-review vuln:accounting-error vuln:business-logic vuln:dos

**Target:** symmio-core PartyA/PartyB facets (forceClosePosition, fillCloseRequest)
**Root cause:** forceClosePosition gates on quote.modifyTimestamp, which closeQuote resets to block.timestamp on every partial fill; PartyB can dust-fill LIMIT close requests to perpetually restart the cooldown.
**Steps:**
1. PartyA calls `requestToClosePosition` with LIMIT order -> status CLOSE_PENDING
2. PartyB calls `fillCloseRequest(quoteId, filledAmount=1, closedPrice, upnlSig)` with minimal filledAmount
3. `LibQuote.closeQuote` sets `quote.modifyTimestamp = block.timestamp`
4. Repeat dust fills before `forceCloseCooldown` elapses so `block.timestamp > quote.modifyTimestamp + forceCloseCooldown` never holds
5. PartyA's `forceClosePosition` reverts with 'Cooldown not reached' indefinitely
**How found:** Code reading of forceClosePosition's cooldown check against modifyTimestamp, then tracing that closeQuote (and ~17 other functions) mutate modifyTimestamp, and noting LIMIT allows partial fills while MARKET does not.
**Exploitation:** Malicious PartyB, when a close is unfavorable, repeatedly submits minimal partial fills on the LIMIT close request to reset modifyTimestamp, preventing PartyA from ever force-closing and locking in PartyA's unrealized losses/profits denial.
**Escalation:** MARKET close orders cannot be force-closed, so PartyA must use LIMIT, which is exactly the order type PartyB can dust-fill — removing the backup path entirely.
**Insight:** When a cooldown/deadline gate reuses a generic 'last modified' timestamp that any counterparty-triggerable state change updates, the counterparty can reset the timer; look for a dedicated request timestamp instead.
