# Malicious user can control premium emissions to steal margin from other traders

Hubble AMM TWAP overweights last fill price, letting a trader push mark TWAP away from oracle TWAP and harvest premium emissions from counterparties' margin.

- Payout: Contest reward
- Severity: medium
- Program: Hubble Exchange
- Credited: dirk_y
- Disclosed: 2023-04-16
- Write-up quality: 7/10
- Original: https://github.com/sherlock-audit/2023-04-hubble-exchange-judging/issues/87
- Library page: https://bugbountylibrary.com/r/sherlock%3A2023-04-hubble-exchange%3AM-6
- Tags: domain:web3 impact:funds-loss kind:contest platform:sherlock sev:medium tech:evm tech:solidity technique:source-review vuln:business-logic vuln:oracle-manipulation

**Target:** Perpetual AMM funding/premium settlement (AMM.sol settleFunding/_calcTwap)
**Root cause:** Premium = markPriceTwap - oraclePrice, and _calcTwap returns the last fill price when no trade occurred in the prior period, giving outsized weight to a single uncapped fill. Fill size is not weighted, so a small order can set the TWAP.
**Steps:**
1. Set oracle price; fund Alice and Bob with margin for 100x MIN_SIZE.
2. Alice opens large long (90x MIN_SIZE) matched against Bob's short at oracle price.
3. Compute minPrice = price*(1e6 - maxOracleSpreadRatio)/1e6.
4. Each period near period end, Alice fills both sides (long+short) at minPrice with MIN_SIZE, keeping mark TWAP low vs oracle.
5. Warp past next funding time and call `orderBook.settleFunding()`; premium credited to Alice's long.
6. Repeat 100 periods; Alice's available margin grows from ~200410 to ~716442910.
**How found:** Code reading of settleFunding's premium formula and _calcTwap's fallback to lastPrice when no trade in the prior period; noticed fill size is not weighted and positions are uncapped, hypothesized a small fill could dominate TWAP and wrote a Foundry PoC.
**Exploitation:** Alice holds a large long, then repeatedly self-fills minimal-size long/short pairs at the minimum allowed price just before each period boundary so the mark TWAP stays below oracle TWAP. settleFunding pays her the positive premium, funded by counterparties' margin, while her net position/margin requirement is unchanged by the paired fills.
**Escalation:** Larger position and longer duration scale the stolen premium; self-matching both sides avoids increasing margin requirements.
**Insight:** When a TWAP falls back to 'last trade price' on inactivity and ignores fill size, a minimal self-matched fill at the spread boundary can pin the mark price; check whether premium/funding deltas exceed the taker fees of that minimal fill.
