# Calling Position._marketSell function compares fill_amt that includes fee to min_fill_amount that does not include fee

Rubicon Position._marketSell passes a fee-exclusive minFill to sellAllAmount, which compares it against a fee-inclusive fill_amt, making slippage protection ineffective.

- Payout: Contest reward
- Severity: medium
- Program: Rubicon
- Credited: rbserver
- Disclosed: 2025-02-17
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2023-04-rubicon-findings/issues/899
- Library page: https://bugbountylibrary.com/r/c4%3A2023-04-rubicon%3AM-15
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:business-logic

**Target:** Solidity leverage Position contract / RubiconMarket.sellAllAmount
**Root cause:** Position._marketSell computes _minFill without fee and passes it as min_fill_amount, but RubiconMarket.sellAllAmount compares it against fill_amt that still includes the fee before calcAmountAfterFee is applied.
**Steps:**
1. Call Position.closePosition which invokes _marketSell(_asset,_quote,_minFill).
2. _marketSell computes _fee from _minFill and _payAmount, then calls rubiconMarket.sellAllAmount(_asset,_payAmount,_quote,_minFill) with fee-exclusive _minFill.
3. sellAllAmount accumulates fill_amt including fee and executes `require(fill_amt >= min_fill_amount)` before `fill_amt = calcAmountAfterFee(fill_amt)`.
4. Observe logs: min_fill_amount=5625001, fill_amt including fee=5625057, fill_amt after fee=5625001 — the require passes trivially.
**How found:** Code reading of _marketSell and sellAllAmount revealed the fee is added to fill_amt but not to min_fill_amount; a Hardhat test with console.logs confirmed fill_amt (with fee) > min_fill_amount while fill_amt after fee equals min_fill_amount.
**Exploitation:** Slippage guard is effectively bypassed: a seller can be filled at a worse price than intended because the fee-inclusive fill_amt always exceeds the fee-exclusive min_fill_amount, allowing unfavorable fills up to the fee amount.
**Insight:** When auditing slippage checks, verify the units/denomination of both sides of the require — here one side includes protocol fee and the other does not, silently widening the accepted slippage by the fee amount.
