title | description | lang | content_type | topic | personas | categories | is_imported_content | ||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Migrating to permissionless fault proofs on OP Stack |
A high-level guide for transitioning from permissioned to permissionless fault proofs on an OP Stack. |
en-US |
tutorial |
migrating to permissionless fault proofs on OP Stack |
|
|
false |
import { Callout } from 'nextra/components'
This guide provides a high-level overview for chain operators looking to transition their OP Stack from permissioned to permissionless fault proofs. It's designed to be accessible for technical decision makers while providing sufficient detail for implementation teams.
The OP Stack architecture uses Fault Proofs to ensure the validity of withdrawals from L2 to L1.
The validity of transactions on L2 is handled by the node's consensus rules.
Transitioning from permissioned to permissionless proofs represents a significant security upgrade, allowing any participant to propose and challenge state output roots.
Permissioned games previously relied on a single trusted validator—typically the proposer configured in the PermissionedDisputeGame
, usually the network's only sequencer.
This migration involves several key components:
- Configuring security-critical dispute monitoring services
- Deploying and configuring smart contracts using op-deployer
- Testing the new system before activation
- Setting the respected game type to permissionless fault proofs, specifically using the
FaultDisputeGame
Before beginning this transition, your chain should:
- Be running a standard OP Stack implementation
- Be operating with the recommended infrastructure services including
op-challenger
andop-dispute-mon
The op-challenger
and op-dispute-mon
services are critical security components that participate in the dispute game process to challenge invalid proposals and monitor active games.
Upgrade to the latest release, which contains important improvements to simplify the upgrade process.
# Example upgrade command (implementation may vary based on your deployment)
git clone https://github.com/ethereum-optimism/optimism -b op-challenger/v1.3.3 --recurse-submodules
cd optimism
make op-challenger
Configure op-challenger
to load your chain configuration. Even if your chain is not included in the superchain-registry, you can specify a custom configuration:
# For chains in the registry
--network <chain-name>
# For chains not in the registry, provide a path to your rollup configuration
--network-config /path/to/your/network-config.json
Configure op-challenger
to support both permissioned and permissionless games by setting:
--trace-type permissioned,cannon
Or by setting the environment variable:
OP_CHALLENGER_TRACE_TYPE=permissioned,cannon
Replace the --cannon-prestate
flag with --prestates-url
, which points to a source containing all required prestates:
--prestates-url <URL_TO_PRESTATES_DIRECTORY>
The URL can use http
, https
, or file
protocols. Each prestate should be named as <PRESTATE_HASH>.json
or <PRESTATE_HASH>.bin.gz
.
You'll need at least two prestates:
- The prestate currently used for permissioned games
- A new prestate matching the
faultGameAbsolutePrestate
configuration for permissionless games
For chains not in the Superchain Registry, you need to build custom prestates with your chain's configuration:
git clone https://github.com/ethereum-optimism/optimism --recurse-submodules
cd optimism
# To build a specific prestate (e.g., for op-program/v1.5.0)
git checkout op-program/v1.5.0
make reproducible-prestate
# Generate the prestate with your chain's specific configuration
./op-program/bin/op-program \
--l2.genesis /path/to/your/l2-genesis.json \
--rollup.config /path/to/your/rollup-config.json \
--network.l2chainid <YOUR_L2_CHAIN_ID> \
--exec.prestate
The prestate will typically be generated at:
op-program/bin/prestate.json
(for older versions)op-program/bin/prestate.bin.gz
(for intermediate versions)op-program/bin/prestate-mt64.bin.gz
(for chains upgraded to Cannon MT64, starting from upgrade 14)
Bonds are required for both permissioned and permissionless games. However, with permissioned games, you typically don't post claims regularly, making bond requirements less noticeable. In contrast, the challenger in permissionless games will frequently need to post bonds with each claim it makes. Therefore, ensure your challenger has sufficient funds available.
As a general guideline:
- Maintain a minimum balance of 50 ETH
- Have access to a large pool of ETH for potential attack scenarios
- Implement monitoring to ensure sufficient funds are always available
Ensure op-dispute-mon
is properly configured by following these steps
This section requires privileged actions by the ProxyAdminOwner
and may involve the Guardian
role depending on your security setup.
OPCM is the recommended tool for safely managing OP Stack upgrades:
# Install OPCM <TODO>
# Configure OPCM with your chain's information
cp config.example.json config.json
# Edit config.json with your chain's specific addresses and parameters
Execute the following smart contract changes in a single bundled transaction:
-
Call
setImplementation
on theDisputeGameFactoryProxy
to:- Set the implementation for the new permissionless
FaultDisputeGame
(game type0
) - Upgrade the permissioned game to the new
PermissionedDisputeGameAddress
(game type1
) with the updated absolute prestate
# Using OPCM to manage the upgrades <TODO>
- Set the implementation for the new permissionless
-
Upgrade the
AnchorStateRegistryProxy
(pre-Upgrade 13 only):After upgrade 13 (FP incident response improvements), this step is no longer required, as a single anchor state is shared across all game types. Before upgrade 13, perform the following:
- First upgrade the proxy to point to the
StorageSetter
contract and clear the initialized flag. - Then upgrade back to the
AnchorStateRegistry
implementation - Call
initialize
with the anchor state for the new game type
- First upgrade the proxy to point to the
# First upgrade to the StorageSetter to clear initialization flag <TODO>
- Initialize bond amounts for each game type to exactly 0.08 ETH:
# Set bond amounts for both game types <TODO>
Post-upgrade 13, the anchor state for permissionless games automatically matches the current anchor state used by permissioned games, since there's only one shared anchor state. Specifying this explicitly is redundant but harmless.
This migration requires actions by privileged roles in your system:
-
The ProxyAdmin Owner has the authority to upgrade proxy contracts.
-
The Guardian has emergency powers like pausing withdrawals and changing the respected game type.
For detailed information about privileged roles and their security implications, refer to the privileged roles documentation.
After you've set the permissionless FaultDisputeContract
implementations on the DisputeGameFactory
and before you set the respected game type to it; you can test your off-chain services in the cold path.
Create a valid proposal using the permissionless game type 0
:
-
Ensure the proposal is from a block at or before the
safe
head:cast block --rpc-url <OP_GETH_ENDPOINT> safe
-
Get a valid output root:
cast rpc --rpc-url <OP_NODE_ENDPOINT> optimism_outputAtBlock \ $(cast 2h <BLOCK_NUMBER>) | jq -r .outputRoot
-
Create a test game:
./op-challenger/bin/op-challenger create-game \ --l1-eth-rpc=<L1_RPC_ENDPOINT> \ --game-factory-address <DISPUTE_GAME_FACTORY_ADDR> \ --l2-block-num <BLOCK_NUMBER> \ --output-root <OUTPUT_ROOT> \ <SIGNER_OPTIONS>
-
Verify:
op-challenger
logs a message showing the game is in progressop-challenger
doesn't post a counter claim (as this is a valid proposal)dispute-mon
includes the new game withstatus="agree_defender_ahead"
Post an invalid counter claim to the valid proposal created above:
./op-challenger/bin/op-challenger move \
--l1-eth-rpc <L1_RPC_ENDPOINT> \
--game-address <GAME_ADDR> \
--attack \
--parent-index 0 \
--claim 0x0000000000000000000000000000000000000000000000000000000000000000 \
<SIGNER_OPTIONS>
Verify that op-challenger
posts a counter-claim to the invalid claim. You can view claims using:
./op-challenger/bin/op-challenger list-claims \
--l1-eth-rpc <L1_RPC_ENDPOINT> \
--game-address <GAME_ADDR>
There should be 3 claims in the game after this test.
After completing all previous steps and verifying their successful operation:
-
Set the
respectedGameType
on theOptimismPortal
toCANNON
(game type0
) using OPCM:opcm set-respected-game-type \ --game-type 0
-
Configure
op-proposer
to create proposals using the permissionlesscannon
game type:# Change from game-type 1 to 0 --game-type 0
Or via environment variable:
OP_PROPOSER_GAME_TYPE=0
- Optimism Fault Proof Documentation
- Privileged Roles Documentation
- L2Beat OP Mainnet Upgrades
- op-challenger GitHub
- op-dispute-mon GitHub
Transitioning to permissionless proofs represents a significant security improvement for your OP Stack chain. This transition decentralizes the validation process, allowing any participant to challenge invalid withdrawal claims rather than relying on a limited set of trusted validators.
By following this guide, you'll be able to safely configure and test your system before making the switch to permissionless proofs. Remember to thoroughly test each service before proceeding to the next step, and ensure that your security monitoring is properly configured to track the health of the system after the transition.