# Some offers can't be cancelled

RubiconMarket fails to override SimpleMarket's offer(), so offers created via that API are never inserted into _rank/_near and cannot be cancelled.

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

**Target:** RubiconMarket / SimpleMarket Solidity contract offer and cancel functions
**Root cause:** RubiconMarket overrides cancel() but not offer(); the inherited SimpleMarket offer() path skips insertion into the _rank linked list and _near unsorted list, so the overridden cancel() cannot locate the offer.
**Steps:**
1. Call `market.offer(90e6, TUSDC, 100e18, TEST, address(this), owner)` via the inherited SimpleMarket offer signature.
2. Offer is created but never inserted into `_rank` or `_near`.
3. Call `market.cancel(id)`; `isOfferSorted` returns false and `_hide` returns false.
4. Require check fails with `can't hide`, reverting cancellation.
**How found:** Code reading: noticed RubiconMarket overrides cancel() but not offer(), then traced that the inherited offer() path never inserts into _rank/_near, which the overridden cancel() depends on.
**Exploitation:** Any user creating an offer through the non-overridden SimpleMarket offer() API is permanently unable to cancel it, leaving funds locked in the offer.
**Insight:** When a child contract overrides a state-mutating function (cancel) but not the paired creation function (offer), check that all creation paths populate the same data structures the override reads.
