All incidents

Aerodrome V6 Unauthorized Reward Harvest via Forged Depositor Assignment

Share
Mar 05, 2026 09:04 UTCAttackLoss: 199.93 AEROManually checked16 exploit txWindow: 4h 51m
Estimated Impact
199.93 AERO
Label
Attack
Exploit Tx
16
Addresses
1
Attack Window
4h 51m
Mar 05, 2026 09:04 UTC → Mar 05, 2026 13:55 UTC

Exploit Transactions

TX 1Base
0xdd8039634e6fc44d1d770bbb9644b34d26908fd867aed0e3453dedc8ad575c7e
Mar 05, 2026 09:04 UTCExplorer
TX 2Base
0x035937a401b7e7a760391e3559d03f8d9c011625fac3c63eef0545e4790df65e
Mar 05, 2026 09:26 UTCExplorer
TX 3Base
0x953abdb832952697d7b33ff6f8720d82fe2683979169eb5250c8a0d3d8506839
Mar 05, 2026 09:28 UTCExplorer
TX 4Base
0xdfc28bb357348a2f152f6564d8063b1e769782d00d84f4045c7eb1c77da5bac8
Mar 05, 2026 09:45 UTCExplorer
TX 5Base
0x63113ffa41566078382c2b6cc221340da5c2fbe08871756a00c66f3f69057154
Mar 05, 2026 10:19 UTCExplorer
TX 6Base
0x09fd2056f0712262bae72569180cfc0119a997bbddd0f8bdf8580b30ee526bf3
Mar 05, 2026 10:32 UTCExplorer
TX 7Base
0xb401c2b5ee9ad4f874f83c8b8f0ba33cd001c3c85d107fdc65250fccd5ac9964
Mar 05, 2026 10:55 UTCExplorer
TX 8Base
0x11b118096f6531790079c7c758c8be048f4b539dba33bc09c52c7e265f9e8c02
Mar 05, 2026 11:15 UTCExplorer
TX 9Base
0x1f3bcd3705c31c6c2e102c233b28608b4e7de6e8a936966b6945cd3560aefff5
Mar 05, 2026 11:35 UTCExplorer
TX 10Base
0xe7cb648e9032a671d13037eb03a2a4f005e9409c0b22de125e231c1063abf621
Mar 05, 2026 11:51 UTCExplorer
TX 11Base
0xd7eb812ab0c094b9963ca834fdd37281b988fa31665fe0b801106dfb3be64721
Mar 05, 2026 12:11 UTCExplorer
TX 12Base
0x86d156040d50dcefab6226139f8232a32d3995c826f280b3f116f52e9e749541
Mar 05, 2026 12:35 UTCExplorer
TX 13Base
0xf12a0756c9021ac77af6119cf240e7a9e45c39eb6259b457217852a8e4ad5ef0
Mar 05, 2026 12:55 UTCExplorer
TX 14Base
0xa7beff52308c2718d13f5c7c86c64553e30f6f74862a115b24f6093214871ce3
Mar 05, 2026 13:15 UTCExplorer
TX 15Base
0x5f9b35d9888ad28f48dd8500367742db1878654d9eaab9b5f4a1f42a7746c506
Mar 05, 2026 13:35 UTCExplorer
TX 16Base
0x6525084589a2668513ca9fb64791e51cbc0629b1b35a6c87ff06a3ca562286d3
Mar 05, 2026 13:55 UTCExplorer

Victim Addresses

0xeb2bd37d47c98d7739b4606eaeffc46f1e519babBase

Loss Breakdown

199.93AERO

Similar Incidents

Root Cause Analysis

Aerodrome V6 Unauthorized Reward Harvest via Forged Depositor Assignment

1. Incident Overview TL;DR

An unprivileged actor on Base exploited Aerodrome CL Position Manager V6 (0xeb2bd37d47c98d7739b4606eaeffc46f1e519bab) by forging depositor ownership for existing position tokenIds, then harvesting gauge rewards to an attacker-controlled recipient.

The critical flaw is authorization coupling: batchHarvest trusts depositors[tokenId], while depositUnstaked allows writing depositors[tokenId] through an attacker-controlled pool -> nft() resolution path. A spoofed NFPM can satisfy safeTransferFrom without proving canonical NFT custody.

