OAK — OnChain Attack Knowledge

Worked example · 2026-07

Across Protocol — a missing 8-byte Anchor discriminator check lets an attacker forge Solana deposit events that never moved funds, and the relayer fills 581 of them — Across / Risk Labs (Solana) — 2026-07-17

Loss
~$4.5M, borne entirely by a relayer operated by Risk Labs, the foundation supporting the protocol. No user funds were lost: all in-flight Solana transfers were completed or fully refunded, and losses stayed contained to the Risk Labs relayer rather than the protocol or its users. The attacker submitted 1,627 forged deposits across 18 destination chains with a combined face value of roughly $41.7M; the relayer filled 581 of them before Solana was disabled as an origin chain. This was Across's first attack since 2021, after processing more than $34B in bridge volume (one account puts the figure above $35B).
OAK Techniques observed
OAK-T10.002 (Message-Verification Bypass — primary, confirmed mechanism, in an off-chain relayer sub-shape OAK has not previously anchored. The defect was not in a contract: the relayer's off-chain code failed to verify the 8-byte Anchor event discriminator when reconstructing deposit events from Solana transaction traces. The attacker crafted transactions emitting data that parsed as valid deposit events while no funds moved on-chain, and the relayer — whose job is to front the destination-side payout against an observed source-side deposit — filled against deposits that did not exist. See techniques/T10.002-message-verification-bypass.md). OAK-T10.002.001 (Off-chain Observer Source-Event Forgery — the load-bearing locus shape, and this case is its canonical parse-level anchor: all three earlier T10.002 anchors place the failing predicate in deployed on-chain bytecode, whereas here it sits in a relayer's off-chain event-reconstruction code, which carries contract-grade authority while receiving indexer-grade review. Promoted to emerging in 2026-08 on its second independent anchor, the Coreum–XRPL bridge, whose failure is the sibling semantic / custody-level shape — fields validated, asserted fact never checked. See techniques/T10.002.001-off-chain-observer-source-event-forgery.md). OAK-T10 (Bridge / Cross-Chain parent).
Attribution
pseudonymous. No named individual or group, and no public link to a tracked OAK actor. The scale and shape of the operation — 1,627 forged deposits fanned across 18 destination chains inside a short window — indicates automation prepared in advance rather than manual exploitation, but nothing further has been made public.
Key teaching point
On Solana there is no canonical event system, so "an event happened" is an inference from transaction traces — and an inference is only as sound as the tag you check before trusting it. Anchor prefixes emitted data with an 8-byte discriminator precisely so a consumer can tell which event type it is looking at. Across's off-chain relayer skipped that check, and because failed Solana transactions still emit data, an attacker could publish byte sequences that a naive parser read as genuine deposits without ever locking a token. The generalisable rule is that off-chain observers are part of the trust boundary and must be reviewed like contracts. Every audit dollar in this ecosystem flows toward on-chain code, yet a relayer, indexer, or filler that decides when to release value is making an authorisation decision, and its parsing logic is the verification predicate. The specific check here is one comparison of eight bytes. The second lesson is about who absorbs the failure: Across's intent-based design places the relayer's own capital in front of the user, so a bug in the relayer's event parsing cost the relayer $4.5M and cost users nothing. That is a design property worth naming, because it is the reason this incident reads as a contained operational loss rather than a protocol failure.

Summary

Across is an intents-based cross-chain bridge in which relayers front the destination-side payout to a user immediately, observing a source-chain deposit and later reclaiming from the protocol. The relayer's decision to fill therefore depends entirely on its off-chain reading of source-chain events.

Across had recently launched a Solana SpokePool. Solana has no canonical event system — events are reconstructed from transaction traces, and failed transactions still emit data. The Anchor framework addresses the resulting ambiguity by prefixing emitted event data with an 8-byte discriminator identifying the event type.

Across's off-chain relayer code did not verify that discriminator. On 2026-07-17 at approximately 05:30 UTC, an attacker exploited this by publishing transactions whose emitted data parsed as legitimate deposit events while no funds actually moved on-chain. The relayer treated them as real deposits and filled the corresponding destination-side orders.

The attacker submitted 1,627 forged deposits across 18 destination chains, totalling roughly $41.7M in face value. The relayer filled 581 of them, losing approximately $4.5M, before Solana was disabled as an origin chain.

Risk Labs disabled Solana as an origin chain, paused the Solana SpokePool on-chain, deployed a root-cause fix within approximately five hours of detection, and fully restored Solana service within roughly 12 hours using fallback CCTP routing. User funds were unaffected; all bridge transactions in flight were completed or fully refunded, and the losses were contained to the Risk Labs-operated relayer.

Timeline (UTC)

