Reproduced Exploit

CWBC — Arkouda.claimReward mints before rewardGenerationStartTime is set

Feb 2022•Other•logic•2 min read

Chain

Other

Category

logic

Date

Feb 2022

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: 56419-user-can-claim-rewards-before-the-start-zokyo-none-cwbc-mark. Standalone Foundry PoC and full write-up: 56419-user-can-claim-rewards-before-the-start-zokyo-none-cwbc-mark_exp in the evm-hack-registry mirror.


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

Reproduction: Local Foundry reproduction. rewardGenerationStartTime stays 0. No fork. Trace: output.txt.

Root cause#

rewardGenerationStartTime defaults to 0 and is written by a separate startRewardGeneration call. claimReward never rejects 0, so block.timestamp >= rewardGenerationStartTime is true before rewards are started. A holder whose NFT was acquired at timestamp 1, observed in the block at timestamp 1 + 10 days, mints 10 * BASE_REWARD = 100 ARK.

SOLIDITY
require(block.timestamp >= rewardGenerationStartTime, "before start");
// @> VULN:
lastReward = daysHeld * BASE_REWARD;

The block timestamp is set once for the whole transaction. run() does not warp.

Attack path#

flowchart TD A["NFT acquired at timestamp 1"] --> B["This block is 10 days later"] B --> C["rewardGenerationStartTime is still 0"] C --> D["timestamp >= 0 passes"] D --> E["claim multiplies 10 days by 10 ARK"] E --> F["100 ARK is minted before the start"]

PoC#

The exploit asserts the start time is still 0, lastDays is 10, and the mint is 100 ARK. Those 100 ARK are transferred to the holder.

The fixed claim reverts with "not started" and mints 0.

BASH
cd 56419-user-can-claim-rewards-before-the-start-zokyo-none-cwbc-mark_exp
forge test -vv

Remediation#

Require rewardGenerationStartTime != 0 before the timestamp comparison, and set the start once.

References#


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.