ΩForensic Capital
FC-005
Incident date · 2026-05-29/30
Published · 2026-06-25
Status · ACTIVE
Forensic Analysis · Public

Gravity Bridge Denom PoisoningActive

A missing validation in a permissionless function allowed the bridge's denom registry to be poisoned via a fabricated cross-chain token. Validators signed legitimate batches against corrupted state. $5.4M drained. Code vulnerability confirmed. No post-mortem published.

$5.4M
Total Loss
2102 ETH
Attacker wallet (2026-05-31)
post-conversion par l'attaquant — vol direct = ~4.35M USDC + 434k USDT + 274 WETH + 14.164 PAYG (~$64,000) — ticker PAXG non confirmé, PAYG retenu per Bitcoin.com/BingX
2 / 10
Recovery probability · no KYC trace
Score basis: KYC-traceability of exchange transactions, bounty negotiation status, fund concentration in identified wallets.
00

Executive Summary

On 29-30 May 2026, Gravity Bridge sustained a $5.4M loss via cross-layer registry corruption. The attack exploited a missing validation in deployERC20() — a permissionless function in Gravity.sol — to poison the bridge's denom mapping registry. No signing key was compromised. The attack is classified FC-CLASS-001 (Cross-Chain State Validation Failure).

The attack originated on Cosmos: the attacker minted a fabricated token via Osmosis tokenfactory, constructing its denom string to embed a real Ethereum ERC20 custody address. A permissionless call to deployERC20() on the Ethereum side triggered handleErc20Deployed to write the poisoned denom→ERC20 mapping to the registry without checking for an existing ERC20 entry at that address. Validators subsequently signed withdrawal batches against the corrupted registry state — operating correctly per protocol rules, with no visibility into the poisoning. On-chain capital required by the attacker was approximately zero. No official Gravity Bridge post-mortem has been published as of 2026-06-25.

As of 2026-05-31, 2102 ETH (~$4.23M) was confirmed in the attacker's wallet. By 2026-06-04, CertiK documented 2,020 ETH (~$4.12M) routed to Tornado Cash across multiple transactions — rendering these funds structurally unrecoverable absent attacker cooperation or exchange-level KYC intercept. The remaining ~$1.17M is unaccounted for in primary sources. The bridge was halted with no announced reopening date.

01

Methodology & Sources

Analysis derived from the Forensic Capital signal database (passive_monitor_log, fc_incidents — FC-005 row), on-chain transaction data for gravitybridge.net, and two primary sources: rekt.news/gravity-bridge-rekt (2026-06-04) and quillaudits.com/blog/hack-analysis/gravity-bridge-demon-mapping-poisoning. The mechanism — cross-layer registry corruption via deployERC20() — is confirmed in both primary sources.

Where figures are unconfirmed or sourced from a single outlet, this is labelled explicitly. Unverified items appear in Open Questions rather than being omitted. No official Gravity Bridge incident report or post-mortem existed at publication date.

Ω GRAVITY BRIDGE — ATTACK SURFACE FC-CLASS-001 · CROSS-CHAIN STATE VALIDATION FAILURE COSMOS LAYER Osmosis tokenfactory fabricated denom embedded ETH address → IBC relay → VULNERABILITY deployERC20() permissionless no _cosmosDenom validation calls handleErc20Deployed → registry write REGISTRY STATE POISONED denom→ERC20 mapping corrupted no collision check handleErc20Deployed ATTACKER 2,102 ETH ≈ $4.23M extracted batch withdrawals vs. poisoned registry VALIDATORS signed legitimate batches · no key compromise operating correctly per protocol no visibility into corruption · poisoning preceded signing The registry was poisoned. The validators signed what they were given. FC-005 · forensic-capital.com
02