This was repeatedly realized across adversary-crafted transactions until the protocol owner paused V6. Observed total extracted value is 199931656475035207998 wei-AERO, credited to 0x1e221ee4abcf419872e71ea403e9a7ca52b784f5.

2. Key Background

Aerodrome V6 uses depositor state as an authorization primitive for reward harvesting.

  • depositors[tokenId] is a security-critical mapping.
  • _resolveNFPM(pool) resolves NFT manager as ICLPool(pool).nft().
  • batchHarvest checks only depositors[tokenId] == msg.sender (or owner override), then calls gauge getReward(tokenId).
  • Rewards (AERO) are forwarded to caller after harvesting.

Relevant victim-side code:

function depositUnstaked(address pool, uint256 tokenId) external whenNotPaused nonReentrant {
    if (pool == address(0)) revert InvalidPool();
    address nfpm = _resolveNFPM(pool);
    INonfungiblePositionManager(nfpm).safeTransferFrom(msg.sender, address(this), tokenId);
    depositors[tokenId] = msg.sender;
    isStaked[tokenId] = false;
    positionPools[tokenId] = pool;
    emit DepositedUnstaked(pool, msg.sender, tokenId, nfpm);
}

function batchHarvest(address[] calldata pools, uint256[] calldata tokenIds) external whenNotPaused nonReentrant {
    for (uint256 i = 0; i < pools.length; i++) {
        if (depositors[tokenIds[i]] != msg.sender && owner() != msg.sender) revert Unauthorized();
        ICLGauge(_resolveGauge(pools[i])).getReward(tokenIds[i]);
    }
    ...
}

function _resolveNFPM(address pool) internal view returns (address) {
    address nfpm = ICLPool(pool).nft();
    if (nfpm == address(0)) revert InvalidPool();
    return nfpm;
}

3. Vulnerability Analysis & Root Cause Summary

Root cause category: ATTACK.

The protocol invariant should be: only canonical NFPM custody transfer can establish depositor authorization for a position. In V6, this invariant is broken because depositor assignment is reachable via a user-supplied pool whose nft() result is trusted.

An attacker deploys helper contracts that impersonate pool/NFPM behavior and returns attacker-controlled addresses through nft(). V6 then invokes safeTransferFrom on that attacker-controlled contract. Because there is no canonical binding check between supplied pool/NFPM and the real position owner, state writes proceed: depositors[tokenId] = attacker and positionPools[tokenId] = suppliedPool.

After overwrite, batchHarvest authorization is satisfied by attacker-controlled mapping state, allowing harvest over real target pools/tokenIds and transfer of AERO to attacker-selected recipient.

Code-level breakpoint:

  • Write primitive: depositUnstaked(pool, tokenId) state update to depositors[tokenId].
  • Abuse point: batchHarvest(...) authorization check against overwritten mapping.

4. Detailed Root Cause Analysis

4.1 Deterministic exploit mechanism

Representative exploit transaction 0x953abdb832952697d7b33ff6f8720d82fe2683979169eb5250c8a0d3d8506839 shows forged depositor assignment followed by harvest:

AerodromeCLPositionManagerV6::depositUnstaked(0x2ccDEDEbb20098141c91A83725A22b4EB72628b8, 55023230)
  0x2ccDE...::nft() -> 0x2ccDE...
  0x2ccDE...::safeTransferFrom(...)
  emit DepositedUnstaked(pool: 0x2ccDE..., depositor: 0x2ccDE..., tokenId: 55023230, nfpm: 0x2ccDE...)

AerodromeCLPositionManagerV6::batchHarvest([...pools...], [...tokenIds...])
  ... getReward(...) repeated across target gauges ...

The helper decompile for 0xb32de53dc70228880c9cedf107d2271accfe527b also shows direct invocation of V6 selectors:

  • 0xa8a59a64 (depositUnstaked(address,uint256))
  • 0xa5eaea2e (batchHarvest(address[],uint256[]))
