ZkLink Nova Exploit: A Stale Transient Hash Forged a Root

At precisely 22:21:35 UTC on October 28, 2026, during Ethereum block 26,294,188, the decentralized ecosystem witnessed a high-precision security breach that completely emptied the Ethereum escrow contracts of zkLink Nova, a prominent aggregated rollup network. The perpetrator executed a single, highly calculated transaction that systematically bypassed the platform’s security mechanisms, making away with a total haul valued between $743,000 and $805,000, depending on the price feeds utilized. According to post-mortem analyses conducted by leading blockchain security firms BlockSec Phalcon and SlowMist, the loot comprised 22.43 native Ethereum (ETH) alongside 11 distinct ERC-20 tokens, heavily dominated by liquid restaking assets led by roughly 245.74 pufETH.
What makes this particular exploit notable in the annals of decentralized finance (DeFi) security is the complete absence of traditional attack vectors: no administrative private keys were compromised, and no cryptographic signatures were forged. Instead, the attacker leveraged two minute, interconnected design oversights within a single contract component—an uncleaned transient-storage hash and an overly permissive privileged function. By manipulating these logic gaps, the malicious actor successfully authored their own fraudulent Merkle root directly into the bridge, subsequently draining the protocol’s liquidity pools against proofs they had generated themselves.
Understanding the Mechanics of zkLink Nova Batch Roots
To contextualize the vulnerability, one must first examine how zkLink Nova manages cross-chain communication and state verification. Layer 2-to-Layer 1 communication relies heavily on escrows that store specific Merkle roots corresponding to individual message log batches. A user attempting to execute a withdrawal on Layer 1 must present a valid Merkle proof that mathematically matches the stored root for that specific batch. Consequently, any entity possessing the capability to write a root into the system effectively gains the authority to approve and finalize arbitrary withdrawals.
However, these crucial roots do not arrive at the settlement layer via direct, unverified channels. Instead, they traverse a multi-hop relay chain originating from Layer 2 networks and passing through various messaging services before settling on Ethereum. Within this framework, every sequential hop implicitly trusts the preceding hop strictly through verification of the msg.sender global variable. This architecture creates a delicate chain of trust, which is only as robust as the central Arbitrator contract’s absolute guarantee that it will never forward a payload it did not genuinely receive from an authorized source.
Anatomy of the Exploit: Two Critical Flaws in the Claim Message
Public code repositories for zkLink’s EVM contracts reveal that the core vulnerability centered around the claimMessage function. Designed as an external, payable, and non-reentrant function restricted only to authorized relayer addresses, its signature immediately highlighted potential architectural risks:
function claimMessage(
address _sourceChainCanonicalMessageService,
bytes calldata _sourceChainClaimCallData,
IL1Gateway _sourceChainL1Gateway,
uint256 _receiveValue,
bytes calldata _receiveCallData,
bytes calldata _forwardParams
) external payable nonReentrant onlyRelayer whenNotPaused
The first structural vulnerability stemmed from an arbitrary call executed with a trusted identity. Within claimMessage, the contract executes a low-level call via Address.functionCall(_sourceChainCanonicalMessageService, _sourceChainClaimCallData). Crucially, both the target address and the payload calldata are supplied entirely by the external caller. Because the execution originates from the Arbitrator contract itself, any callee receiving this external call observes msg.sender == Arbitrator—the exact identity trusted implicitly by every gateway’s onlyArbitrator security modifier.
Consequently, if an attacker configured the canonical message service parameter to point directly to the EthereumGateway itself, and wrapped a syncBatchRoot instruction inside the sendMessage calldata, all internal access control checks would successfully pass. The gateway would be duped into believing the Arbitrator had genuinely requested a root forward, while the broader zkLink system assumed its legitimate gateway had delivered authentic data.
The second and fatal flaw involved a validation hash that fundamentally outlived its intended operational scope. The sole defense mechanism preventing an arbitrary call from establishing a forged root was a validation check executed immediately following the external call:
bytes32 _finalizeMessageHash;
assembly _finalizeMessageHash := tload(finalizeMessageHash.slot)
require(
_finalizeMessageHash ==
keccak256(abi.encode(_sourceChainL1Gateway, _receiveValue, _receiveCallData)),
"Incorrect finalize data"
);
This validation variable, finalizeMessageHash, leverages Ethereum’s EIP-1153 transient storage standard, which was written by the receiveMessage function whenever a registered gateway successfully delivered a legitimate message. Unlike standard storage, transient storage persists across the entire lifecycle of a transaction rather than being scoped exclusively to a single call frame. Because the Arbitrator contract failed to clear or reset this storage slot following the validation check, its semantic meaning was dangerously weakened.
Rather than affirming that "a genuine message delivery occurred during this specific claim," the check effectively stated that "a genuine message delivery with these exact parameters occurred at some point earlier within this identical transaction." Once a single legitimate claim initialized and armed the storage slot, any subsequent claim executed within the same multi-call transaction could effortlessly bypass the validation check by simply replicating the gateway, value, and calldata parameters—even if the accompanying external call delivered absolutely nothing. The inclusion of standard reentrancy guards offered no protection, as the malicious sequence consisted of sequential calls originating from the attacker’s custom smart contract rather than nested execution frames.
Chronology and Execution of the Attack Sequence
Security analytics teams from both BlockSec Phalcon and SlowMist reconstructed the exact transaction flow, revealing a multi-step attack executed entirely within a single transaction originating from an externally owned account (EOA) and directed toward a custom-built attack contract.
The operation commenced with Step 1: Arming the Hash With a Genuine Message. The attacker initiated the sequence by invoking the public SyncL2TxHashRelayer to process a legitimate, pending Linea message designed to synchronize two separate Layer 2 transaction hashes. The Linea bridge successfully validated the proof, prompting the Linea gateway to call back into the Arbitrator, which populated finalizeMessageHash with the hash of the authentic message. While the legitimate message was forwarded and processed normally, the transient storage slot remained armed.
With the security mechanism primed, the attacker proceeded to Step 2: Smuggling a Root Update. In the same transaction, the attacker called the relayer a second time. This time, the canonical message service was designated as the EthereumGateway, and the calldata payload contained a sendMessage instruction wrapping syncBatchRoot(116409, attackerChosenRoot, 0). Because the caller was recognized as the Arbitrator, the EthereumGateway accepted the payload, and zkLink formally stored the attacker-generated root for batch 116409.
Step 3 involved Passing Validation via the Stale Hash. Because the EthereumGateway never triggered a callback into receiveMessage during this second phase, the transient storage slot remained untouched. By supplying identical gateway parameters, values, and calldata matching the initial legitimate transaction, the recomputed hash matched the stale transient value, allowing the forged root to pass validation successfully.
Finally, in Step 4, the attacker executed withdrawals against the forged root. Because zkLink’s finalization process for withdrawals is entirely permissionless and relies exclusively on stored batch roots, the attacker submitted 12 custom-crafted withdrawal proofs built entirely against their malicious root. This included one native ETH withdrawal directly from the zkLink escrow and eleven token withdrawals sourced from the L1ERC20Bridge, with every destination address set to the attacker’s EOA.
Transaction receipts confirmed substantial outflows from the bridge, led by 245.7379 pufETH, 18,113.45 USDC, 12.5693 ezETH, 6.8665 rsETH, 6.2998 STONE, 3,360.90 USDT, 2.6372 mstETH, 2.4826 mswETH, 0.5000 rswETH, 0.4660 wstETH, and 0.1736 WBTC. Combined with 22.43 ETH drained directly from the main escrow, liquid restaking tokens accounted for the vast majority of the financial impact.
Wider Industry Ramifications and Subsequent Waves
Following the initial breach on Ethereum, the crisis escalated. BlockSec Phalcon identified subsequent attack transactions targeting zkLink Nova deployments across alternative Layer 2 networks. zkLink issued an official statement at 09:06 UTC on October 29 confirming an active exploit impacting the Arbitrator contract across both Ethereum and Optimism.
Independent analysis by Parapet Labs attributed a secondary wave of exploitation—occurring at approximately 07:16 UTC on October 29—to a distinct malicious actor. This secondary wave allegedly extracted an additional 24.76 ETH alongside various token balances from escrow deployments on Optimism, Base, Blast, and Mantle, though these secondary figures await formal independent verification.
In response to the unfolding crisis, zkLink instituted an emergency protocol response, offering a 20% white-hat bounty for the safe return of all stolen funds. By 13:08 UTC on October 29, block production on the Nova rollup was officially suspended, affected contracts were patched under emergency measures, and withdrawal functionalities were temporarily halted. Industry analysts noted a critical operational oversight during the incident: while several secondary chains had been paused earlier in 2025 to restrict deposits, their respective withdrawal finalization functions had been left active, inadvertently leaving escrowed funds vulnerable to extraction even on supposedly paused networks.
Lessons for Smart Contract Builders and Security Auditors
The zkLink Nova incident serves as a stark reminder of the complex security assumptions underpinning modern cross-chain bridge architectures. Security researchers have repeatedly emphasized core defensive principles to prevent similar systemic failures:
- Consume Transient Flags Immediately: Because EIP-1153 transient storage variables persist across the entire transaction lifecycle, state flags denoting authentication or authorization must be explicitly cleared using
tstore(slot, 0)immediately following validation. - Restrict Privileged Identities from Executing Arbitrary Calls: Contracts that rely on
msg.sender == address(this)for authorization must never permit external callers to arbitrarily define target addresses and execution payloads, as this directly introduces privilege escalation vectors. - Enforce Strict Ordering of Validation and Execution: Security checks must always precede state-changing operations and external calls. Validating inputs after external executions mimic reentrancy vulnerabilities and open doors to logical bypasses.
- Treat Permissionless Relayers as Public Attack Surfaces: Whitelisting a relayer address provides zero security if the relayer blindly forwards unmodified, untrusted user parameters to critical protocol functions.
- Ensure Comprehensive Emergency Pauses: Operational emergency stops must encompass both deposit mechanisms and withdrawal finalization routines to ensure escrowed capital cannot be siphoned during an active threat response.
- Rigorously Test Multi-Call Transaction Scenarios: Automated fuzzing harnesses and test suites must simulate complex, multi-call transactions where attackers interleave legitimate and malicious inputs within a single execution block, ensuring stale transient data cannot be exploited across sequential operations.
As decentralized protocols continue to adopt advanced Ethereum storage standards like transient memory, developers must recognize that temporary storage primitives alter traditional execution boundaries. Without rigorous state cleanup and strict access control enforcement, a single authenticated message can easily become the key that unlocks an entire ecosystem’s treasury.





