# RubiconMarket checks slippage incorrectly

RubiconMarket sellAllAmount/buyAllAmount compare fill_amt to min_fill_amount before deducting fees, so users receive less than their slippage floor.

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

**Target:** RubiconMarket.sol sellAllAmount/buyAllAmount
**Root cause:** fill_amt accumulates pre-fee amounts and is checked against min_fill_amount before calcAmountAfterFee is applied, so the enforced minimum is gross rather than net of fees.
**Steps:**
1. Call `sellAllAmount(pay_gem, pay_amt, buy_gem, min_fill_amount)` with a min_fill_amount equal to the desired net output.
2. Loop fills offers accumulating gross `fill_amt`.
3. `require(fill_amt >= min_fill_amount)` passes on gross amount.
4. `fill_amt = calcAmountAfterFee(fill_amt)` then reduces the actual received amount below min_fill_amount.
**How found:** Code reading of sellAllAmount: noticed fill_amt is accumulated from offer pay_amt and the slippage require precedes the calcAmountAfterFee call at the end of the function.
**Exploitation:** A user setting min_fill_amount to their true desired net output has the check satisfied by the pre-fee total, then receives less after fees are subtracted, incurring unintended slippage loss.
**Insight:** When auditing slippage/min-out guards, verify the compared value is the same post-fee, post-transfer amount the user actually receives; check ordering of fee deduction relative to require statements.
