Reproduced Exploit

Subsquid — Gateway creator can steal all tokens from the GatewayRegistry

1. Stake tokens into a gateway; after unlock, unstake them. 2. Unregister the gateway — Gateway struct deleted, stakes[] kept. 3. Re-register the same peerId — totalUnstaked resets to 0. 4. Unstake again against leftover stakes[] — pulls other depositors' tokens.

Jan 2024Otheruntagged3 min read

Chain

Other

Category

untagged

Date

Jan 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: 58244-c-01-gateway-creator-can-steal-all-tokens-from-the-gatewayre. Standalone Foundry PoC and full write-up: 58244-c-01-gateway-creator-can-steal-all-tokens-from-the-gatewayre_exp in the evm-hack-registry mirror.


Vulnerability classes: lockup · permanent · direct-drain · cross-contract-state-consistency

Reproduction: self-contained Foundry PoC with only forge-std — no fork. output.txt · test/58244-…sol.

AuditVault taxonomy: lang/solidity · platform/pashov · severity/high · impact/loss-of-funds/direct-drain · sector/bridge · genome: lockup · permanent · direct-drain · cross-contract-state-consistency


Key info#

ImpactHIGH — double-unstake drains other gateways' SQD from the shared registry balance
ProtocolSubsquid Network — GatewayRegistry
Vulnerable coderegister resets totalUnstaked: 0 while unregister never deletes stakes[]
Bug classStale stake array / accounting reset on re-register
FindingPashov Audit Group — Subsquid · #58244
ReportSubsquid-security-review.md
SourceAuditVault
Fixdelete stakes[peerIdHash] on unregister
Compiler^0.8.24 (PoC)
Reposubsquid/subsquid-network-contracts commit 3545236

TL;DR#

  1. Stake tokens into a gateway; after unlock, unstake them.
  2. Unregister the gateway — Gateway struct deleted, stakes[] kept.
  3. Re-register the same peerId — totalUnstaked resets to 0.
  4. Unstake again against leftover stakes[] — pulls other depositors' tokens.

Vulnerable code#

SOLIDITY
gateways[peerIdHash] = Gateway({
  // ...
  totalStaked: 0,
  totalUnstaked: 0 // @> VULN: reset without clearing stakes[]
});
SOLIDITY
// unregister deletes gateways[peerIdHash] but NOT stakes[peerIdHash]
return total - gateway.totalUnstaked; // recomputes from stale stakes

Root cause#

Two stores track the same economic reality (stakes[] amounts vs totalUnstaked). Unregister only clears one; re-register resets the other to zero, so _unstakeable overstates unlockable funds.

Preconditions#

  • Operator can register/unregister a peerId.
  • At least one mature stake entry exists for that peerId.
  • Registry holds other users' tokens (shared ERC20 balance).

Attack walkthrough#

  1. Bob stakes 100 SQD; Alice stakes 100 SQD (registry = 200).
  2. Alice unstakes 100, unregisters, re-registers same peerId.
  3. Alice unstakes 100 again → registry balance 0; Alice holds 200.

Diagrams#

sequenceDiagram participant Bob participant Alice participant GR as GatewayRegistry Bob->>GR: stake 100 Alice->>GR: stake 100 Note over GR: balance 200 Alice->>GR: unstake 100 Alice->>GR: unregister Note over GR: stakes array still has Alice entry Alice->>GR: register same peerId Note over GR: totalUnstaked = 0 Alice->>GR: unstake 100 again Note over GR: balance 0 Bob drained

Impact#

Any gateway operator can drain the entire registry balance after one legitimate stake/unstake cycle on a recycled peerId.

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.