Reproduced Exploit

CAP Labs — a same-block delegation takes 750 of 1000 RWD

Vault A already delegates 100 behind an agent. The repayment interest, 1000 RWD, sits on the delegation contract.

May 2025•Other•logic•3 min read

Chain

Other

Category

logic

Date

May 2025

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: 61538-reward-distribution-enables-front-running-attacks-and-reward. Standalone Foundry PoC and full write-up: 61538-reward-distribution-enables-front-running-attacks-and-reward_exp in the evm-hack-registry mirror.


Vulnerability classes: vuln/logic/reward-calculation · vuln/logic/missing-check

Reproduction: a self-contained Foundry PoC that compiles and runs offline with only forge-std — no fork and no RPC. Trace: output.txt. PoC: test/61538-reward-distribution-enables-front-running-attacks-and-reward_exp.sol.


Key info#

ImpactHIGH — vault B delegates in the repayment block and takes 750 of 1000 RWD from vault A
ProtocolCAP Labs Delegation
Vulnerable codedistribute pays pot * delegated[vault] / total with no time weight
Bug classReward share ignores how long the stake has been delegated
FindingTrail of Bits (Benjamin Samuels) — CAP Labs, May 2025 · id 61538
ReportTrail of Bits CAP Labs review
SourceAuditVault finding
StatusReproduced as a local delegation pot.
Compilersolc 0.8.27, cancun, via IR

TL;DR#

Vault A already delegates 100 behind an agent. The repayment interest, 1000 RWD, sits on the delegation contract.

Vault B delegates 300 and calls distribute in the same transaction. The pot is split by current delegation: A receives 250 RWD and B receives 750 RWD. B provided none of the backing before this block.

The control locks eligibility after A's deposit. B's later delegation is ignored. A receives the full 1000 RWD and B receives 0.

The vulnerable code#

SOLIDITY
// @> VULN: the share uses delegation at distribute time, including this block
uint256 pay = pot * delegated[vault] / base;
if (pay != 0) reward.transfer(vault, pay);

Preconditions#

  • Vault A is already delegated for 100.
  • 1000 RWD of interest is ready to distribute.
  • Vault B can delegate before distribute in the same block. No warp is required.

Attack walkthrough#

  1. Vault B delegates 300. Total delegation becomes 400.
  2. distribute reads the 1000 RWD balance.
  3. A is paid 1000 * 100 / 400 = 250.
  4. B is paid 1000 * 300 / 400 = 750.

Control: eligibility is frozen at A's 100 before B delegates. distributeTo(A) transfers 1000 RWD. B's balance stays 0.

Diagrams#

flowchart TD A["Vault A already delegates 100"] --> B["1000 RWD of interest is ready"] B --> C["Vault B delegates 300 in this block"] C --> D["distribute splits by the new total of 400"] D --> E["A receives 250 RWD"] E --> F["B receives 750 RWD"]

Impact#

Vault A, the existing backer, receives 250 RWD instead of the 1000 RWD interest. Vault B takes the other 750 RWD without having backed the loan before the repayment.

Remediation#

Exclude collateral delegated in the current epoch from the distribution, or pay from a checkpoint of delegation taken before the repayment.

Sources#

Taxonomy#

  • severity/high
  • vuln/logic/reward-calculation · vuln/logic/missing-check

Sources & further analysis#

Reproductions & code

Alerts & third-party analyses

  • 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.