# OracleMaker's price with spread does not take into account the new position

OracleMaker's spread ignores incoming order size, letting traders open a reverse position first to bypass the dynamic premium and force oracle-price quotes.

- Payout: Contest reward
- Severity: medium
- Program: Perpetual
- Credited: IllIllI
- Disclosed: 2024-02-19
- Write-up quality: 6/10
- Original: https://github.com/sherlock-audit/2024-02-perpetual-judging/issues/25
- Library page: https://bugbountylibrary.com/r/sherlock%3A2024-02-perpetual%3AM-1
- Tags: domain:web3 impact:funds-loss kind:contest platform:sherlock sev:medium tech:evm tech:solidity technique:source-review vuln:business-logic

**Target:** OracleMaker.sol _getBasePriceWithSpread / fillOrder
**Root cause:** _getBasePriceWithSpread() computes spread only from the Maker's current position, ignoring the incoming order amount, so de-risking quotes use the raw oracle price regardless of size and crossing zero is mis-evaluated.
**Steps:**
1. Maker holds +1 ETH long position.
2. Alice sends order 1: 1 ETH short (-1 ETH) via relayer; Maker sees de-risking and quotes oracle price, ending at 0 ETH.
3. Alice sends order 2: 11 ETH long (+11 ETH); Maker at zero quotes oracle price.
4. Net Alice position +10 ETH long with no spread paid; Maker now -99 ETH short risk.
**How found:** Code review of fillOrder/_getBasePriceWithSpread noting the order amount parameter is unused in spread computation, then reasoning about the zero-crossing case where the Maker believes it de-risks but actually accumulates opposite exposure.
**Exploitation:** Trader submits two orders in quick succession to the trusted relayer: a small reverse order that de-risks the Maker (quoted at oracle price), then the intended larger order from a zero Maker position (also oracle price), netting the desired exposure while avoiding the dynamic premium.
**Insight:** When a market-maker quotes a spread based on current inventory, check whether the incoming order size is an input to the spread formula; if not, a two-order reverse-then-open sequence can reset inventory to zero and dodge the premium.
