Reproduced Exploit

Multipli: Reported yield instantly reprices shares, so a same-block sandwich siphons the LP's yield

Jan 1970Otheruntagged3 min read

Chain

Other

Category

untagged

Date

Jan 1970

Source

AuditVault

EVM Playground

Source-level debugger — step opcodes and Solidity in sync

evm-hack-analyzer

The attack is replayed in an in-browser EVM preloaded with the exact dumped fork state. The execution tree shows every call; step by Solidity line or by opcode across all depths — source, Stack, Memory, Storage, Balances (native / ERC-20 / NFT), Transient storage and Return value stay in sync. Click a tree node, opcode, or source line to jump. No backend, no live RPC.

Loading fork state…

Source & credit. Reproduction of a public audit finding curated by AuditVault — the original finding: 58701-h-01-attackers-can-exploit-yield-distribution-through-onunde. The historical source/toolchain is unavailable; this entry is documentation only and claims no executable Forge PoC.


Vulnerability classes: vuln/erc4626 · vuln/same-block-sandwich · vuln/yield-theft

Reproduction: a faithful minimal reproduction of the vulnerable finding — the vulnerable function is reproduced verbatim (marked @>) with faithful minimal doubles; local deploy, no fork.

Root cause#

onUnderlyingBalanceUpdate sets aggregatedUnderlyingBalances = newAggregatedBalance immediately (line 114), so totalAssets() jumps in one block; line 117 then reprices every share on that inflated total. An attacker who deposits right before the update and redeems right after captures part of the yield that belonged to existing long-term depositors — halving the honest LP's return.

SOLIDITY
        require(block.number > lastBlockUpdated, "UpdateAlreadyCompletedInThisBlock");

        emit UnderlyingBalanceUpdated(aggregatedUnderlyingBalances, newAggregatedBalance);
        aggregatedUnderlyingBalances = newAggregatedBalance; // @> reported yield instantly inflates totalAssets() -> current shareholders (incl. a just-deposited attacker) reprice up in the same block

Why it's exploitable here#

  • The reported yield is credited to aggregatedUnderlyingBalances instantly, repricing every existing share the same block.
  • An attacker who front-runs the update with a deposit is treated as a shareholder at update time.
  • Redeeming immediately after pays the attacker on the inflated ratio, diluting the honest LP's return by half.

Attack path#

flowchart TD A["Attacker deposits right before the yield update"] --> B["Strategy reports yield → onUnderlyingBalanceUpdate"] B --> C["totalAssets() inflated instantly (same block)"] C --> D["All shares reprice up — incl. attacker's"] D --> E["Attacker redeems at the inflated ratio"] E --> F["100 of 200 yield siphoned from the LP"]

Marked-line walkthrough (Playground)#

The EVM Playground pins each step to the exact executed source line in MultipliVault:

  1. Line 93 — deposit() computes shares = convertToShares(assets) on the assets:supply ratio BEFORE the yield is reported.
  2. Line 117VULN. onUnderlyingBalanceUpdate credits the reported yield instantly (line 114); this line immediately reprices every share via the inflated totalAssets() — including the just-deposited attacker's.
  3. Line 101 — redeem()'s convertToAssets pays the attacker more than deposited, siphoning part of the existing depositors' yield.

PoC#

Registry (Foundry, local deploy — exploit path + a fixed-variant control):

BASH
cd 58701-h-01-attackers-can-exploit-yield-distribution-through-onun_exp
forge test -vv

Expected: both tests PASS — the exploit test sandwiches the yield update and asserts 100 of 200 yield is siphoned from the LP; the fixed (vesting) vault yields the attacker nothing. The browser EVM Playground is served at /hacks/58701-h-01-attackers-can-exploit-yield-distribution-through-onun/.

Remediation#

Stream/vest the reported yield over time (or snapshot pre-update shares) so a same-block deposit cannot capture yield it did not earn.

References#


Sources & further analysis#

Reproductions & code

Alerts & third-party analyses

These dashboards index community alerts tweets, post-mortems, and independent write-ups. Reach them through the protocol name above to cross-check this reproduction against other analyses.