Skip to content
Dark abstract cutaway of layered machined strata seen from a raised corner, a clean bored shaft passing untouched through a reinforced teal shutter lattice at the top and ending at a single red-lit cell with a missing retaining bracket deep in the oldest layer, a cropped gloved hand entering at the lower right
exploitsAugust 13, 20263 min read

Harmony's 4 Billion ONE Mint: The Replay Fix the Attacker Could Switch Off

Dmitry Serdyuk
Dmitry SerdyukCo-Founder & CDO

Updated on August 13, 2026

TL;DR

On August 12, 2026, an attacker minted roughly 4 billion ONE on Harmony, about 26% of the token's supply, by abusing the chain's cross-shard receipt path. Harmony asked exchanges to freeze the attacker's addresses at 05:25 UTC and 65 minutes after that request published a signed emergency release, v2026.1.1. That release contains exactly one change set: pull request #5101, "Cx receipt fixes". Read it and the mechanism is plain. Harmony's replay defense and its pre-staking quorum check both decided how strictly to behave based on the epoch carried inside the artifact being checked, and the chain is full of old headers from epochs where those rules were weaker. A defense that reads its own activation condition from the thing it is inspecting has already been switched off. Harmony has not published a postmortem, so the numbers below mix confirmed, reported and reconstructed. I have labeled which is which.


What Actually Happened on August 12?

Harmony is a sharded proof-of-stake layer 1. Money moves between its shards constantly, and on August 12 money started arriving on destination shards that had never left a source shard.

The timeline is unusually crisp, because every step is timestamped somewhere anyone can check:

Time (UTC, Aug 12 2026)EventSource
~01:42On-chain analyst Juiceberg posts that close to 4 billion ONE has been mintedTechTimes
~04:26Harmony confirms publicly and says it is working on a patch and rollback optionsTechTimes
05:25:28Harmony asks exchanges to block and freeze funds tracing to the attacker's addressesHarmony on X
06:10:19Branch cx-receipt-security-fixes-main opened as PR #5101created_at
06:22:31PR #5101 merged, 5 files changed, 137 insertionsmerged_at, changed_files, additions
06:30:21Signed mainnet release v2026.1.1 publishedpublished_at

Second-level timestamps and diff counts come from GitHub's REST API, not the rendered pages. Measured from the fix branch, the engineering took twenty minutes: twelve to merge, eight more to a signed binary. From the public freeze request, 65 minutes. From Juiceberg's first post, under five hours. Whatever else went wrong here, that part was fast and done in the open.

The money was already gone. Juiceberg tracked roughly 2.8 billion ONE moving to exchanges with about 115 million left on-chain, figures relayed by CryptoSlate and Decrypt. Harmony has confirmed neither. Treat them as one researcher's on-chain estimate.

Harmony paused its bridge, told validators to upgrade, and said it was "working on a patch and rollback options." A rollback would erase every transaction since the attack, honest ones included. None has been announced and no reversal point named.


What Is a Cross-Shard Receipt, and Why Can It Print Money?

A sharded chain splits state across parallel chains. Moving 100 ONE from shard 0 to shard 1 cannot be one atomic write, because no single validator set owns both sides. So the transfer splits in two. Shard 0 debits the sender and emits a receipt. Shard 1 later accepts a proof of that receipt and credits the recipient. Debit here, credit there, glued together by a proof.

In Harmony that proof is a CXReceiptsProof, carrying the receipts, a MerkleProof, the source block's Header, and the CommitSig and CommitBitmap validators signed over that header.

Two of those are load-bearing in a way that is easy to miss. The Header is authenticated: altering one byte invalidates the aggregate signature over it. The MerkleProof is a separate struct with its own copies of ShardID and BlockNum, and those copies are not covered by that signature.

The entire incident lives in that gap. Whatever a chain uses to decide "have I already honored this proof?" is its mint authority. Harmony pointed that decision at the unsigned copy.


The Root Cause: Two Checks That Asked the Proof How Strict to Be

PR #5101 closes two distinct paths. Both share a shape.

Path one: the spent marker was keyed off unauthenticated fields

When a destination shard applies a proof it writes a "spent" marker, so the receipt cannot be honored twice. Before the patch, IsSpent built that key like this:

shardID := cxp.MerkleProof.ShardID
blockNum := cxp.MerkleProof.BlockNum.Uint64()
if cxp.Header != nil && bc.Config().IsCXMerkleProofReplayFixEpoch(cxp.Header.Epoch()) {
    shardID = cxp.Header.ShardID()
    blockNum = cxp.Header.Number().Uint64()
}

By default a receipt's identity came from MerkleProof, the copy nobody signed. Only inside IsCXMerkleProofReplayFixEpoch did the code switch to the signed Header.

So: take a genuine, already-applied proof. Leave the header and signature untouched, since both must stay valid. Change MerkleProof.ShardID from 1 to 99 and MerkleProof.BlockNum from 42 to 9999. The signature still verifies, because it never covered those fields. The spent check looks up a key that was never written, finds nothing, and treats this as a fresh receipt. The credit is applied again. No debit occurs anywhere, because the debit happened once, honestly, on the source shard, possibly years ago.

Repeat. That is the infinite mint.

Harmony's own regression test spells the attack out in its name: TestIsSpentIgnoresMutatedMerkleProofIdentity builds a proof, marks it spent, rebuilds it with "the same genuine, signed header" and a mutated MerkleProof, and asserts the replay is still caught. The fix deletes the epoch condition. The key now always comes from the header.

Path two: the quorum check counted the wrong thing

The second fix is in consensus/quorum/verifier.go. uniformVerifier.IsQuorumAchievedByMask is supposed to answer "did enough validators sign this?" It answered a different question:

got := int64(len(mask.Publics))
exp := uv.thresholdKeyCount()
return got > exp

mask.Publics is the full committee key list, not the signers. That expression weighs committee size against the threshold, which has nothing to do with the bitmap, and returns the same answer whether every validator signed or none did.

The patched version walks the bitmap and counts bits actually set. The new tests are unambiguous: 0x00 must fail, padding bits must fail, a nil mask must fail, and TestVerifySignatureRejectsEmptyPreStakingQuorum requires the error "not enough signature collected." CryptoSlate describes the same hole from the other side, a flaw letting "an empty signer record and a mathematically neutral aggregate signature to pass a quorum check." An empty BLS aggregate is the identity element, and it verifies against an empty key set.

This verifier serves the pre-staking path. On mainnet, PreStakingEpoch is 185 and StakingEpoch is 186, thousands of epochs behind the present.

The shape both paths share

CXMerkleProofReplayFixEpoch on mainnet is epoch 2964. So is BloomEpoch. The Bloom hardfork activated at epoch 2964, shard 0 block 91488255, on July 13, 2026 at 05:58:57 UTC, bundling a cluster of cross-shard receipt hardening: the replay fix, a receipt state rollback, stricter crosslink handling. Someone at Harmony had already identified this subsystem as dangerous and written the fix.

It was live for thirty days. It did not stop this.

It did not stop it because the gate was IsCXMerkleProofReplayFixEpoch(cxp.Header.Epoch()). Not the chain's current epoch. The epoch of the header inside the proof. Every cross-shard receipt from before July 13 carries a genuine, correctly signed header stamped below 2964. Present one and the strict branch is skipped by design, because the code asked the artifact which era's rules to apply and the artifact answered honestly.

That is the spine. Both defenses were conditioned on a value the attacker selects by choosing which historical proof to bring.

One uncomfortable follow-on. Harmony develops in the open, so the fix, the epoch constant, and the conditional limiting it to epochs at or above 2964 sat in public source for all thirty days. A fix that ships with a visible activation boundary also ships a map of where it does not apply. There is no evidence about how this attacker found the flaw, and open development remains the right default. But "we patched it" and "we patched it everywhere it can be reached" are different claims.


The Attack, Step by Step

Harmony has not named a vector. The following reconstructs the replay path from the patch that stopped the mint: informed reading of primary source code, not the operator's confirmed account.

