Reproduced Exploit

Common Pool — signature omits nonce/expiry and can be reused

1. Signed digest is keccak256(abi.encode(DEPOSIT_STRUCT, multicall/amount)) only. 2. sig.nonce and sig.expiry are checked but not bound into the digest. 3. Observer re-submits the same signature bytes with nonce = orderNonce → second allocate succeeds. 4. HARM: pool inventory (2×1000e8) drained wit…

Jul 2024Othersignature3 min read

Chain

Other

Category

signature

Date

Jul 2024

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: 52006-signature-does-not-take-all-parameters-into-account-and-can. Standalone Foundry PoC and full write-up: 52006-signature-does-not-take-all-parameters-into-account-and-can_exp in the evm-hack-registry mirror.


Vulnerability classes: vuln/signature/incomplete-scope · vuln/auth/replay · genome: signature-replay · direct-drain

Reproduction: self-contained Foundry PoC with only forge-std. Full trace: output.txt. PoC: test/52006-signature-does-not-take-all-parameters-into-account-and-can_exp.sol.

AuditVault taxonomy: lang/solidity · platform/halborn · has/github · has/poc · severity/high · sector/vault · genome: signature-replay · direct-drain · access-roles · permit-fork-replay · timestamp-dependence


Key info#

ImpactHIGH — anyone can replay a used allocateFunds signature with a fresh nonce and re-trigger deposits/withdrawals against the pool
ProtocolCommon Pool / RFX
Vulnerable codecheckAllReports / payload hash — signs only multicall data, not sig.nonce or sig.expiry
Bug classIncomplete signature domain / replay
FindingHalborn — RFX Common Pool · #52006
Reporthalborn.com/audits/rfx-exchange/common-pool
SourceAuditVault
StatusAudit finding — fixed by removing signature auth in favor of access control. Local synthetic PoC.
Compiler^0.8.24 (PoC)

TL;DR#

  1. Signed digest is keccak256(abi.encode(DEPOSIT_STRUCT, multicall/amount)) only.
  2. sig.nonce and sig.expiry are checked but not bound into the digest.
  3. Observer re-submits the same signature bytes with nonce = orderNonce → second allocate succeeds.
  4. HARM: pool inventory (2×1000e8) drained with one signature.

The vulnerable code#

SOLIDITY
bytes32 input = keccak256(abi.encode(keccak256(bytes(DEPOSIT_STRUCT)), amount)); // @> VULN
// FIX: also encode sig.nonce and sig.expiry into input before signing/verifying
checkReport(sig, input, orderNonce);

Root cause#

Anti-replay fields exist in the struct and are validated against live state, but because they are outside the signed message an attacker can freely rewrite them to match the current epoch.

Preconditions#

  • An approved signer has produced at least one valid allocateFunds signature (visible on-chain).
  • Pool still holds inventory for another deposit of the same payload size.

Attack walkthrough#

  1. Legitimate allocate with nonce 0 moves 1000e8 BTC to the market; orderNonce = 1.
  2. Attacker copies signature bytes, sets nonce = 1, resubmits.
  3. Recovery still succeeds; second 1000e8 leaves the pool.
  4. HARM: double allocation from a single authorization.

Diagrams#

sequenceDiagram participant Signer participant Pool as CommonPool participant Attacker participant Market Signer->>Pool: allocateFunds sig nonce=0 Pool->>Market: transfer 1000e8 Note over Pool: orderNonce = 1 Attacker->>Pool: same sig bytes nonce=1 Pool->>Market: transfer 1000e8 again Note over Pool: signature still verifies #59; nonce not in digest

Impact#

Unauthorized re-allocation of pool funds; anyone can force deposits/withdrawals matching previously signed payloads.

Sources#


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.