Skip to main content

BoLD: a technical deep dive

Arbitrum's former dispute protocol involved defending against challengers individually in a 1-vs-1 tournament setting. In contrast, BoLD enables an all-vs-all battle royale between good and evil, with a single deterministic winner.

BoLD’s time-bounded, permissionless validation makes this dynamic possible through deterministic Merkle proofs and hashes. This allows any party to place a bond on the correct state and prove their claim through interactive fraud proofs, ensuring that a single honest party that bonds on the correct state will always win a dispute.

Validators on Arbitrum can post their claim on the validity of state roots, known as assertions. Ethereum does not know anything about the validity of these Arbitrum state roots, but it can help prove their correctness. Anyone can initiate a challenge against any unconfirmed assertion.

The disputed assertions concern block hashes on an Arbitrum chain at a given batch or inbox position. Because Arbitrum chains are deterministic, only one history is correct for anyone running the standard Nitro software. Using the notion of a one-step proof, Ethereum can check whether someone is making a fraudulent assertion after an interactive game narrows down a dispute to a single winner.

If a claim is honest, Ethereum can confirm it after a 6.4 day period (the DAO can change this period). If a claim is malicious, anyone who knows the correct Arbitrum state can challenge it within that 6.4-day window and always win within a challenge period (plus a small delta).

The current implementation of BoLD involves both onchain and offchain components:

  1. Rollup contracts deployed on Ethereum
  2. New challenge management contracts deployed on Ethereum
  3. Honest validator software equipped to submit assertions and perform challenges on any assertions it disagrees with.

How BoLD leverages Ethereum

To implement the BoLD protocol, it must be deployed on a credible, neutral, censorship-resistant backend to ensure fairness for all participants. Ethereum fits the requirements, as it's currently the most decentralized, secure, smart contract-enabled blockchain to which the full protocol can be deployed, with challenge moves performed as transactions to the protocol's smart contracts.

A helpful mental model for understanding the system is: Ethereum itself is the referee for deciding assertion results. Participants in the challenge protocol can disagree over the results of the child-chain state transitions and provide proofs to the protocol's smart contracts on Ethereum to determine which result is correct. Because computation is deterministic, there will always be a single correct result.

Transaction lifecycle diagram showing various pathways for submitting transactions

From the Nitro whitepaper. Parent chain blocks are “settled to the parent chain” after a 6.4 day period has elapsed and nobody has challenged their validity on Ethereum.

In effect, a miniature Arbitrum state-transition VM is deployed as an Ethereum smart contract to prove which assertions are correct. However, computation on Ethereum is expensive, so this mini-VM is built to handle "one-step proofs" consisting of a single step of WebAssembly (WASM) code. The Arbitrum state transition logic, written in Golang, is also compiled to WASM and will therefore obtain the same results as the VM found in the onchain smart contract. The protocol's soundness depends on the assumption that computation is deterministic and equivalent between the onchain VM and the Golang state transition compiled to WASM.

All participants in the protocol have a local state from which they can produce valid proofs, and all honest parties will have the same local state. However, malicious entities can deviate from the honest parties in attempts to confirm invalid states through the protocol. The protocol and the honest validator client's job is to ensure honest parties always win against any number of malicious participants by always claiming the absolute truth.

Assertions

A key responsibility for Arbitrum proposers is to regularly post claims about the Arbitrum chains’ state to Ethereum at certain checkpoints. These are known as assertions (called child-chain state roots). Assertions contain data, most critically:

  1. The child chain block hash being claimed.
  2. A "history commitment" combining hashes of the chain's intermediate state after every block the assertion covers. This is essentially a Merkle-like data structure, a tree from which the asserter only needs to provide the root when posting the assertion.
  3. The batch number it corresponds to for the Arbitrum chain.
  4. The number of messages in the Arbitrum Sequencer inbox at the time the assertion is created.

The assertion to be posted onchain must consume the specified number of inbox messages from the previous assertion. There is a required delay measured in blocks of the first non-Arbitrum ancestor chain (i.e., Ethereum blocks for L2 chains and L3 chains settling to an Arbitrum chain, and parent chain blocks for chains settling to a non-Arbitrum L2 chain) for assertion posting. Currently, this value is set to equal one hour for BoLD.

Anyone can confirm assertions after 6.4 days if they have not been challenged. In particular, assertions help with withdrawing from Arbitrum back to Ethereum. Arbitrum withdrawals require specifying a blockhash, which must be confirmed onchain as an assertion. This is why withdrawals have a 6.4 day delay if they are not actively challenged.

