# Losses of some long traders can eat into the margins of others

Flatmoney's global PnL aggregation lets one underwater long's bad debt drain other longs' margins, blocking their withdrawals.

- Payout: Contest reward
- Severity: medium
- Program: Flatmoney
- Credited: xiaoming90
- Disclosed: 2023-12-11
- Write-up quality: 7/10
- Original: https://github.com/sherlock-audit/2023-12-flatmoney-judging/issues/198
- Library page: https://bugbountylibrary.com/r/sherlock%3A2023-12-flatmoney%3AM-7
- Tags: domain:web3 impact:funds-loss kind:contest platform:sherlock sev:medium tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:liquidation

**Target:** FlatcoinVault.updateGlobalPositionData / perp long positions
**Root cause:** updateGlobalPositionData aggregates all longs' PnL into a single marginDepositedTotal, so one position's negative settled margin (bad debt) is subtracted from the shared pool instead of being borne by LPs, zeroing out solvent longs' margins.
**Steps:**
1. Set up Alice (size 6 ETH, margin 3 ETH) and Bob (size 6 ETH, margin 5 ETH) longs at $1000; stableCollateralTotal=12, marginDepositedTotal=8, sizeOpenedTotal=12.
2. Drop ETH price to $600; each position PnL = (6 * -400)/600 = -4 ETH.
3. Alice settleMargin = 3-4 = -1 ETH (underwater); Bob settleMargin = 5-4 = 1 ETH (solvent).
4. Trigger updateGlobalPositionData via liquidation/open/adjust/close: profitLossTotal = (12 * -400)/600 = -8 ETH.
5. newMarginDepositedTotal = 8 + 0 + (-8) = 0, wiping Bob's remaining 1 ETH margin.
6. Bob cannot withdraw his 1 ETH - liquidationMargin; LP collateral not debited for Alice's -1 ETH bad debt.
**How found:** Code-reading of updateGlobalPositionData: noticed profitLossTotal is computed over aggregate sizeOpenedTotal and subtracted from a shared marginDepositedTotal, so a single negative settled margin propagates to all longs rather than being isolated or charged to LPs.
**Exploitation:** Any liquidation or position update after a price drop that pushes one long underwater causes the shared marginDepositedTotal to absorb the bad debt, zeroing solvent longs' withdrawable margin; no attacker capital needed, triggered by normal protocol operations.
**Insight:** In perp/leverage protocols, check whether per-position bad debt is socialized into a shared aggregate margin pool instead of being isolated or charged to the LP/insurance side; construct a two-trader example where one is underwater and one solvent to expose cross-subsidy.