(bool success, bytes memory ret0) = address(0xeb2bd...19bab).Unresolved_a8a59a64(var_n); // call
...
(bool success, bytes memory ret0) = address(0xeb2bd...19bab).Unresolved_a5eaea2e(var_i, var_s, var_n, var_o); // call

4.2 State-diff confirmation of authorization overwrite

State diff for 0x63113ffa41566078382c2b6cc221340da5c2fbe08871756a00c66f3f69057154 shows V6 depositor-related slots rewritten from prior values (often 0x2ccded...) to new attacker helper (0xb32de53...), proving attacker-controlled reassignment across multiple tokenIds:

slot 0x0cffbb18...: 0x...2ccdedebb20098141c91a83725a22b4eb72628b8 -> 0x...b32de53dc70228880c9cedf107d2271accfe527b
slot 0x16724184...: 0x...2ccdedebb20098141c91a83725a22b4eb72628b8 -> 0x...b32de53dc70228880c9cedf107d2271accfe527b
slot 0x20236063...: 0x...2ccdedebb20098141c91a83725a22b4eb72628b8 -> 0x...b32de53dc70228880c9cedf107d2271accfe527b
slot 0x4387a588...: 0x...2ccdedebb20098141c91a83725a22b4eb72628b8 -> 0x...b32de53dc70228880c9cedf107d2271accfe527b

4.3 Mitigation and failed replay

Pause transaction 0xeba22027756c7d090722dfd88b58dcc26722ed9c017d1331602785a901472638 emitted pause event on V6. Subsequent replay attempt 0x6525084589a2668513ca9fb64791e51cbc0629b1b35a6c87ff06a3ca562286d3 reverted on first depositUnstaked call with 0xd93c0665 (EnforcedPause()).

5. Adversary Flow Analysis

5.1 Adversary-related accounts

  • EOA executor: 0x0000e83906facc4132c520403ae99ee0ab8feaa7
  • Helper contracts: 0x2ccdedebb20098141c91a83725a22b4eb72628b8, 0xb32de53dc70228880c9cedf107d2271accfe527b
  • Profit recipient: 0x1e221ee4abcf419872e71ea403e9a7ca52b784f5

Victim-side protocol/token components:

  • Aerodrome V6 manager: 0xeb2bd37d47c98d7739b4606eaeffc46f1e519bab
  • AERO token: 0x940181a94a35a4569e4529a3cdfb74e38fd98631

5.2 Lifecycle stages with concrete transactions

  1. Helper deployment/priming:
  • 0xdd8039634e6fc44d1d770bbb9644b34d26908fd867aed0e3453dedc8ad575c7e (block 42956055)
  • 0xdfc28bb357348a2f152f6564d8063b1e769782d00d84f4045c7eb1c77da5bac8 (block 42957298)
  1. Depositor overwrite and reward extraction (representative):
  • 0x953abdb832952697d7b33ff6f8720d82fe2683979169eb5250c8a0d3d8506839 (block 42956775)
  • 0x5f9b35d9888ad28f48dd8500367742db1878654d9eaab9b5f4a1f42a7746c506 (block 42964189)
  1. Mitigation and failed replay:
  • 0xeba22027756c7d090722dfd88b58dcc26722ed9c017d1331602785a901472638 (block 42964272)
  • 0x6525084589a2668513ca9fb64791e51cbc0629b1b35a6c87ff06a3ca562286d3 (block 42964798)

5.3 Full relevant transaction set

