Get Secured
← All Posts Bridge Security 30 May 2026

Gravity Bridge exploit: denom mapping poisoning drained ~$5.4M

Summary

On 29 and 30 May 2026, the Gravity Bridge was exploited for approximately $5.4 million through denom mapping poisoning. The attacker did not need a privileged role or a stolen key. They registered a minimal validator on Gravity with 80 GRAV, minted fake tokens on Osmosis, IBC-transferred them to Gravity, and then used the permissionless deployERC20() function on Ethereum with fabricated _cosmosDenom strings that embedded the addresses of real custody tokens. Validators acknowledged the deployment, the bridge wrote attacker-influenced metadata into its denom-to-ERC20 registry without a collision check, and a batch of withdrawals then released real assets. The stolen funds included roughly $4.3M USDC, 274 WETH, $434K USDT, and 14.16 PAXG. Validators halted the bridge once the incident was detected. An official postmortem is still pending.

What is confirmed and what is pending

Gravity issued short public statements on 30 May 2026, quoted by Rekt and others. The first: “There was an unfortunate incident on Gravity. Validators should halt their validators and orchestrators while this incident is being investigated.” The second: “Thanks to the swift action of validators, the bridge is currently halted while investigations continue.” The mechanism, loss breakdown, and on-chain artefacts below are drawn from Rekt’s technical analysis and QuillAudits’ hack analysis. A full official postmortem from the Gravity team is still pending.

Incident timeline

StageEvent
SetupAttacker registers a minimal validator named julia666 on Gravity with 80 GRAV.
MintAttacker mints fake tokens on Osmosis and IBC-transfers them to Gravity.
PoisonAttacker calls permissionless deployERC20() on Ethereum with fabricated _cosmosDenom strings embedding real Ethereum custody token addresses.
AcknowledgeGravity validators submit MsgERC20DeployedClaim; handleErc20Deployed writes attacker-influenced metadata into the denom-to-ERC20 registry without a collision check.
DrainBatch withdrawals 41572–41575 are signed and submitted; safeTransfer releases real assets.
30 MayGravity instructs validators to halt; the bridge is halted while investigation continues.

The attack path

Gravity Bridge maps Cosmos-side denominations (denoms) to Ethereum ERC-20 token addresses through a registry. When a new token is bridged, a deployERC20() call on Ethereum establishes the ERC-20 representation, and validators acknowledge that deployment back on the Cosmos side with a MsgERC20DeployedClaim. The handler handleErc20Deployed records the mapping between the Cosmos denom and the Ethereum token.

The critical weakness is that deployERC20() is permissionless and the acknowledgement path wrote attacker-influenced metadata into the registry without checking for collisions against existing, legitimate mappings. The attacker exploited this in steps that each looked individually benign.

They first registered a minimal validator, julia666, with just 80 GRAV, giving themselves standing in the validator set. They minted worthless fake tokens on Osmosis and IBC-transferred them to Gravity to create a denom they controlled. They then called deployERC20() on Ethereum with fabricated _cosmosDenom strings crafted so that the metadata embedded the contract addresses of real, valuable custody tokens such as USDC, USDT, WETH, and PAXG. When validators acknowledged these deployments through MsgERC20DeployedClaim, handleErc20Deployed wrote the poisoned mapping into the registry, with no collision check to reject a denom that pointed at an asset the bridge already held.

With the registry poisoned, the attacker triggered withdrawals. Batches 41572 through 41575 were signed and submitted, and safeTransfer dutifully released the real custody assets to the attacker’s Ethereum addresses. The bridge behaved exactly as coded; the code trusted a mapping that an unprivileged user had been allowed to write.

Technical evidence and explorer links

The following addresses, transactions, and identifiers appear in the cited analyses. Full addresses, transaction hashes, and explorer links are reproduced exactly as published.