Timeline

  • Pre-2026-05-29 · date inconnueL'attaquant enregistre un validateur minimal julia666 sur Gravity Chain avec 80 GRAV (~$2–5 USD). Condition nécessaire pour que deployERC20() déclenche handleErc20Deployed.
  • Pre-2026-05-30 · date unknownPoisoning transaction submitted to deployERC20() on Gravity.sol. Exact date unconfirmed — only the exploitation date (2026-05-30) is in the FC-005 record. Bridge continues operating — registry corruption is not detectable on-chain without specific denom mapping inspection.
  • 2026-05-29/30 · incident dateAttacker exploits poisoned registry to initiate batch withdrawals. All transactions pass cryptographic validation — validators sign based on registry state, with no visibility into the poisoning. The bridge contract correctly processes every withdrawal.
  • 2026-05-30 · post-drainBridge halted. $5.4M total loss confirmed in FC-005 record. No reopening date announced.
  • 2026-05-31 · observation date2102 ETH (~$4.23M at observation) confirmed in attacker wallet. Remaining ~$1.17M disposition unknown — potentially moved, exchanged, or distributed across additional wallets.
  • 2026-06-25 · publication dateNo Gravity Bridge post-mortem published. Bridge remains halted. Incident classified ACTIVE in FC database.
Ω FC SIGNAL INVENTORY — FUND FLOW FC-005 · gravitybridge.net GRAVITY BRIDGE $5.4M total drained ATTACKER WALLET 2,102 ETH ≈ $4.23M · confirmed on-chain UNKNOWN DESTINATION ≈ $1.17M untraced · disposition unknown valid sig 2026-05-29/30 Denom poisoning batch withdrawals 2026-05-30 Bridge halted no reopening date 2026-05-31 2,102 ETH confirmed in attacker wallet Root cause · FC-CLASS-001 Cross-Chain State Validation Failure registry_state_pollution · deployERC20() missing _cosmosDenom validation Severity 9/10 · Blast radius 8/10 · ACTIVE forensic-capital.com · Ω

Fonds partiellement routés via Binance et ChangeNow (BTC conversion) avant dépôt Tornado Cash — source : PeckShield 2026-05-30, Bitcoin.com 2026-05-29.

03

Analysis — Registry State Corruption

The vulnerability consists of two connected gaps in the registry write path. First: deployERC20() in Gravity.sol is permissionless — any caller can invoke it with any _cosmosDenom string, with no validation that the string corresponds to a legitimate Cosmos asset. Second: handleErc20Deployed, the Gravity chain handler triggered in response, writes the new denom→ERC20 mapping to the registry without checking whether an ERC20 contract at that address was already registered under a different denom. A collision check existed elsewhere in the same codebase — it was never applied in this execution path. Sources: rekt.news/gravity-bridge-rekt (2026-06-04); quillaudits.com/blog/hack-analysis/gravity-bridge-demon-mapping-poisoning.

The attack requires three sequential preconditions: (1) validator registration on Gravity Chain (julia666, 80 GRAV), (2) tokenfactory mint on Osmosis with fabricated denom embedding a real ERC20 custody address, (3) permissionless call to deployERC20() on Ethereum. The attack originates on Cosmos. The attacker used Osmosis tokenfactory to mint a fabricated token whose denom string was constructed to embed the address of a real Ethereum ERC20 custody contract. A call to deployERC20() on the Ethereum side — which accepts any caller — triggered handleErc20Deployed to write this poisoned denom→ERC20 mapping to the registry. Validators then signed withdrawal batches against the corrupted registry state. Every signature was cryptographically legitimate. No signing key was compromised. No validator acted outside protocol rules. The poisoning of the registry state preceded and enabled the withdrawals.

bridge Gravity Bridge (gravitybridge.net) fc_class FC-CLASS-001 — Cross-Chain State Validation Failure submechanism registry_state_pollution entry_chain Cosmos — Osmosis tokenfactory via IBC vuln_function deployERC20() — permissionless, no _cosmosDenom validation registry_flaw handleErc20Deployed: no collision check on existing ERC20 entries key_compromise none — validators signed correctly per protocol rules code_vuln confirmed — missing input validation / missing collision check txn_validity all withdrawal transactions cryptographically valid exploit_capital ~80 GRAV + gas (~$2–5 USD total) loss_usd $5,400,000 attacker_wallet 0x7B582033061b96cC3F9421e73a749ED7C62da1F9 · 2102 ETH (~$4.23M) confirmed 2026-05-31 fc_severity 9 / 10 fc_blast_radius 8 / 10 fc_defensibility 6 / 10 — input validation on deployERC20() or collision check in handleErc20Deployed would each block the attack status ACTIVE — bridge halted, no post-mortem, no reopening date