Seed/related plus adversary-crafted set:

  • seed: 0x6c581fb9d552075e07d4c9f544a971b81d7b14d5a50064e38839fb5a45cfa338
  • adversary-crafted: 0xdd8039634e6fc44d1d770bbb9644b34d26908fd867aed0e3453dedc8ad575c7e, 0x035937a401b7e7a760391e3559d03f8d9c011625fac3c63eef0545e4790df65e, 0x953abdb832952697d7b33ff6f8720d82fe2683979169eb5250c8a0d3d8506839, 0xdfc28bb357348a2f152f6564d8063b1e769782d00d84f4045c7eb1c77da5bac8, 0x63113ffa41566078382c2b6cc221340da5c2fbe08871756a00c66f3f69057154, 0x09fd2056f0712262bae72569180cfc0119a997bbddd0f8bdf8580b30ee526bf3, 0xb401c2b5ee9ad4f874f83c8b8f0ba33cd001c3c85d107fdc65250fccd5ac9964, 0x11b118096f6531790079c7c758c8be048f4b539dba33bc09c52c7e265f9e8c02, 0x1f3bcd3705c31c6c2e102c233b28608b4e7de6e8a936966b6945cd3560aefff5, 0xe7cb648e9032a671d13037eb03a2a4f005e9409c0b22de125e231c1063abf621, 0xd7eb812ab0c094b9963ca834fdd37281b988fa31665fe0b801106dfb3be64721, 0x86d156040d50dcefab6226139f8232a32d3995c826f280b3f116f52e9e749541, 0xf12a0756c9021ac77af6119cf240e7a9e45c39eb6259b457217852a8e4ad5ef0, 0xa7beff52308c2718d13f5c7c86c64553e30f6f74862a115b24f6093214871ce3, 0x5f9b35d9888ad28f48dd8500367742db1878654d9eaab9b5f4a1f42a7746c506, 0x6525084589a2668513ca9fb64791e51cbc0629b1b35a6c87ff06a3ca562286d3
  • related mitigation: 0xeba22027756c7d090722dfd88b58dcc26722ed9c017d1331602785a901472638

6. Impact & Losses

Measured on-chain loss (token flow):

  • AERO: 199931656475035207998 wei (18 decimals)

Observed behavior:

  • Rewards were redirected from at least 17 holder addresses to attacker recipient 0x1e221ee4abcf419872e71ea403e9a7ca52b784f5.
  • Representative credited deltas to attacker recipient include:
    • +15412603354802695460 wei-AERO (tx 0x953abd...)
    • +14790754003241337582 wei-AERO (tx 0x5f9b35...)

Deterministic fee accounting (for context, not AERO-denominated predicate):

  • Sum over adversary-crafted tx receipts: Sigma(gasUsed * effectiveGasPrice) = 15545487842576235 wei ETH (0.015545487842576236 ETH).

7. References

[1] Aerodrome V6 source (depositUnstaked, batchHarvest, _resolveNFPM): /workspace/session/artifacts/collector/iter_2/contract/8453/0xeb2bd37d47c98d7739b4606eaeffc46f1e519bab/source/forge_clone/src/AerodromeCLPositionManagerV6.sol

[2] Representative exploit trace: /workspace/session/artifacts/collector/iter_2/tx/8453/0x5f9b35d9888ad28f48dd8500367742db1878654d9eaab9b5f4a1f42a7746c506/trace.calltracer.json

[3] Storage overwrite state diff: /workspace/session/artifacts/collector/iter_2/tx/8453/0x63113ffa41566078382c2b6cc221340da5c2fbe08871756a00c66f3f69057154/state_diff.prestate_tracer_diff.json

[4] V6 storage layout: /workspace/session/artifacts/collector/iter_2/contract/8453/0xeb2bd37d47c98d7739b4606eaeffc46f1e519bab/source/forge_clone/out/AerodromeCLPositionManagerV6.sol/AerodromeCLPositionManagerV6.json

[5] Helper decompile (0xb32de53...): /workspace/session/artifacts/collector/iter_2/contract/8453/0xb32de53dc70228880c9cedf107d2271accfe527b/decompile/0xb32de53dc70228880c9cedf107d2271accfe527b-decompiled.sol

[6] Helper decompile (0x2ccded...): /workspace/session/artifacts/collector/iter_2/contract/8453/0x2ccdedebb20098141c91a83725a22b4eb72628b8/decompile/0x2ccdedebb20098141c91a83725a22b4eb72628b8-decompiled.sol

[7] Exploit balance diffs: /workspace/session/artifacts/collector/iter_2/tx/8453

[8] Pause receipt: /workspace/session/artifacts/collector/iter_2/tx/8453/0xeba22027756c7d090722dfd88b58dcc26722ed9c017d1331602785a901472638/receipt.json

[9] Collector summary (coverage and artifact quality): /workspace/session/artifacts/collector/data_collection_summary.json