Validators must become proposers in the rollup contract before they can post assertions. For Arbitrum One and Arbitrum Nova, this involves placing a one-time bond of 3600 WETH, locked in the contract until they choose to withdraw. Validators can only withdraw their bond once the protocol confirms their latest bonded assertion. Posting a new assertion does not require a new bond; instead, the protocol "moves" a validator's bond to their latest posted assertion.

Assertions form a chain where there can be forks. For instance, a validator might disagree on the history commitment of block state hashes, which an assertion contains. All Arbitrum Nitro nodes are configured to warn users if they observe an assertion they disagree with posted onchain.

However, suppose a node is configured as a validator and has deposited a bond to the Rollup contract. In that case, that validator can post the correct rival assertion to any invalid one it observes. The validator can also initiate a challenge by posting a challenge bond and other data to the ChallengeManager, signaling that it is disputing an assertion.

Overflow assertions

Given the mandatory delay of one hour between assertions posted onchain, and that each assertion is a claim to a specific Arbitrum batch, there could be a very large number of blocks between assertions. However, a single assertion supports at most 2^26 Arbitrum blocks since the previous assertion. If this value overflows, one or more follow-up overflow assertions need to be posted to consume the rest of the blocks above the maximum. This overflow assertion will not be subject to the mandatory one-hour delay between assertions.

Trustless bonding pools

A large upfront assertion bond is critical to discourage malicious actors from attacking Arbitrum and spamming the network (e.g., delay attacks), especially because malicious actors will always lose challenges and their entire bond. On the other hand, requiring such a high upfront assertion bond may be prohibitive for a single honest entity to put up—since the cost to defend Arbitrum is proportional to the number of malicious entities and ongoing challenges at any given point in time.

To address this, a staking (bond) pool contract lets anyone deploy a trustless bonding pool to crowdsource funds from others who want to help defend Arbitrum but may not be able to post the sizable upfront bond themselves.

Anyone can deploy an assertion bonding pool using the AssertionStakingPoolCreator.sol contract to crowdsource bonding funds for an assertion. To defend Arbitrum using one of these pools, an entity would first deploy this pool with the assertion they believe is correct and wish to bond on to challenge an adversary's assertion. Then, anyone can verify that the claimed assertion is correct by running the inputs through their node's State Transition Function (STF).

If other parties agree that the assertion is correct, they can deposit their funds into the contract. When enough funds have been deposited, anyone can trigger the creation of the assertion onchain to start the challenge in a trustless manner. Once the dispute protocol confirms the honest parties' assertion, all participants who contributed to the bonding pool will be promptly reimbursed and able to withdraw their funds.

With bonding pools

There is no minimum WETH requirement, and once the entire bond amount is raised (either 3600, 555, or 79 ETH for Arbitrum One), anyone can post the assertion trustlessly. Additionally, the Nitro node validator software includes an optional feature that enables both automatic deployment of a bonding pool contract and depositing funds to challenge an observed invalid assertion.

Trustless bonding pools can also be created to open challenges and make moves on challenges without sacrificing decentralization.

Opening challenges

To initiate a challenge, the assertion chain must first fork within the Arbitrum Rollup contracts. However, a challenge actually starts when you create an edge claim and post it to the ChallengeManager contract on the parent chain.

If there is a fork in the assertion chain (a "top-level" dispute), anyone can begin a challenge by creating a challenge edge. No bond is needed: each branch of the fork has a unique assertion, with an attached bond, and that assertion contains enough information to uniquely determine its challenge edge; that is, there is no "wiggle room" that an adversary can use to create multiple challenge edges from a single assertion (if this were possible, it could lead to spam attacks on the protocol).

Anyone can open a sub-challenge on an assertion without needing to be a bonder in the Rollup contract, so long as they post a challenge bond and an edge claiming intent to start the challenge. This challenge bond is much lower than the one required to become an assertion proposer. Challenges aren't tied to specific addresses or parties; anyone can participate.

Recall that a challenge is a fundamental disagreement about an assertion posted to the Arbitrum chain. At its core, validators disagree about the blockhash at a certain block number, and the BoLD protocol lets them interactively narrow that disagreement via fraud proofs so Ethereum can be the final referee and declare a winner.

At its core, the disagreement between validators looks something like this:

  • Common parent assertion: batch 5, blockhash 0xabc
  • Alice's assertion: batch 10, blockhash 0x123
  • Bob's assertion: batch 10, blockhash 0x456

Their disagreement is about an Arbitrum block somewhere between batch 5 and batch 10. Here’s how the actual challenge begins in this example:

Validators have to fetch all blocks between batch 5 and batch 10 and create a Merkle commitment out of them as a Merkle tree with 2^26+1 leaves. If there are fewer than 2^26 blocks between the assertions, the last block is repeated to pad the leaves of the tree to that value. Validators then create an “edge” data structure, which contains the following fields:

  • start_hash: the start_hash of the claimed assertion and is also the end_hash of the previous assertion
  • end_hash: the end hash of the last block in the child assertion that a validator claims is correct.
  • merkle_root: the Merkle root that results from committing to a Merkle tree from the start block hash to the end block hash
  • inclusion_proofs: Merkle proofs that the end hashes are indeed leaves of the Merkle tree committing to a root

The concept of a history commitment is at the core of challenges and BoLD itself.

The validators above provide a Merkle proof of their commitment to some history. In this case, all the Arbitrum block hashes from batch 5 to batch 10. Using this tree, validators can narrow their disagreement to a single block by iteratively bisecting the Merkle root and creating edges that have their own history commitments for each half of the tree.

Challenge resolution

The fundamental unit in a challenge is an edge data structure.

Initiation

The first validator to create an edge initiates a challenge. The smart contracts validate the Merkle inclusion proofs and hashes provided to prove that the challenge targets a specific fork in the assertion chain in the Rollup contract.

Bisections

When an edge is created, it claims some history from point A to point B, which validators can agree or disagree on. Other validators can claim some history from point A to B', where B' is a different end state. A history commitment is a Merkle commitment to a list of hashes.

To narrow down a disagreement, validators have to figure out what exact hash they disagree with. To do this, the game essentially takes turns between validators playing binary search. Each move is known as a "bisection" because it splits a history commitment in half. For an interactive walkthrough that replays real onchain bisections, see How BoLD bisection works.

For instance:

  • Alice commits to 33 hashes with start = A, end = B
  • Bob commits to 33 hashes with start = A, end = B'

Either of them can perform a "bisection" move on their edge. For instance, if Alice "bisects" her edge E, the bisection transaction will produce two children, E_1 and E_2. E_1 commits to 17 hashes from height A to B/2, and E_2 commits to 17 hashes from height B/2 to B.

A validator can make a bisection move on an edge as long as that edge is "rivaled," meaning that there is another edge with a conflicting claim.

Sub-challenges

The number of execution steps at which validators could disagree within a single Arbitrum block has a max of 2^42. Playing a game of bisections on this number of hashes would be unreasonable from a space requirement standpoint, as each history commitment would require 4.35TB worth of hashes. Instead, BoLD plays the bisection game over different levels of granularity within this space of 2^42 hashes, which we call sub-challenges and can view as recursive execution of the dispute resolution process.

As a reminder, the bisection game is an iterative and interactive process. The first sub-challenge is at the block level, where validators disagree over Arbitrum blocks between two assertions. The disagreeing validators create "edges" containing history commitments to all the blocks in between those two assertions, which is a maximum of 2^26 child chain blocks, and start the bisection game. As they progressively narrow down to a single block of disagreement, the validators begin the next phase of the challenge process by opening a sub-challenge over up to 2^19 BigSteps, each representing 2^23 steps of WASM execution. Once they reach a single disagreement at the BigStep level, they open a final sub-challenge over up to 2^23 SmallSteps, each a single step of WASM execution. The bisection game is the same at each sub-challenge level, and opening a sub-challenge requires placing another "challenge bond." Challenge bond magnitudes differ at each sub-challenge level. See How BoLD bisection works for a visual replay of these levels in action.

One step proof

Once validators reach a single step of disagreement at the deepest sub-challenge level, they need to provide something called a One Step Proof, or OSP. This proof shows WASM execution and demonstrates that running the Arbitrum State Transition Function (STF) at machine hash A leads to machine hash B. The parent chain, like Ethereum for Arbitrum One, then runs a WASM emulator using a smart contract for this step and declares a winner. An evil party cannot forge a one-step proof, and unless there is a critical bug in the smart contract, the honest party will always win.

At this stage, the honest party's one-step proven edge is confirmed, leaving the dishonest party with no further actions to take. Next, the honest party's "branch" of edges, from the top to the one-step proven edge, will have an ever-increasing timer until the top edge is confirmed by time.

Timers

Once a validator creates an edge, if no rival edge contests it, that edge gets a timer that ticks up called its unrivaled timer. Time in the protocol is measured in blocks of the first non-Arbitrum ancestor chain (that is, Ethereum blocks for L2 chains and L3 chains settling to an Arbitrum chain, and parent chain blocks for chains settling to a non-Arbitrum L2 chain), and block numbers are used. An edge's timer stops ticking when a rival edge is created onchain.