The critical classification distinction from FC-CLASS-002 (Privileged Key Compromise): the off-chain key management layer was never touched. The attack is entirely on-chain, deterministic, and reproducible from the Gravity.sol source. The architectural failure is the absence of authorization and input validation on a function with direct write access to the cross-chain state registry. Any actor with access to IBC tokenfactory — permissionless by design on Osmosis — could construct the poisoning transaction.

The defensibility score of 6/10 reflects that the fix is a targeted code change in a known path, not an architectural overhaul. The severity score of 9/10 reflects that once the registry is poisoned, withdrawals are indistinguishable from legitimate operations at the signing layer.

GitHub signal 1 — Audit status undischarged. The Gravity Bridge README states: "will be undergoing audits soon" — a statement present in the repository since at least the December 2021 mainnet launch, 4.5 years before the May 2026 exploit. No audit report link appears in the repository as of publication date. Source: github.com/Gravity-Bridge/Gravity-Bridge

GitHub signal 2 — 14 months without a release, 8 watchers. Last published release: v1.12.3, March 2025 — 14 months elapsed before the May 2026 exploit with no subsequent release. At time of incident the repository carried 8 watchers on a bridge holding $5.4M in assets. Source: GitHub releases — github.com/Gravity-Bridge/Gravity-Bridge/releases

GitHub signal 3 — No input validation on cross-chain state transition. The README Operational parameters section states: "events accepted based purely on signatures of the current validator set". The registry write path — deployERC20()handleErc20Deployed — requires neither caller authorization nor _cosmosDenom input validation. Any actor on Cosmos can trigger a registry update on Ethereum with an arbitrary denom string. Source: Gravity.solgithub.com/Gravity-Bridge/Gravity-Bridge

GitHub signal 4 — Business Wire 2022 launch claim. Business Wire dated 2022-01-19 described the Gravity Bridge mainnet launch of December 2021 as "Never Hacked". The bridge was exploited 4.5 years later, in May 2026. Source: Business Wire 2022-01-19.

Perimeter signal — gravitybridge.net security hygiene. The Forensic Capital passive monitor recorded two perimeter deficiencies on gravitybridge.net at observation date: SPF absent (dns_spf_absent) and HSTS missing (http_hsts_missing_financial). These are not causal to this incident but indicate security hygiene posture consistent with a bridge operating without routine perimeter monitoring. Source: Forensic Capital passive_monitor_log.

Media misclassification signal. Multiple outlets initially classified this incident as a signing key compromise (Yahoo Finance 2026-05-30; Zealynx 2026-06-02). This classification is factually incorrect. No signing key was compromised. Validators operated correctly per protocol rules throughout. The misclassification reflects the difficulty of distinguishing registry-level state corruption from key compromise at the validator layer — both produce cryptographically valid signatures on malicious state. The distinction is material: key compromise is remediable by key rotation; registry corruption requires code-level validation enforcement.

The registry was poisoned. The validators signed what they were given.

03.5

Confidence Mapping

Three-tier classification of findings by evidentiary basis. ESTABLISHED requires on-chain or primary-source confirmation. INFERRED requires logical elimination from confirmed data. UNVERIFIED identifies open questions without confirmed answers in primary sources.

