Skip to content
HomeAboutServicesGuidesContact

Guide

What audits a bridge protocol needs

A bridge is several systems that have to agree, and most of them are not the contracts. What to commission, what each engagement covers, and the order that makes each one cheaper than the last.

In short

  • A bridge is not one system, and a bridge audit is not one engagement. The contracts are the smallest part of the surface and the part most often reviewed alone.
  • The two components behind the largest losses, the message verification routine and the infrastructure holding the signing keys, are not fully covered by a contract audit. Each needs a scope of its own.
  • Every chain you support is a separate review. A scope written for two chains does not extend to a third by implication, and the third is usually added under launch pressure.
  • Nothing here finishes at launch. A bridge changes its signer set, its supported chains and its contracts, and each change retires part of what the last report established.

One engagement is not a scope

Teams commission a bridge audit and receive exactly that: a review of the contracts, on the chains named in the statement of work, at the commit named in the report. The document is accurate. It is also a description of a minority of the system.

The reason is in the architecture. A bridge exists to convince one chain that something happened on another, and the convincing is done by parts that mostly do not live on chain. A set of relayers watches for events. A set of attesters signs claims about them. Keys sit on machines somewhere. A verification routine on the destination decides what to believe. Of those four, one is a contract.

In plain terms: the contract holding the funds is not what protects them. What protects them is everything that decides which messages that contract will accept, and most of that is infrastructure rather than Solidity.

So the useful question is not whether to audit a bridge. It is which of six scopes you are buying, and which of them you have assumed somebody else covered.

The contracts, on every chain you support

This is the engagement most teams already know they need, and the one most often scoped too narrowly.

A bridge has at least two contract surfaces. The source side locks or burns and emits a claim. The destination side verifies the claim and releases or mints. Each can be internally correct while disagreeing with the other about what a message means, and that disagreement is not visible from inside either one. A review of the destination alone can confirm the signature check is sound without ever establishing that the signed structure carries what the source believed it was sending.

The multiplication is the part that surprises people. A bridge supporting five chains has five deployments, and they are rarely identical: gas semantics differ, finality differs, one chain needs a shim for a precompile another has natively. Each variant is code that the others were not reviewed as.

In plain terms: ask what the scope says when you add chain six. If the answer is that the existing report covers it, the answer is wrong, and the sixth chain is usually added in a hurry for a partnership.

The verification routine, proved rather than read

One function on the destination chain decides whether an inbound message is genuine. Nearly every catastrophic bridge loss traces back to that function or to the keys feeding it.

It deserves more than line-by-line reading, because the defects it carries are the kind reading tends to pass over. A proof structure accepted when empty. A signature set counted without checking that the signers are distinct. A field validated while an adjacent field, the one that actually carries the destination address, is not. These look correct on the page. They fail on an input nobody wrote a test for.

Formal verification states the property as mathematics and establishes that no input violates it. For a verification routine the properties are expressible and worth the effort: a message cannot be accepted without a valid proof, the same message cannot be accepted twice, the threshold cannot be reached by one party holding several slots.

In plain terms: this is the one component where proving a property beats reviewing the code, because the failures are in the inputs nobody imagined rather than in the logic anybody can see.

The off-chain half

Relayers, attesters, the signing service, the machines they run on and the cloud account that owns those machines. None of this is on a chain, and all of it is inside the trust boundary.

A penetration test treats this as an attacker would. The questions are infrastructural rather than cryptographic: can a relayer be made to observe something that did not happen, can the attester service be reached from outside the network it is supposed to be confined to, what credentials does the deployment pipeline hold, and who in the organisation can reach the host that signs.

This is where the record is worst. The largest individual bridge losses were not protocol breaks. An attacker obtained enough signing authority and then used the bridge exactly as designed, which no contract review would have flagged because no contract misbehaved.

In plain terms: a sound signature scheme operated on a compromised machine produces valid signatures on fraudulent messages, and every contract in the path will honour them.

Who holds the keys, and how that changes

If your design depends on a signer set, the custody arrangement is a security control with the same weight as the verification routine, and it is reviewed far less often.

The threshold on paper is not the threshold in practice. Five of nine signers sounds robust until four of the nine run in the same cloud account, or three are operated by the same partner organisation, or the key material was generated in one ceremony on one machine. Independence is a property of the operational arrangement rather than of the number.