Edges also have an inherited timer, which is the sum of its unrivaled timer + the minimum inherited timer of an edge's children (recursive definition). Once one of the top-level edges that initiated a challenge has achieved an inherited timer >= a CHALLENGE_PERIOD, it can be confirmed. At this point, its assertion can also be confirmed, as its associated challenge has completed. A minor but important detail is that edges also inherit the time their claimed assertion was unrivaled.

Feel free to read the BoLD whitepaper for more details around how timers are tracked.

Cached timer updates

An edge's "inherited timer" value exists onchain and can be updated via a transaction. Given it is a recursive definition, it can be updated via multiple transactions. First, the lowermost edges have their timers updated, then their parents, etc., up to the top. Validators can track information locally to avoid sending wasteful transactions and only propagate updates once they are confident their edge is confirmable by time.

Confirmation

Once an edge has a total onchain timer greater than or equal to a challenge period, it can be confirmed via a transaction. Not all edges need to be confirmed onchain; the top-level block challenge edge is enough to confirm the claimed assertion and resolve a dispute. A challenge is not complete with a one-step proof alone. It is only complete once the claimed assertion is confirmed by time.

Bonding in challenges

To create a challenge, there must be a fork in the Arbitrum assertion chain smart contract. A validator that wishes to initiate a challenge must then post an "edge" claiming a history of block hashes from the previous assertion to the claimed assertion they believe is correct. To do so, they must post a value called a "challenge bond." Note that to open a new assertion-level challenge, no challenge bond needs to be posted. This is because top-level assertions already contain enough information to uniquely determine their corresponding challenge edge (which contains a hash of this history), and have already been bonded on.

Challenge bonds are named as such because they are required to open challenges. The mechanism of how challenge bond economics are decided is contained in the Economics of Disputes, which also explains the cost profile and spam prevention in BoLD. In short, the actual cost of a bond encompasses many costs associated with participating in the dispute game. For further details on bond sizes and their calculation methods, refer to the aforementioned document.

Each sub-challenge requires a challenge bond deposit. For Arbitrum One, the first unrivaled edge's bond is held in the challenge manager contract on Ethereum, while subsequent rival bonds are held in an excess bond receiver address. Once a challenge is complete, all bonds for an honest party are automatically refunded in-protocol, while all confiscated bonds are sent to the ArbitrumDAO treasury. It is important not to offer the majority of the bonds confiscated from dishonest parties to honest parties to avoid perverse incentives, such as griefing attacks in self-challenges, or to discourage needless competition between honest parties.

Reimbursements of bonds

The reimbursement of assertion bonds and challenge bonds for honest parties will be handled “in-band” by the protocol. Please see Economics of Disputes for more information about this topic.

Upgrade mechanism

To deploy BoLD on an Arbitrum chain, an upgrade admin action must be taken using an UpgradeExecutor pattern. This smart contract acts on behalf of the rollup owner. During the upgrade, RollupCore.sol was updated to the new BoLD version, and any additional contracts required for BoLD challenges—such as EdgeChallengeManager.sol—will also be deployed on the parent chain.

Afterward, assertions will be posted to the new Rollup contract. During the upgrade period, it's possible for a substantial volume of blocks to accumulate in Arbitrum batches. For this reason, BoLD assertions support the concept of an overflow, allowing us to handle this situation effectively.

Withdrawals leading up to a BoLD upgrade

The confirmation timing for any withdrawal in flight when the BoLD upgrade is activated will be delayed until the first BoLD assertion is confirmed. When any Arbitrum chain upgrades to BoLD—including Arbitrum One and Arbitrum Nova—any pending withdrawal to Ethereum initiated before the upgrade will be delayed by one additional challenge period, plus however much time passed between the withdrawal initiation and the BoLD upgrade. This is because the upgrade effectively "resets" the challenge period for those that are not yet finalized.

For example, if the upgrade happens at time t, then a withdrawal initiated at time t-2 days will need to wait an additional 6.4 days for its withdrawal to be finalized, totaling 8.4 days of maximum delay. Withdrawals that finalize before the upgrade takes place at time t will be unaffected. In other words, the maximum delay a withdrawal will experience leading up to the upgrade is 12.8 days (two challenge periods).

The upgrade pattern for an existing Arbitrum Rollup to a BoLD-enabled one is tested extensively and run as part of each of our pull requests in the BoLD repository upgrade workflow on GitHub.