Reproduced Exploit
Paladin Valkyrie — recycled LP liquidity pays the reward token to the caller
transferFrom on the incentivized LP notifies the hook, which moves poolUserLiquidity from the holder to the recipient. Recycling that LP into the pool manager makes the manager the sole liquidity account. claim then pays the manager 100e18 of the reward token, a different token from the LP. A sweep…
Chain
Other
Category
logic
Date
Mar 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: 61562-rewards-can-be-stolen-when-incentivizederc20-tokens-are-recu. Standalone Foundry PoC and full write-up: 61562-rewards-can-be-stolen-when-incentivizederc20-tokens-are-recu_exp in the
evm-hack-registrymirror.
Vulnerability classes: vuln/logic/reward-calculation · vuln/logic/missing-check
Key info#
| Protocol | Paladin Valkyrie |
| Finding | Cyfrin, AuditVault 61562 |
| Vulnerable code | IncentivizedERC20.transferFrom → notifyTransfer |
| Harm | The caller claims 100e18 of the reward token. The LP holder is paid 0. |
| Chain | local synthetic |
TL;DR#
transferFrom on the incentivized LP notifies the hook, which moves poolUserLiquidity from the holder to the recipient. Recycling that LP into the pool manager makes the manager the sole liquidity account. claim then pays the manager 100e18 of the reward token, a different token from the LP. A sweep takes that balance to the caller. The control reverts when the recycled LP notifies, and the holder claims the 100e18.
The vulnerable code#
function transferFrom(address from, address to, uint256 amount) public override returns (bool) {
ITokenizedHook(hook).notifyTransfer(poolId, from, to, amount);
return super.transferFrom(from, to, amount);
}
poolUserLiquidity[id][from] -= amount;
// @> VULN: recycled IncentivizedERC20 liquidity is credited to `to`
poolUserLiquidity[id][to] += amount;
The fix rejects notifyTransfer when the caller is the incentivized LP.
Root cause#
Liquidity accounting follows the ERC20 transfer with no check that the token is an incentivized LP being parked on a contract that will not keep the rewards. Whoever can call claim for the new holder receives the reward token.
Preconditions#
The holder has the whole LP liquidity. The incentive contract holds 100e18 of a separate reward token. No timestamp warp. One block.
Attack walkthrough#
- 100e18 of RWD is deposited. The pot is not the LP token.
- The holder is credited with 100e18 of LP liquidity and approves the pool manager.
- The manager
transferFroms the LP.notifyTransfercredits the manager and zeroes the holder. claimpays 100e18 of RWD to the manager.- The caller sweeps it. The holder still holds 0 of the reward token.
Diagrams#
Impact#
The caller receives 100e18 of the reward token. The LP holder receives 0. The control rejects the recycled token, the liquidity stays with the holder, and the holder is paid the 100e18.
Remediation#
Reject notifyTransfer from the incentivized LP, or wrap that token before it is used as liquidity somewhere else.
How to reproduce#
cd 61562-rewards-can-be-stolen-when-incentivizederc20-tokens-are-recu_exp
forge test -vv
Sources#
- AuditVault finding: https://github.com/Auditware/AuditVault/blob/main/findings/61562-rewards-can-be-stolen-when-incentivizederc20-tokens-are-recu.md
- Cyfrin report: https://github.com/solodit/solodit_content/blob/main/reports/Cyfrin/2025-03-12-cyfrin-paladin-valkyrie-v2.0.md
- Vulnerable lines as quoted in that report:
IncentivizedERC20.transferFromand thepoolUserLiquiditymove inside the transfer notification.
Sources & further analysis#
Reproductions & code
- Standalone PoC + full trace: 61562-rewards-can-be-stolen-when-incentivizederc20-tokens-are-recu_exp (evm-hack-registry mirror).
- AuditVault finding: 61562-rewards-can-be-stolen-when-incentivizederc20-tokens-are-recu.
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.