ESTABLISHED — ON-CHAIN / PRIMARY-SOURCE CONFIRMED
registry_state_poisoned confirmed — rekt.news/gravity-bridge-rekt (2026-06-04) · quillaudits analysis deployERC20_permissionless Gravity.sol source confirmed — any caller, no _cosmosDenom validation no_key_compromise validators signed correctly per protocol rules — on-chain confirmed loss_usd $5,400,000 — FC-005 record, consistent with on-chain withdrawal data attacker_wallet 0x7B582033061b96cC3F9421e73a749ED7C62da1F9 · 2102 ETH (~$4.23M) confirmed on-chain — observation date 2026-05-31 bridge_halted 2026-05-30 — no reopening date published as of 2026-06-25
INFERRED — LOGICAL ELIMINATION FROM CONFIRMED DATA
entry_vector Osmosis tokenfactory + IBC — logical from denom construction (embedded ETH address in Cosmos denom) collision_check_absent handleErc20Deployed write path — confirmed absent per quillaudits · check exists elsewhere in codebase denom_construction fabricated denom string embedding real ETH custody contract address — structural requirement of exploit
UNVERIFIED — NOT CONFIRMED IN ANY PRIMARY SOURCE
exact_denom_string fabricated denom value not published in available primary sources exploit_prep_date only exploitation date (2026-05-30) confirmed — poisoning transaction date unconfirmed remaining_funds ~$1.17M disposition untraced in primary sources as of 2026-06-25
04

Recovery Status

FC-005 recovery probability: 2/10 — reflecting the absence of KYC-linked exchange transactions in available evidence and no publicly reported bounty negotiation. As of 2026-05-31, 2102 ETH (~$4.23M) was confirmed in the attacker's wallet. By 2026-06-04, CertiK documented 2,020 ETH (~$4.12M) routed to Tornado Cash across multiple transactions — rendering these funds structurally unrecoverable absent attacker cooperation or exchange-level KYC intercept.

The remaining ~$1.17M between the $5.4M total loss and the identified 2102 ETH is unaccounted for in primary sources. It may have been bridged, exchanged via DEX, or distributed across additional wallets prior to the 2026-05-31 observation date.

In an environment of concentrated law enforcement attention on bridge exploits, asset tracing is active but fund recovery without attacker cooperation remains structurally unlikely given the absence of KYC-linked exchange transactions in available evidence.

Open Questions & Unverified

  • Exact fabricated denom string — the Cosmos denom value used in the poisoning transaction has not been published in available primary sources.
  • Exploit preparation date — only the exploitation date (2026-05-30) is confirmed. The date when the poisoning transaction was submitted to deployERC20() is not confirmed in available sources.
  • Additional poisoned registry entries — whether the attacker poisoned one or multiple denom→ERC20 mappings is not confirmed in available primary sources.
  • Disposition of ~$1.17M not present in the identified 2102 ETH attacker wallet — no primary source confirms movement to exchange, mixer, or secondary wallet.
  • No official Gravity Bridge post-mortem published as of 2026-06-25. This report relies on the FC-005 database record, on-chain observation, and two external primary sources.
  • Bridge reopening timeline: not announced. Source: FC-005 vector field ("Bridge halted — no reopening date").

About this report

Forensic Capital produces independent, source-traceable forensic analysis of DeFi incidents. This report is public.

forensic-capital.com · Ω

Sources

  1. Forensic Capital database — FC-005 record, fc_incidents table, data/forensic_capital.sqlite
  2. On-chain transaction data — gravitybridge.net bridge contract, attacker wallet 0x7B582033061b96cC3F9421e73a749ED7C62da1F9, observation 2026-05-31. Drain transactions: USDC 0xfce883…b5044 · USDT 0x469274…1281d · WETH 0x59e523…eb84b · PAXG 0xd3cdfa…f9ef0
  3. Forensic Capital passive monitor — passive_monitor_log, signal dns_spf_absent and http_hsts_missing_financial on gravitybridge.net
  4. rekt.news/gravity-bridge-rekt — primary incident report (2026-06-04)
  5. quillaudits.com/blog/hack-analysis/gravity-bridge-demon-mapping-poisoning — technical analysis, collision check absence (2026-06-04)

No official post-mortem published — see Methodology and Open Questions.

SHA-256 (this version) · cbf28d45cddeb3641f2173e4ec5f73aacef24bb424934ae51c13d534c6c4c935
Version date · 2026-06-29 · rev. FC-005-P1 (Perplexity corrections: PAYG, julia666, Tornado Cash, Binance/ChangeNow, media misclassification, SVG amount)

This hash fixes the published version at the stated date. It is a version marker, not a third-party proof of immutability; the canonical hash is anchored in the public repository commit history.