# Closing partial positions miscounts the settled fees

Partial position close double-divides already-prorated settled fees in settledMargin math, letting traders extract extra value by splitting closes.

- Payout: Contest reward
- Severity: high
- Program: Elfi Protocol
- Credited: mstpr-brainbot
- Disclosed: 2024-05-09
- Write-up quality: 7/10
- Original: https://github.com/sherlock-audit/2024-05-elfi-protocol-judging/issues/37
- Library page: https://bugbountylibrary.com/r/sherlock%3A2024-05-elfi-protocol%3AH-6
- Tags: domain:web3 impact:funds-loss kind:contest platform:sherlock sev:high tech:solidity technique:source-review vuln:accounting-error vuln:business-logic vuln:precision-loss

**Target:** DecreasePositionProcess.sol _updateDecreasePosition (perp DEX)
**Root cause:** In the partial-close branch, settled fees are prorated by decreaseQty/qty into settledFundingFeeInUsd/settledBorrowingFeeInUsd, but _getPosFee(cache) is then multiplied again by decreaseIntQty/positionIntQty inside the settledMargin computation, shrinking fees twice.
**Steps:**
1. Open a BTC LONG 5x $1000 margin position at $25k.
2. Mine blocks to accrue borrowing/funding fees.
3. Submit a DECREASE order for qty/2 at $27.5k and execute via oracle.
4. Close remaining qty in a second DECREASE order.
5. Compare final accountInfo to a single full close: two-part close yields 13825113546993371n vs 13721368330375054n, i.e. higher balance.
**How found:** Code reading of the partial-close else branch: noticed settled fees were already divided by decreaseQty/qty into *_InUsd vars, then _getPosFee(cache) is divided again by decreaseIntQty/positionIntQty in the settledMargin formula, while initialMarginInUsd and pnlInUsd are not yet prorated.
**Exploitation:** Trader splits a close into partial closes so the double-divided fee term understates fees; when net fees are positive, partial closing is always more profitable than a single full close, draining value from the protocol/pool.
**Insight:** In perp/derivative accounting, audit every place a fee or PnL is prorated: check whether the same decreaseQty/qty ratio is applied twice across helper functions (_getPosFee) versus inline math, and diff partial-close vs full-close balances in a PoC.
