# Users Can Drain Funds From MarginSwap By Making Undercollateralized Borrows If The Price Of A Token Has Moved More Than 10% Since The Last MarginSwap Borrow/Liquidation Involving Accounts Holding That Token.

Stale internal price oracle lets attackers take undercollateralized loans and drain MarginSwap when a token's Uniswap price moves >10% without a borrow/liquidation.

- Payout: Audit contest
- Severity: medium
- Program: Marginswap
- Disclosed: 2021-05-03
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2021-04-marginswap-findings/issues/67
- Library page: https://bugbountylibrary.com/r/c4%3A2021-04-marginswap%3AM-06
- Tags: area:web3 domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:evm tech:solidity vuln:business-logic vuln:oracle-manipulation

**Target:** Lending protocol internal price oracle / borrow logic
**Root cause:** Internal price oracle only updates on borrow/liquidation for accounts holding that token, so prices go stale; the UPDATE_MAX_PEG_AMOUNT threshold skips updates for large borrows, and the slow EMA lets stale prices persist.
**Steps:**
1. Wait until Uniswap price of a token moves >10% (liquidationThresholdPercent - 100) with no borrow/liquidation on MarginSwap for accounts holding it.
2. If price fell: deposit >UPDATE_MAX_PEG_AMOUNT worth of the token as collateral, borrow ether, sell ether for token on Uniswap, repeat with coolingOffPeriod blocks between lend and borrow.
3. If price rose: deposit ether as collateral, borrow the token (>UPDATE_MAX_PEG_AMOUNT worth), sell token for ether, repeat.
4. Bypass CoolingOffPeriod by splitting deposits/borrows across 20-block windows; deposits don't trigger oracle updates so pre-position collateral.
5. Keep borrows within contract's token balance to satisfy the global totalLending >= totalBorrowed check.
**How found:** Code review of the price oracle update conditions (getPriceFromAMM, UPDATE_MAX_PEG_AMOUNT), coolingOffPeriod, and registerBorrow global check, reasoning about stale-price scenarios for low-volume tokens.
**Exploitation:** Attacker loops borrow/sell cycles against the stale oracle, borrowing more than 100% of collateral's real value since MarginSwap prices the debt at ≤90% of market value, draining contract funds.
**Escalation:** Repeated looping across cooling-off windows and pre-positioned deposits amplify the drain; works even after UPDATE_MAX_PEG_AMOUNT fix due to slow EMA.
**Insight:** On-chain oracles that only refresh on user actions are exploitable for low-volume assets; check whether large trades skip the update threshold and whether the EMA converges slowly enough to leave a profitable window.