RoleAddress / tx / link
Primary theft wallethttps://etherscan.io/address/0x7B582033061b96cC3F9421e73a749ED7C62da1F9
Secondary theft wallethttps://etherscan.io/address/0x4d3ca32e687e871a58b78AcAc73bE59AC37C7A47
Vulnerable contracthttps://etherscan.io/address/0xa4108aa1ec4967f8b52220a4f7e94a8201f2d906
Orchestrator Ethereum keyhttps://etherscan.io/address/0x91B52e07132a49DAD1B7a3939a51547f79468Ec7
Other EOAhttps://etherscan.io/address/0x73e95ae5f3b87e02d4547afe86d0d466e9450d6b
Other EOAhttps://etherscan.io/address/0xDaf38ad7f8F7431978d6bFffa78A23e4c5f010c6
Tornado routing addresshttps://etherscan.io/address/0xc8c71ae4261e55a66d9967f2ac252be4e669f562
USDC drain txhttps://etherscan.io/tx/0xfce883a8f9a4f3479cce1368b99287973ab40451ac092f5a41e1e09eecab5044
USDT drain txhttps://etherscan.io/tx/0x469274f4edd45ec3284bf60de8eb30086222745f8f8c8b6a955137feed41281d
WETH drain txhttps://etherscan.io/tx/0x59e52302c53e862fcf833b61eb851ff66e098e3d29db19fd66e5a04734eeb84b
PAXG drain txhttps://etherscan.io/tx/0xd3cdfa10be4f0cde6b3f294856a8bdd840983dcef29a5dc24c70c36e2d7f9ef0
Fake deploy tx 1https://etherscan.io/tx/0x92b2a61d88b3f68d7d3b5cba4a12f53e0c226287702d72de80a60515987e3532
Fake deploy tx 2https://etherscan.io/tx/0x364ebefab8e7c8ddd425447349cc99dcd75ab1751612f7ef9c60c20fdb9a2bb6
Fake deploy tx 3https://etherscan.io/tx/0x871433af303743d61b3f2a38174e9e6655fdc8937c0689122685509dcabbf066
Fake deploy tx 4https://etherscan.io/tx/0x67a181c333cb75231613c125215168a1eacbb4021d07cf0d91ca8bbaa65f8245
Osmosis attackerosmo1m9athjzah02f2mnrgtcke7e5ya3zpvw8lccuss
Gravity validatorgravityvaloper1rdwckpx2p3mwu4k8xdz8vmd4x3mqx4v9ars8k
Gravity create-validator txF6AA34E8D01C55A5F1E38310E816DBB4BEE25B2FDB29ACD7ED1E25352BA62009

Loss breakdown

AssetAmount
USDC~$4.3M
WETH274 WETH
USDT~$434K
PAXG14.16 PAXG
Total~$5.4M

Confirmed vs pending

FieldStatusDetail
Incident datesReported29 and 30 May 2026
Bridge haltConfirmed by GravityValidators instructed to halt; bridge halted while investigation continues
Total lossReported~$5.4M (USDC, WETH, USDT, PAXG)
MechanismReportedDenom mapping / registry poisoning via permissionless deployERC20()
Missing controlReportedhandleErc20Deployed wrote registry metadata without a collision check
Validator abuseReportedMinimal validator julia666 registered with 80 GRAV
Official postmortemPendingNo full postmortem published at drafting time

Why this matters

Permissionless registration plus trusted writes is a dangerous pairing. A function being open to anyone is not a flaw in itself. It becomes one when the output of that open function is later trusted as authoritative without validation. Here, deployERC20() was permissionless by design, but the metadata it produced flowed into a registry that controlled which Ethereum token a denom could withdraw, and nothing checked whether that mapping collided with an existing legitimate asset.

Registries that control custody are part of the trust boundary. The denom-to-ERC20 map is not bookkeeping. It is the lookup that decides which real asset a withdrawal releases. Any write path into that map is effectively a write path into the vault. Treating it as configuration rather than as security-critical state is how attacker-controlled strings ended up pointing at USDC custody.

A low validator stake bar lowers the cost of an attack, not the impact. Registering a validator with 80 GRAV gave the attacker the standing needed to push the deployment claims through the validator flow. The economic cost of entry was trivial relative to the $5.4M extracted, which is the signature of a design where the value at risk is wildly out of proportion to the cost of participating.

What defenders can take from this

Validate before you trust a write to custody-controlling state. Any acknowledgement that updates a denom-to-token or asset-mapping registry must reject collisions with existing mappings and must reject denoms whose embedded metadata references custody tokens the bridge already holds. The collision check that was missing here is the single control that would have stopped the entire chain.

Separate the right to register a token from the right to define what it withdraws. A newly deployed ERC-20 representation should not be able to inherit or alias the withdrawal path of an existing, valuable asset. Bind each denom to exactly one immutable token mapping at first legitimate creation, and treat any later attempt to remap it as an attack, not an update.

Monitor the registry, not just the balances. By the time funds move in batch withdrawals, the poisoning has already happened. Alerting should fire on the registry write itself: a new mapping whose metadata references the address of a high-value custody token is a high-confidence indicator that should pause batches before they are signed.

Watch for Tornado routing as a containment trigger. The stolen funds were routed toward Tornado-associated addresses. Detecting that pattern quickly is what determines whether centralised venues and downstream protocols can react before the trail is obscured.

Sources

If you run a cross-chain bridge or any system that maps external identifiers to on-chain assets, the question is not whether your signature scheme is sound. It is whether every write into the state that controls custody is validated against collisions and bound to a single trusted origin. Security4Web3 can audit your denom and token registry logic, model the cost-to-impact ratio of your validator and registration paths, and build monitoring that pauses withdrawals the moment a registry write looks like poisoning.

Protect Your Protocol Before the Next Exploit

Book a Security Review