Synchronization problem: how the Verus protocol lost $7.5M due to differences between blockchains

Synchronization problem: how the Verus protocol lost $7.5M due to differences between blockchains

The attack did not require compromising keys or hacking validators — the attacker exploited the way two different blockchains interpreted notarization confirmations. We explain why legitimate notary signatures became part of one of the most unusual attacks on cross-chain bridges.

Aug 3, 2026

Duplicate malicious records with a substituted state root were added to fully legitimate notarization records. These records were signed by Verus notaries and then passed to Ethereum, where they replaced the genuine trusted state root. Having gained control over this value, the attacker was able to submit a fake import proof through the bridge, which allowed far more funds to be withdrawn than were actually sent — even though the original export amounted to just 0.01 VRSC.

What a notarization is

Such a confirmation contains:

  • the blockchain or currency identifier;
  • the notarization height;
  • one or more proof roots (proofRoots), including:
  • the network identifier;
  • the block height;
  • the state (state/proof) root;
  • the block hash;
  • the accumulated computing power;
  • currency and converter-state information;
  • a reference to the previous notarization;
  • the hash of the previous cross-chain notarization;
  • node and initiator information.

Proof roots are formed from the public data of the Verus and Ethereum blockchains. Any user can create and submit a notarization candidate, but the network will accept it only if consensus requirements are met and the correct UTXO of the previous notarization chain is used.

Notary signatures (CNotarySignature) are part of the CNotaryEvidence structure and are published openly. This allowed the attacker to obtain these signatures and reuse them.

Attack timeline (UTC)

The attackers prepared carefully for the hack and operated over the course of two days.

How the attack unfolded: four stages

The entire hack can be broken down into four key stages.

1. Substituting the notarization on the Verus network

The first transaction used the previous confirmed output of the notarization chain (4f4f…:1) and created a new one (0c247…:0). Although the block explorer interface showed only two legitimate records, additional records with fake state roots were covertly embedded inside the serialized data.

The reason lay in the specifics of data processing. Verus first read the list of roots as an array and then moved it into a Map structure. This allowed the attacker to create two consecutive transactions, each of which additionally contained several hidden malicious records with substituted state roots.

2. Substituting the state root on Ethereum

After that, the attacker waited for the notaries' software to verify the correct first records. Then 11 notary nodes signed the notarization in full, including the hidden duplicate records with malicious data, which the Verus system effectively ignored.

The resulting signatures were included in the CNotaryEvidence structure. Next, through the Verus RPC interface, the attacker obtained these signatures and then constructed a call to the setLatestData() function on Ethereum.

On the Ethereum side, the attacker acted merely as a relay: they copied the notarization's byte data along with the legitimate notary signatures and passed them to the smart contract.

During execution of the deserializeNotarization() function, the Ethereum contract processed the proofRoots array sequentially. In doing so, each record with the Verus system identifier overwrote the stateRoot value:

  • the first record — the real state root;
  • the second — Ethereum data;
  • the third — a malicious state root;
  • the fourth — malicious again;
  • the fifth — also malicious.

As a result, the last record fully replaced the genuine trusted state root. It was this fake state root that was subsequently used to verify the fraudulent transfer proof through the bridge.

3. Preparing the export via Verus

Then the attacker created a perfectly ordinary cross-chain transfer request. In transaction 5b5043febfd7f7c089e976d11d0f87a904881266bb96dd118b3d69b0e02aab52, a new address initiated an export of just 0.01 VRSC, paying a fee of around 12 units via Bridge.vETH.

After that, the request was processed by the converter, and LuckPool formed a batch export in a separate transaction. It was this fully legitimate request that later became the basis for constructing the fake proof.

In particular, the following parameters were used:

  • hashtransfers: 440787f9114dbb41b7d3d6f6c48980d51221f62ef0a33613d1d305b98ae85053
  • sourceheightstart: 4162638
  • sourceheightend: 4162847

4. Fake import and withdrawal via Ethereum

In the final stage, the attacker called the submitImports() function. In the 14-field CCE structure, only a few key parameters were changed. The hashtransfers field was completely falsified so as to match the withdrawal transactions.

In addition:

  • the numInputs value was changed to 8;
  • firstInput — to 0;
  • the totalAmounts, totalFees, and totalBurned fields were absent entirely.

Part of the proof remained original. In particular, the following real values were used:

  • the transaction identifier (TxID);
  • the first node of the proof tree (First node);
  • the general parameters of the proof format, versions, and system identifiers.

All other elements were artificially generated. Because the malicious state root had already been registered by Ethereum as trusted, the resulting proof passed verification successfully, despite the absence of a corresponding amount of funds in the original transfer.

Where the vulnerability lay: Verus and Ethereum read the data differently

Verus treated the serialized records as a structure in which duplicate elements were effectively ignored after the array was converted into a Map.

Ethereum, by contrast, processed all records sequentially, so each subsequent record could overwrite the state root value.

As a result, the Verus notaries signed data they considered fully correct, yet Ethereum interpreted the same bytes differently and ultimately stored, as its trusted state root, a value entirely controlled by the attacker.

Once Ethereum recognized this fake state root as valid, any import proof built on it was treated by the system as legitimate.

An additional factor was a logic error in the Ethereum bridge contract. The contract did not check whether the amount specified in the import request matched the volume of assets actually exported from the Verus network.

It was enough to simply construct a fake hashtransfers parameter matching the withdrawal transactions to successfully pass the CCE structure check.

Movement of the stolen funds: 2,778 ETH through Tornado Cash

Flow of funds stolen from the Verus protocol. Visualization: Certik
Flow of funds stolen from the Verus protocol. Visualization: Certik

After successfully exploiting the vulnerability, the attacker swapped the stolen assets for 2,778.8662 ETH via Relay, then moved the proceeds into the Tornado Cash anonymization service.

#Hack
A $7.5M mistake: what the Verus protocol developers overlooked