Reproduced Exploit

Kinetiq — `receive()` re-stakes Core-returned HYPE and bricks confirmWithdrawal

1. On HyperEVM, HYPE is the native gas token. Undelegations from Hypercore arrive as native ETH-like transfers to StakingManager. 2. receive() external payable { stake(); } immediately re-stakes any incoming HYPE and forwards it back to Core, minting kHYPE to the sender. 3. After a user queues a wi…

Apr 2025Otheraccounting3 min read

Chain

Other

Category

accounting

Date

Apr 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: 58555-h-03-mishandling-of-receiving-hype-in-the-stakingmanager-use. Standalone Foundry PoC and full write-up: 58555-h-03-mishandling-of-receiving-hype-in-the-stakingmanager-use_exp in the evm-hack-registry mirror.


Vulnerability classes: vuln/accounting/reward-accounting · vuln/logic/state-update · vuln/liveness/withdrawal-brick

Reproduction: a self-contained Foundry PoC that compiles & runs in an isolated project with only forge-std — no fork, no RPC, no anvil_state. Full trace: output.txt. PoC: test/58555-h-03-mishandling-of-receiving-hype-in-the-stakingmanager-use_exp.sol.

AuditVault taxonomy: severity/high · sector/oracle · sector/staking · sector/token · platform/code4rena · reward-accounting · logic/state-update · data-corruption/accounting-error · known-pattern · always · redesign-logic · blast-radius/protocol-wide


Key info#

ImpactHIGH — Core-returned HYPE is auto-staked; users cannot confirmWithdrawal; spurious kHYPE mint to system inflates exchange accounting
ProtocolKinetiq — StakingManager on HyperEVM
Vulnerable codeStakingManager.receive — unconditionally calls stake() (StakingManager.sol#L208-L211)
Bug classNative receive handler re-enters deposit path (withdrawal funds re-staked)
FindingCode4rena 2025-04-kinetiq · #58555 · reporter FalseGenius
Reportcode4rena.com/reports/2025-04-kinetiq
SourceAuditVault
StatusAudit finding — acknowledged by Kinetiq. Reproduced as a standalone local PoC.
Compiler^0.8.24 (PoC)

TL;DR#

  1. On HyperEVM, HYPE is the native gas token. Undelegations from Hypercore arrive as native ETH-like transfers to StakingManager.
  2. receive() external payable { stake(); } immediately re-stakes any incoming HYPE and forwards it back to Core, minting kHYPE to the sender.
  3. After a user queues a withdrawal, Core returns the undelegated HYPE — but it is re-staked, so the manager balance stays 0.
  4. confirmWithdrawal requires address(this).balance >= pending and reverts. The user is stuck.
  5. Spurious kHYPE is minted to the system address; totalStaked grows again → exchange-ratio inflation. Fix: skip stake() when msg.sender == systemAddress.

The vulnerable code#

SOLIDITY
receive() external payable {
    // Simply call the stake function
    stake(); // @> VULN
    // FIX: if (msg.sender != systemAddress) { stake(); }
}

Root cause#

receive() treats every native credit as a user deposit. Withdrawal returns and validator rewards from Core are not user deposits — they are liquidity the manager must hold to pay confirmWithdrawal. Auto-staking them empties the balance the withdrawal path needs and mints unbacked kHYPE to whoever sent the ETH (Core/system).

Preconditions#

  • targetBuffer = 0 (simplest; with buffer the user may still confirm but ratio still inflates).
  • User has queued a withdrawal; operator has undelegated on L1; Core pushes HYPE back.

Attack walkthrough#

  1. User stakes 1 HYPE → forwarded to Core; manager balance 0.
  2. User queues full withdrawal (kHYPE burned, pending = 1e18).
  3. Core pushTo(manager, 1e18)receive()stake() → HYPE re-forwarded to Core; manager balance still 0; system receives 1e18 spurious kHYPE.
  4. confirmWithdrawal reverts (insufficient HYPE). User funds stuck; accounting inflated.

Diagrams#

sequenceDiagram participant User participant Manager as StakingManager participant Core as SystemCore User->>Manager: stake 1 HYPE Manager->>Core: forward 1 HYPE User->>Manager: queueWithdrawal Core->>Manager: push 1 HYPE back Note over Manager: receive calls stake Manager->>Core: re-forward 1 HYPE User->>Manager: confirmWithdrawal Manager-->>User: revert insufficient HYPE

Impact#

Withdrawal confirmations fail whenever Core returns HYPE through the native receive path. Users cannot exit. Spurious kHYPE mint + re-counted stake distorts the HYPE/kHYPE exchange ratio protocol-wide. The same path fires for validator rewards sent to the manager.

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.