Reproduced Exploit
YieldFi YToken: wrong `owner` (`msg.sender`) passed to `Manager.redeem` in delegated withdrawals
Chain
Other
Category
untagged
Date
Apr 2025
Source
AuditVault
EVM Playground
Source-level debugger — step opcodes and Solidity in sync
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.
Source & credit. Reproduction of a public audit finding curated by AuditVault — the original finding: 55538-incorrect-owner-passed-to-managerredeem-in-ytoken-withdrawal. Standalone Foundry PoC and full write-up: 55538-incorrect-owner-passed-to-managerredeem-in-ytoken-withdrawal_exp in the
evm-hack-registrymirror.
Protocol: YieldFi (v2.0) · Auditor: Cyfrin (Immeas) · Severity: High
AuditVault: #55538 · Report: Cyfrin YieldFi v2.0
Vulnerable source: contracts/core/tokens/YToken.sol — _withdraw (L161-L172) (same in YTokenL2.sol)
Fix commit: adbb6fb (owner now passed to manager.redeem)
Provenance#
The audited repo YieldFiLabs/contracts@40caad6c was deleted (no fork, no
mirror, Wayback 404). The exploit path uses real source where recoverable:
src/yieldfi/YToken.sol— the_withdrawbody is verbatim from the Cyfrin report; the base is the real OpenZeppelinERC4626(v4.9.6) whose_withdrawis the exact allowance-spend point the audited override matches, plus YieldFi's realAccessbase (adapted to non-upgradeableReentrancyGuard).Administrator(roles/blacklist/pause registry) andManagerare minimal, faithful stand-ins for the deleted YieldFi contracts — they implement exactly theIRole/IBlackList/IPausablesurfaceAccessqueries and theredeem(...)entry point_withdrawcalls. Neither is the finding's subject.
Root cause#
YToken defers withdrawals to a central Manager. Third parties may withdraw on
a user's behalf with an allowance. But _withdraw spends the owner's
allowance yet tells the Manager the redeemer is msg.sender:
function _withdraw(address caller, address receiver, address owner, uint256 assets, uint256 shares)
internal override nonReentrant notPaused {
require(receiver != address(0) && owner != address(0) && assets > 0 && shares > 0, "!valid");
require(!IBlackList(administrator).isBlackListed(caller) && !IBlackList(administrator).isBlackListed(receiver), "blacklisted");
if (caller != owner) { _spendAllowance(owner, caller, shares); }
// @audit msg.sender passed as owner (should be `owner`)
IManager(manager).redeem(msg.sender, address(this), asset(), shares, receiver, address(0), "");
}
When the Manager executes the order it burns msg.sender's shares, not the
owner's. So a delegated redemption either reverts (caller holds no shares) or
burns the wrong account's tokens (caller happens to hold shares), while the
owner's allowance is consumed for nothing.
Reproduction#
test/…_exp.sol (registry, [PASS]):
test_wrongUsersTokensBurned— victim holds 100 shares, u1 holds 50 and is approved for 50. u1 redeems on victim's behalf → u1's own 50 shares are burned (50 → 0), victim's 100 are untouched, and victim's allowance is spent.test_thirdPartyWithdrawalReverts— u1 holds 0 shares; the delegated redeem reverts"!balance"— the exact failure the report's PoC observes.test_control_fixedBurnsCorrectOwner— passingowner(the fix) burns victim's 50 shares and leaves u1's intact.
_shared/run-poc/run_poc.sh 55538-incorrect-owner-passed-to-managerredeem-in-ytoken-withdrawal_exp -vvvvv
Fix#
Pass owner (not msg.sender) to manager.redeem in both YToken._withdraw
and YTokenL2._withdraw (fix commit adbb6fb).
Sources & further analysis#
Reproductions & code
- Standalone PoC + full trace: 55538-incorrect-owner-passed-to-managerredeem-in-ytoken-withdrawal_exp (evm-hack-registry mirror).
- AuditVault finding: 55538-incorrect-owner-passed-to-managerredeem-in-ytoken-withdrawal.
- Upstream DeFiHackLabs PoC directory: src/test.
Alerts & third-party analyses
- DeFiHackLabs incident explorer: search "YieldFi YToken: wrong
owner(msg.sender) passed toManager.redeemin delegated withdrawals". - Web3Sec X hacked database: search.
- Rekt leaderboard: search.
- Solodit incident search: search.
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.