# The Furnace#melt() is vulnerable to sandwich attacks

Furnace.melt() payout step lets attackers flashloan-sandwich or issue just before payout to capture RToken appreciation meant for long-term holders.

- Payout: Contest reward
- Severity: medium
- Program: Reserve
- Credited: wait
- Disclosed: 2023-04-27
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2023-01-reserve-findings/issues/258
- Library page: https://bugbountylibrary.com/r/c4%3A2023-01-reserve%3AM-15
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:chained vuln:business-logic vuln:flash-loan vuln:oracle-manipulation

**Target:** Furnace.melt() / RToken issue-redeem pricing
**Root cause:** melt() raises the RToken basket rate in a single discrete step at payout, so issue/redeem prices jump instantly rather than accruing continuously, letting anyone positioned just before the step capture the appreciation.
**Steps:**
1. Compute next payout block from Furnace (lastPayout + period).
2. Flashloan inputFund, swap for RToken on a DEX at pre-melt price.
3. Call RToken.redeem() which invokes Furnace.melt() first, raising basket rate, then redeems at higher value.
4. Swap part of outputFund back to repay flashloan; remainder is profit.
5. Alternative: call RToken.issue() 1..n blocks before payout block, then redeem() at payout block for outsized APR.
**How found:** Warden observed melt() applies appreciation as a discrete step at payout and that redeem() calls melt() before pricing, so a position taken just before the step captures the jump; reasoned that DEX and issue/redeem prices are arbitrage-equal, making the sandwich profitable.
**Exploitation:** Attacker flashloans capital, buys RToken cheaply before the payout block, triggers melt() via redeem() to lift the basket rate, redeems at the higher rate, repays loan and keeps the delta; or simply issues shortly before payout and redeems at payout to harvest a full period's yield.
**Insight:** When a yield/rebase accrual is applied as a discrete step inside a user-triggered function (melt() called first in redeem()), the step itself is the MEV surface: check whether entering just before the step and exiting after captures the accrual, and whether the accrual should be time-weighted instead.
