# Fee inclusivity calculations are inaccurate in RubiconMarket

RubiconMarket's calcAmountAfterFee subtracts fees from the gross amount, so taker fees are recomputed on the reduced amount, leaving part of the intended spend unspent.

- Payout: Contest reward
- Severity: medium
- Program: Rubicon
- Credited: adriro
- Disclosed: 2025-02-17
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2023-04-rubicon-findings/issues/1312
- Library page: https://bugbountylibrary.com/r/c4%3A2023-04-rubicon%3AM-01
- 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 vuln:precision-loss

**Target:** RubiconMarket Solidity contract (buy / calcAmountAfterFee)
**Root cause:** calcAmountAfterFee subtracts protocol and maker fees computed on the full amount, but the buy function then recomputes fees on the already-reduced amount, so the total debited is less than the requested fee-inclusive amount.
**Steps:**
1. Alice makes offer: `market.make(USDC, BTC, 30000e18, 1e18)`
2. Bob approves BTC and calls `market.buy(id, 30000e18)`
3. buy computes `fee = mul(spend, feeBPS)/100000` and `mFee = mul(spend, makerFee())/100000` on the reduced spend from calcAmountAfterFee
4. Observe Bob retains ~0.000225 BTC unspent because fees were double-discounted
**How found:** Code review of the fee-inclusivity feature: noticed calcAmountAfterFee subtracts fees from the gross amount while buy recomputes fees on the net amount, producing a mismatch; verified with a Foundry PoC.
**Insight:** When a contract offers 'fee-inclusive' amounts, check whether the fee is computed once on the gross or recomputed on the net; the correct gross-up is amount/(1+fees), not amount minus fees.