#StepWhat made it work
1Select a genuine, already-applied proof from a pre-Bloom epochThe chain's own history supplies these, nothing needs forging
2Keep Header, CommitSig, CommitBitmap byte-identicalSignature verification still passes
3Mutate MerkleProof.ShardID and MerkleProof.BlockNumThese sit outside the signed header
4Submit to the destination shardHeader epoch is below 2964, so the strict branch is skipped
5IsSpent keys off the mutated fieldsNo marker at that key, so the proof reads as unused
6The shard credits the receipts againThe matching debit already happened, once
7Return to step 3 with new mutationsEach variant is a fresh identity to the spent check
8Route the balance to exchangesRoughly 2.8 billion ONE landed there, per Juiceberg

The credit arrives through a block's IncomingReceipts field, which Harmony keeps separate from its transaction list. A block can carry no transactions and still move balances. That is the most plausible reading of the "minted via empty blocks" phrasing in early coverage, though no source states it in those terms and I am inferring it from the data structure.

rendering diagram…

While reading cx_receipt.go I noticed CXReceiptsProof.Copy populates CommitBitmap from cxp.CommitSig rather than cxp.CommitBitmap, a copy-paste slip still present in v2026.1.1. It is not implicated in this exploit, and I raise it only as a measure of the attention this subsystem has been getting.


Reconciling the Numbers

Coverage on August 12 put the price drop at 26%, 30.65%, 33%, 37%, 40% and 50%. That spread is six outlets sampling a moving intraday chart. CoinDesk's story makes the point by itself: the headline reads 40% while the URL it published at still carries 26% from an earlier version. Anchor on the CryptoSlate figure of 30.65% over 24 hours at $0.000813, which is timestamped. TechTimes recorded the intraday low at $0.0005735 and a partial recovery to about $0.00077, which brackets the range.

The token count is stabler. Roughly 4 billion ONE, about 26% of supply, appears consistently across The Block, Decrypt and CryptoSlate. One aggregator headline said 40 billion, an order of magnitude above every other account and above 26% by its own arithmetic. Use 4 billion until someone publishes evidence otherwise.

The dollar figure deserves more suspicion than either. Several outlets valued the mint at roughly $3.2 million by multiplying 4 billion tokens by a post-crash price near $0.0008. That describes a trade nobody could execute: the attacker pushed 2.8 billion ONE into a book already collapsing under the news, and the last tokens out cannot fetch what the first ones did. Realized proceeds stay unknown until someone traces the deposits. What is certain is that 26% of a monetary base came from nothing, and the loss to holders is the dilution.

Harmony's freeze request rewards a close read too. It asks exchanges to block "these 4 wallet addresses" and lists four strings, which are two wallets written twice. Decode the bech32: one1uap8dx2z0qsjxqthm5flgcxkeepsz3gsrghnfn is byte-for-byte 0xe7427699427821230177dd13f460d6ce43014510, and one17u300a40ll5wphd8kj5hktryhdjq3ml9f4phy4 is 0xf722f7f6afffe8e0dda7b4a97b2c64bb6408efe5. TechTimes read the list as "two on Harmony's native ONE network and two on Ethereum," which is the mistake the format invites. If you are screening this list, you are screening two addresses.


Why Does This Matter Beyond Harmony?

Every chain that has shipped a hardfork carries this exposure, and most teams have never looked at it.

A fork gate is a conditional that turns a rule on at some height or epoch. Teams add them constantly, because you cannot retroactively change how old blocks were validated without splitting the network. That constraint is real. The mistake is subtler: a security fix expressed as a fork gate leaves an executable copy of the vulnerable behavior in the tree permanently, and the condition choosing between them is often read out of the data being validated.

Old blocks must keep validating under old rules. A proof presented today, to move money today, is a different question, and Harmony's code answered it with the first one.

This is the same failure family as the Verus bridge drain, where every signature was legitimate and the two chains disagreed about what the signed bytes meant. Nobody stole a key in either case. The attacker found the seam between what was signed and what was trusted, which is where bridge and cross-shard money has been leaving all year.

Harmony has been here before, twice. June 2022 took about $99.7 million from the Horizon bridge after two of five multisig keys were compromised, attributed by the FBI to the Lazarus Group. December 2023 is the closer relative: per TechTimes, a staking defect minted 146.28 million ONE across 74 delegator addresses when undelegation logic kept paying rewards that should have stopped, fixed by emergency hard fork at block 51,118,080. Same chain, same shape: an accounting record that should have been consumed once, honored more than once.

