Reproduced Exploit

Remora — `buyTokenOCP` signatures reusable forever (missing nonce)

1. buyTokenOCP verifies an EIP-712-style BuyToken(investor, token, amount) signature and skips on-chain payment. 2. The hash omits a nonce and nothing marks the digest as used. 3. The same signature is submitted N times → N free token purchases. 4. HARM in the PoC: one signature buys 5 inventory to…

Oct 2025Othersignature2 min read

Chain

Other

Category

signature

Date

Oct 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: 63777-signatures-on-tokenbank-and-allowlist-can-be-reused-in-perpe. Standalone Foundry PoC and full write-up: 63777-signatures-on-tokenbank-and-allowlist-can-be-reused-in-perpe_exp in the evm-hack-registry mirror.


Vulnerability classes: vuln/signature/missing-nonce · vuln/auth/replay · vuln/logic/free-mint

Reproduction: self-contained Foundry PoC with only forge-std. Full trace: output.txt. PoC: test/63777-signatures-on-tokenbank-and-allowlist-can-be-reused-in-perpe_exp.sol.

AuditVault taxonomy: lang/solidity · platform/cyfrin · has/github · has/poc · severity/high · sector/perpetuals · sector/stable · genome: missing-modifier · role-bypass · permit-fork-replay


Key info#

ImpactHIGH — a single off-chain-payment signature can be replayed indefinitely to mint free tokens via buyTokenOCP
ProtocolRemora Dynamic Tokens
Vulnerable codeTokenBank.verifySignature — struct hash is (investor, token, amount) with no nonce / used-digest map
Bug classSignature replay (missing nonce)
FindingCyfrin — Remora Dynamic Tokens v2.1, 2025-10-22 · #63777 · reporter 0xStalin
ReportCyfrin Remora report
SourceAuditVault
StatusFixed at commit 4f73c1d. Local synthetic PoC.
Compiler^0.8.24 (PoC)

TL;DR#

  1. buyTokenOCP verifies an EIP-712-style BuyToken(investor, token, amount) signature and skips on-chain payment.
  2. The hash omits a nonce and nothing marks the digest as used.
  3. The same signature is submitted N times → N free token purchases.
  4. HARM in the PoC: one signature buys 5 inventory tokens.

The vulnerable code#

SOLIDITY
bytes32 structHash = keccak256(
    abi.encode(BUY_TOKEN_TYPEHASH, investor, token, amount)
); // @> VULN: no nonce

Fix: include and bump a per-investor nonce (or store used digests).


Root cause#

Off-chain-payment authorization is a pure function of static fields. Without a one-time nonce, each signature is a free mint coupon of unlimited use.


Preconditions#

  • A valid authorized-signer signature for (investor, token, amount).
  • Sufficient TokenBank inventory.

Attack walkthrough#

  1. Obtain one signed BuyToken for 1 unit.
  2. Call buyTokenOCP with that signature five times.
  3. Receive five free tokens; inventory is drained.

Diagrams#

flowchart LR SIG["One signed BuyToken coupon"] --> B1["buyTokenOCP #1"] SIG --> B2["buyTokenOCP #2"] SIG --> B3["buyTokenOCP #N"] B1 --> FREE["Free tokens"] B2 --> FREE B3 --> FREE

Impact#

Unbounded free mint of central tokens for the cost of a single off-chain signature. Same missing-nonce pattern on AllowList lets removed admins re-add themselves.


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.