When Event OAK ref
(standing) Across relayers fill destination-side orders against off-chain observation of source-chain deposits; the Solana relayer path does not verify the 8-byte Anchor event discriminator (standing T10.002 surface)
(standing) Solana has no canonical event system; events are reconstructed from transaction traces, and failed transactions still emit data (substrate condition)
2026-07-17 ~05:30 Attacker publishes transactions emitting data that parses as valid deposit events with no funds moved on-chain T10.002 exploitation
same window 1,627 forged deposits submitted across 18 destination chains, ~$41.7M face value; relayer fills 581 T10.002 extraction
same day Risk Labs disables Solana as an origin chain and pauses the Solana SpokePool on-chain; ~$4.5M relayer loss realised (containment)
+~5 hours Root-cause fix deployed (remediation)
+~12 hours Solana service fully restored using fallback CCTP routing; all in-flight transfers completed or refunded (recovery)

What defenders observed

  • Pre-event (the off-chain observer is inside the trust boundary). Across's contracts were not defective. The authorisation decision — is this deposit real? — was made in off-chain relayer code, which means that code carried contract-grade security responsibility while receiving indexer-grade review attention. Any protocol where an off-chain component releases or fronts value should scope it into security review explicitly (M23, M35).
  • Pre-event (Solana's event model is a standing hazard for every consumer). No canonical events, reconstruction from traces, and data emitted by failed transactions together mean that every Solana event consumer must validate the discriminator and the emitting program. This is not an Across-specific bug so much as an Across-specific instance of a hazard shared by every indexer, relayer, filler, and analytics pipeline reading Solana events. Teams operating such consumers can check their own code for the same omission today.
  • At-event (volume anomaly across destination chains). 1,627 deposits spread over 18 destination chains inside a short window is far outside normal traffic. A rate limit on fills-per-window and a fan-out anomaly rule on destination-chain diversity would both have fired well before 581 fills accumulated (M04, M05).
  • At-event (fill-versus-settlement reconciliation). The forged deposits never locked funds, so each fill created an immediate, checkable discrepancy between what the relayer fronted and what the source chain actually held. Continuous reconciliation of filled orders against confirmed source-side balances is the direct detection control for this class, and it does not require knowing anything about discriminators.
  • Response (unusually good, and specific). Detection to root-cause fix in about five hours and full service restoration in about twelve, with in-flight transfers completed or refunded and a fallback routing path (CCTP) available to keep the route alive while the primary was paused. The availability of that pre-existing fallback is what allowed the operator to pause the vulnerable path without stranding users — a design decision made long before the incident that paid off during it.
  • Response (loss placement was architectural, not luck). The relayer fronts its own capital ahead of settlement. That is why a parsing bug produced a $4.5M loss for Risk Labs and a $0 loss for users. Protocols should be able to state, in advance, which party's balance sheet absorbs a failure of each component — Across could.

Public references

Discussion

This is the most structurally novel case in OAK's July 2026 cohort, because the verification failure is entirely off-chain and the corpus's existing T10.002 anchors are all on-chain contract predicates — Wormhole's unvalidated guardian account, Nomad's 0x00 trusted root, Verus's missing source-amount conservation check. Across extends the class to the observer: the component that decides a source-chain event occurred, before any contract is asked to verify anything. The shared primitive holds — value is released against a message that should have been rejected — but the predicate lives in a Rust or TypeScript relayer rather than in deployed bytecode, and therefore in a place almost nobody audits. OAK records this as a sub-Technique candidate in TAXONOMY-GAPS.md; it needs additional anchors before promotion, and defenders should expect them, because the population of off-chain fillers, solvers, and relayers making value decisions from parsed chain events has grown very fast alongside intents-based architectures.

The Solana substrate detail deserves emphasis independent of Across. Because the chain has no canonical event log, every consumer reconstructs semantics from traces, and because failed transactions still emit data, an attacker can publish arbitrary bytes that a careless parser will treat as protocol history. The 8-byte Anchor discriminator exists to make that distinguishable, which means the entire attack reduces to one omitted comparison — and the same omission is available to any of the many teams running Solana event consumers. This is the rare finding that generalises into an immediately actionable check for third parties who were not involved in the incident.

Finally, this case is worth keeping in OAK as a contained-outcome exemplar rather than filing it away as a near-miss. The corpus is naturally biased toward total losses, which distorts what good looks like. Across pairs instructively with examples/2026-07-verus-ethereum-bridge-repeat-exploit-unfixed-import-path.md from six days later: same technique class, opposite response. Verus took 66 days to not fix a publicly root-caused defect and was drained a second time; Across fixed its root cause in about five hours, restored service in twelve, kept users whole, and absorbed the loss on the balance sheet of the party whose code was wrong. The mechanism did not determine those outcomes. The operational posture did.

Techniques demonstrated (3)