An audit certifies the code you showed it, on the day you showed it. It says nothing about which of the fork-gated variants of that code an attacker can still reach.


What Should Operators Actually Do?

  1. Audit your fork gates as attacker-controlled input. For every IsSomethingEpoch(x), establish where x comes from. If it can be read out of a user-supplied artifact rather than the node's own view of chain state, that is a finding.
  2. Never key a uniqueness check off unauthenticated fields. Where a struct carries both a signed identity and an unsigned copy of it, every nullifier, spent marker and dedup key must derive from the signed one. Write the regression test that mutates the unsigned copy and asserts nothing changes, as PR #5101 now does.
  3. Test quorum verifiers against the empty set. Assert that a zero bitmap fails, that padding bits do not count, that a nil mask fails, and that an identity aggregate signature is rejected. Four cheap tests that would have caught this.
  4. Monitor total supply from chain state, not from your own API. Reporting noted Harmony's totalSupply endpoint did not immediately reflect the new tokens. An endpoint your own infrastructure computes is not an independent witness to your own solvency. Sum balances or read the state trie, and set the alert threshold near zero.
  5. Alert on the first anomalous credit, not the aggregate. Harmony's response was quick and the tokens were still 97% on exchanges. This shape produces a credit with no matching debit on the very first replay, detectable in one block. By four billion tokens, all you have left to issue is a press release.
  6. Treat old, still-reachable code paths as live attack surface. Inventory every legacy branch a current transaction can invoke. If a path exists only to preserve historical validation, make sure nothing that moves value today can enter it.

Frequently Asked Questions

How much was actually stolen in the Harmony exploit?

About 4 billion ONE were minted, roughly 26% of supply, and about 2.8 billion reached exchanges according to on-chain analyst Juiceberg. The commonly cited $3.2 million is 4 billion multiplied by a post-crash price, which overstates what could be realized selling into a collapsing book. Harmony has not confirmed a loss figure.

Was this a bridge hack like Harmony's 2022 incident?

No. The 2022 Horizon bridge loss came from compromised multisig keys, attributed to the Lazarus Group. This was a code defect in Harmony's internal cross-shard receipt handling, and every signature involved appears to have been genuine.

Would a smart contract audit have prevented this?

A review was the right control, though not a smart contract audit. The defect sits in the chain client, in consensus and state code, so it needed a protocol-level review of the fork-gating logic and the receipt path. This is a case where we would point at deep human review rather than runtime monitoring for prevention. Monitoring shortens the window between the first bad credit and the funds reaching an exchange, and that window is where the 97% went.

Is Harmony going to roll back the chain?

Harmony said rollback options were under consideration and has not announced a decision or a reversal point. A rollback would also erase legitimate activity since the attack, which is why teams rarely commit to one quickly.

What is the fix, and should validators upgrade?

Release v2026.1.1 contains PR #5101, which always derives the spent marker from the signed header and rewrites the quorum check to count actual signers. Validators should be on it. Harmony says a further update will address the already-minted tokens.


What to Watch Next

Harmony has not published a postmortem, confirmed the token count, or said which of the two patched paths was used. Whether the minted supply gets burned, frozen, or absorbed is undecided, and that decision matters more to ONE holders than the exploit did.

The freeze request is the loop nobody has closed. TechTimes reported no exchange had publicly confirmed compliance, and none has since. That silence separates 2.8 billion tokens being recoverable from 2.8 billion tokens being somebody's realized profit. Nobody is going to publish it, which is its own answer.

There is a human cost worth recording too. On-chain investigator ZachXBT declined to help, saying nobody should assist Harmony for free and citing it rewarding $0 to the people whose work drove freezes and seizures after 2022. A protocol that needs volunteer investigators in hour one should think about what it owes them in hour one thousand.

Harmony shipped a real fix, in public, in twenty minutes, with tests that document the attack better than any disclosure would have. Good incident engineering. It arrived thirty days after the same team shipped the fix meant to prevent this, gated on a number the attacker got to pick.


Sources / References

Dmitry Serdyuk
Dmitry Serdyuk

Co-Founder & CDO

Full-Stack Operator | Building across security, AI, and digital infrastructure.