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…
Chain
Other
Category
signature
Date
Jul 2024
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: 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-registrymirror.
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#
| Impact | HIGH — anyone can replay a used allocateFunds signature with a fresh nonce and re-trigger deposits/withdrawals against the pool |
| Protocol | Common Pool / RFX |
| Vulnerable code | checkAllReports / payload hash — signs only multicall data, not sig.nonce or sig.expiry |
| Bug class | Incomplete signature domain / replay |
| Finding | Halborn — RFX Common Pool · #52006 |
| Report | halborn.com/audits/rfx-exchange/common-pool |
| Source | AuditVault |
| Status | Audit finding — fixed by removing signature auth in favor of access control. Local synthetic PoC. |
| Compiler | ^0.8.24 (PoC) |
TL;DR#
- Signed digest is
keccak256(abi.encode(DEPOSIT_STRUCT, multicall/amount))only. sig.nonceandsig.expiryare checked but not bound into the digest.- Observer re-submits the same signature bytes with
nonce = orderNonce→ second allocate succeeds. - HARM: pool inventory (2×1000e8) drained with one signature.
The vulnerable code#
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
allocateFundssignature (visible on-chain). - Pool still holds inventory for another deposit of the same payload size.
Attack walkthrough#
- Legitimate allocate with nonce 0 moves 1000e8 BTC to the market;
orderNonce = 1. - Attacker copies signature bytes, sets
nonce = 1, resubmits. - Recovery still succeeds; second 1000e8 leaves the pool.
- HARM: double allocation from a single authorization.
Diagrams#
Impact#
Unauthorized re-allocation of pool funds; anyone can force deposits/withdrawals matching previously signed payloads.
Sources#
- AuditVault finding #52006
- Halborn report — Common Pool
- Remediation discussion: relative-finance/common-pool#22
Sources & further analysis#
Reproductions & code
- Standalone PoC + full trace: 52006-signature-does-not-take-all-parameters-into-account-and-can_exp (evm-hack-registry mirror).
- AuditVault finding: 52006-signature-does-not-take-all-parameters-into-account-and-can.
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.