Rotation is the quieter problem. A signer set that changes needs a rule for who authorises the change, how the destination learns about it, and what happens to messages already in flight when it happens. Rotation logic tends to be written late, reviewed least, and exercised for the first time under pressure.

In plain terms: the question is not how many signatures are required. It is how many separate organisations, networks and people would have to be compromised to produce them, and whether anyone has written that number down.

The gap between the audited commit and the live contract

A report names a commit. Users interact with a deployment. Those are different objects, and nothing automatic connects them.

Deployment verification closes that gap: that the bytecode at the live address was built from the reviewed commit, that constructor arguments and initialisation values match what the review assumed, that ownership and privileged roles landed on the addresses intended rather than on a deployer key somebody forgot to transfer, and that the proxy, if there is one, points where it should.

For a bridge this matters more than for most systems, because the deployment happens several times across several chains, frequently by different people under schedule pressure, and an address configured wrongly on the fifth chain is indistinguishable from one configured correctly until it is used.

In plain terms: an audit tells you the code was sound. Deployment verification tells you that the code is the one now holding the money.

After launch, the part that does not finish

A bridge is a live operation rather than a shipped artefact. Its signer set rotates, its supported chains grow, its contracts get upgraded, and the chains underneath it change consensus rules on their own schedule and without asking.

Three things cover the running system. Monitoring watches what is observable in real time: mint sizes against locked balances, signer-set changes, pause events, volume that does not match the other side. A bug bounty puts the live deployment in front of people who are paid for what they find rather than for the hours they spend. And a retained reviewer looks at each upgrade before it ships, which is the one that quietly matters most, because an upgrade is a new contract being held to a report written about a different one.

Monitoring has a specific limit worth stating. It is strong on quantities and weak on logic. A flaw in the verification routine produces a message that looks entirely valid, in a normal size, at a normal time, and monitoring has no reason to question it.

In plain terms: the audit establishes a state, and the state expires. What you are buying after launch is the detection of changes that invalidate it.

The order to commission them in

Sequencing changes what each engagement costs, because a reviewer who arrives before the architecture is settled is reviewing decisions instead of code.

Design review comes before the contracts are finished, while changing the trust model is still a conversation rather than a migration. The contract audit comes at feature freeze, not before it, so the reviewed commit resembles the shipped one. Formal verification runs against the verification routine once its interface has stopped moving, since the properties are written against a signature. Infrastructure and key custody work can run in parallel with all of it, because it reviews a different system and does not wait on the code. Deployment verification happens in the window between deploying and announcing. Everything else begins the day it goes live.

The expensive mistake is a single engagement a fortnight before launch, covering the contracts only, with the report delivered after the marketing date is public. At that point findings arrive with nowhere to go.

ScopeWhat it coversWhen
Design reviewTrust model, who can convince the destination, what fails when a chain haltsBefore contracts are final
Contract auditSource and destination code, on every chain supportedAt feature freeze
Formal verificationMessage verification, replay prevention, threshold propertiesOnce the interface is stable
Infrastructure and penetration testRelayers, attesters, signing hosts, pipeline, cloud rolesIn parallel, before launch
Key custody reviewSigner independence, generation, storage, rotation authorityIn parallel, before launch
Deployment verificationDeployed bytecode against reviewed commit, roles, proxy targetsBetween deploy and announce
Monitoring, bounty, upgrade reviewThe running system and every change to itFrom launch, continuously

Questions

We have had a contract audit. What is still uncovered?

Typically the off-chain half and the custody arrangement, which is where the largest bridge losses originated. A contract audit establishes that the code behaves correctly given the messages it accepts. It does not establish that the parties able to produce those messages are who you believe, or that the machines holding their keys are sound.

Does one audit cover a bridge on five chains?

Only the chains the scope names. Deployments differ across chains in gas semantics, finality and precompile availability, and those differences are code that the other reviews did not read. Check what the scope statement says before assuming the sixth chain inherits the report.

Is formal verification worth it for a bridge?

For the message verification routine, more than for most components. The defects there are reached by inputs nobody wrote a test for, which is the category reading passes over and proof does not. Applying it across the whole system is a different proposition, and the properties are harder to state usefully.

We use a third-party bridge rather than operating one. Does any of this apply?

The due diligence version of it does. Accepting a wrapped asset means inheriting its issuer trust model, so the questions become what convinces that bridge destination chain, how many independent parties would have to be compromised to forge a message, and what happens to your position if it halts.

The work behind this

Related reading