Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ SAFE_MANAGEMENT_DIR = $(network)/$(shell date +'%Y-%m-%d')-safe-swap-owner
FUNDING_DIR = $(network)/$(shell date +'%Y-%m-%d')-funding
SET_BASE_BRIDGE_PARTNER_THRESHOLD_DIR = $(network)/$(shell date +'%Y-%m-%d')-pause-bridge-base
PAUSE_BRIDGE_BASE_DIR = $(network)/$(shell date +'%Y-%m-%d')-pause-bridge-base
SWITCH_TO_PERMISSIONED_GAME_DIR=$(network)/$(shell date +'%Y-%m-%d')-switch-to-permissioned-game

TEMPLATE_GENERIC = setup-templates/template-generic
TEMPLATE_GAS_INCREASE = setup-templates/template-gas-increase
Expand All @@ -15,6 +16,7 @@ TEMPLATE_SAFE_MANAGEMENT = setup-templates/template-safe-management
TEMPLATE_FUNDING = setup-templates/template-funding
TEMPLATE_SET_BASE_BRIDGE_PARTNER_THRESHOLD = setup-templates/template-set-bridge-partner-threshold
TEMPLATE_PAUSE_BRIDGE_BASE = setup-templates/template-pause-bridge-base
TEMPLATE_SWITCH_TO_PERMISSIONED_GAME = setup-templates/template-switch-to-permissioned-game

ifndef $(GOPATH)
GOPATH=$(shell go env GOPATH)
Expand Down Expand Up @@ -63,6 +65,10 @@ setup-bridge-pause:
rm -rf $(TEMPLATE_PAUSE_BRIDGE_BASE)/cache $(TEMPLATE_PAUSE_BRIDGE_BASE)/lib $(TEMPLATE_PAUSE_BRIDGE_BASE)/out
cp -r $(TEMPLATE_PAUSE_BRIDGE_BASE) $(PAUSE_BRIDGE_BASE_DIR)

setup-switch-to-permissioned-game:
rm -rf $(TEMPLATE_SWITCH_TO_PERMISSIONED_GAME)/cache $(TEMPLATE_SWITCH_TO_PERMISSIONED_GAME)/lib $(TEMPLATE_SWITCH_TO_PERMISSIONED_GAME)/out
cp -r $(TEMPLATE_SWITCH_TO_PERMISSIONED_GAME) $(SWITCH_TO_PERMISSIONED_GAME_DIR)

##
# Solidity Setup
##
Expand Down
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ To execute a new task, run one of the following commands (depending on the type
- For funding tasks: `make setup-funding network=<network>`
- For updating the partner threshold in Base Bridge: `make setup-bridge-partner-threshold network=<network>`
- For pausing / un-pausing Base Bridge: `make setup-bridge-pause network=<network>`
- For switching to a permissioned game and retiring dispute games: `make setup-switch-to-permissioned-game network=<network>`

Next, `cd` into the directory that was created for you and follow the steps listed below for the relevant template.

Expand Down Expand Up @@ -172,3 +173,17 @@ This template is used to pause or un-pause [Base Bridge](https://github.com/base
1. Generate the validation file for signers with `make gen-validation`.
1. Check in the task when it's ready to sign and request the facilitators to collect signatures from signers.
1. Once executed, check in the records files and mark the task `EXECUTED` in the README.

## Using the Switch to Permissioned Game template

This template is used to switch Base to a Permissioned Game.

1. Ensure you have followed the instructions above in `setup`.
1. Run `mmake setup-switch-to-permissioned-game network=<network>` and go to the folder that was created by this command.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
1. Run `mmake setup-switch-to-permissioned-game network=<network>` and go to the folder that was created by this command.
1. Run `make setup-switch-to-permissioned-game network=<network>` and go to the folder that was created by this command.

1. Specify the commit of [Optimism code](https://github.com/ethereum-optimism/optimism) and [Base contracts code](https://github.com/base/contracts) you intend to use in the `.env` file.
1. Run `make deps`.
1. Ensure only the Sepolia or Mainnet variables are in the `.env` file depending on what network this task is for.
1. Build the contracts with `forge build`.
1. Generate the validation file for signers with `make gen-validation`.
1. Check in the task when it's ready to sign and request the facilitators to collect signatures from signers.
1. Once executed, check in the records files and mark the task `EXECUTED` in the README.
25 changes: 25 additions & 0 deletions setup-templates/template-switch-to-permissioned-game/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
OP_COMMIT=
BASE_CONTRACTS_COMMIT=

RECORD_STATE_DIFF=true

# Mainnet Config
SYSTEM_CONFIG=0x73a79Fab69143498Ed3712e519A88a918e1f4072

# Optimism Guardian Multisig (controls Anchor State Registry)
OWNER_SAFE=0x09f7150D8c019BeF34450d6920f6B3608ceFdAf2
# Owner of Optimism Guardian Multisig
OP_SECURITY_COUNCIL_SAFE=0xc2819DC788505Aac350142A7A707BF9D03E3Bd03

SENDER=0x1822b35B09f5ce1C78ecbC06AC0A4e17885b925e # used to simulate

# #Sepolia Config
#SYSTEM_CONFIG=0xf272670eb55e895584501d564AfEB048bEd26194

# #Optimism Guardian Multisig (controls Anchor State Registry)
#OWNER_SAFE=0x7a50f00e8D05b95F98fE38d8BeE366a7324dCf7E
# #Owner of Optimism Guardian Multisig
#OP_SECURITY_COUNCIL_SAFE=0xf64bc17485f0B4Ea5F06A96514182FC4cB561977

# # used to simulate
#SENDER=0x1084092Ac2f04c866806CF3d4a385Afa4F6A6C97
33 changes: 33 additions & 0 deletions setup-templates/template-switch-to-permissioned-game/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
include ../../Makefile
include ../../Multisig.mk

include ../.env
include .env

ifndef LEDGER_ACCOUNT
override LEDGER_ACCOUNT = 0
endif

RPC_URL = $(L1_RPC_URL)
SCRIPT_NAME = SwitchToPermissionedGame

.PHONY: gen-validation
gen-validation: checkout-signer-tool run-script

.PHONY: run-script
run-script:
cd $(SIGNER_TOOL_PATH); \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There must be an empty validations/ directory added to the root of this task sub-directory, otherwise this error occurs when running make gen-validation:

119 |   const sdc = new StateDiffClient();
120 |   const { result } = await sdc.simulate(opts.rpcUrl, forgeCmdParts, workdir);
121 | 
122 |   if (opts.out) {
123 |     const outPath = path.resolve(process.cwd(), opts.out);
124 |     writeFileSync(outPath, JSON.stringify(result, null, 2) + '\n');
          ^
ENOENT: no such file or directory, open '/Users/user/contract-deployments/mainnet/2025-11-07-switch-to-permissioned-game/validations/op-signer.json'
    path: "/Users/user/contract-deployments/mainnet/2025-11-07-switch-to-permissioned-game/validations/op-signer.json",
 syscall: "open",
   errno: -2,
    code: "ENOENT"

      at main (/Users/user/contract-deployments/mainnet/2025-11-07-switch-to-permissioned-game/signer-tool/scripts/genValidationFile.ts:124:5)
Suggested change
cd $(SIGNER_TOOL_PATH); \
mkdir validations; \
cd $(SIGNER_TOOL_PATH); \

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lines 19 and 20 need to switch order (as in my example above), since the validations/ sub-directory must exist at the task's root.

mkdir validations; \
npm ci; \
bun run scripts/genValidationFile.ts --rpc-url $(L1_RPC_URL) \
--workdir .. --forge-cmd 'forge script --rpc-url $(L1_RPC_URL) \
Comment on lines +22 to +23
Copy link
Contributor

@leopoldjoy leopoldjoy Nov 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we already created the RPC_URL variable in this file:

Suggested change
bun run scripts/genValidationFile.ts --rpc-url $(L1_RPC_URL) \
--workdir .. --forge-cmd 'forge script --rpc-url $(L1_RPC_URL) \
bun run scripts/genValidationFile.ts --rpc-url $(RPC_URL) \
--workdir .. --forge-cmd 'forge script --rpc-url $(RPC_URL) \

$(SCRIPT_NAME) --sig "sign(address[])" ["$(OP_SECURITY_COUNCIL_SAFE)"] --sender $(SENDER)' --out ../validations/op-signer.json;

.PHONY: approve-op
approve-op:
$(call MULTISIG_APPROVE,$(OP_SECURITY_COUNCIL_SAFE),$(SIGNATURES))

# Execute
.PHONY: execute
execute:
$(call MULTISIG_EXECUTE,0x)
48 changes: 48 additions & 0 deletions setup-templates/template-switch-to-permissioned-game/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Switch to Permissioned Games

Status: READY TO SIGN

## Description

Switches Base to Permissioned Fault Dispute Games and retires existing games.

## Install dependencies

### 1. Update foundry

```bash
foundryup
```

### 2. Install Node.js if needed

First, check if you have node installed

```bash
node --version
```

If you see a version output from the above command, you can move on. Otherwise, install node

```bash
brew install node
```

## Sign Task

### 1. Update repo:

```bash
cd contract-deployments
git pull
```

### 2. Run the signing tool (NOTE: do not enter the task directory. Run this command from the project's root).

```bash
make sign-task
```

### 3. Open the UI at [http://localhost:3000](http://localhost:3000)

### 4. Send signature to facilitator
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
### 4. Send signature to facilitator
### 4. Send signature to facilitator
You may now kill the Signer Tool process in your terminal window by running `Ctrl + C`.

20 changes: 20 additions & 0 deletions setup-templates/template-switch-to-permissioned-game/foundry.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[profile.default]
src = 'src'
out = 'out'
libs = ['lib']
broadcast = 'records'
fs_permissions = [{ access = "read-write", path = "./" }]
optimizer = true
optimizer_runs = 200
via-ir = false
remappings = [
'@eth-optimism-bedrock/=lib/optimism/packages/contracts-bedrock/',
'@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts',
'@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts',
'@rari-capital/solmate/=lib/solmate/',
'@base-contracts/=lib/base-contracts',
'solady/=lib/solady/src/',
'@lib-keccak/=lib/lib-keccak/contracts/lib',
]

# See more config options https://github.com/foundry-rs/foundry/tree/master/config
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;

import {Vm} from "forge-std/Vm.sol";
import {IMulticall3} from "forge-std/interfaces/IMulticall3.sol";
import {IAnchorStateRegistry} from "@eth-optimism-bedrock/src/dispute/FaultDisputeGame.sol";
import {SystemConfig} from "@eth-optimism-bedrock/src/L1/SystemConfig.sol";
import {DisputeGameFactory} from "@eth-optimism-bedrock/src/dispute/DisputeGameFactory.sol";
import {FaultDisputeGame} from "@eth-optimism-bedrock/src/dispute/PermissionedDisputeGame.sol";
import {GameTypes, GameType} from "@eth-optimism-bedrock/src/dispute/lib/Types.sol";
import {MultisigScript} from "@base-contracts/script/universal/MultisigScript.sol";
import {Simulation} from "@base-contracts/script/universal/Simulation.sol";

/// @notice This script updates the respectedGameType and retires existing games in the AnchorStateRegistry.
contract SwitchToPermissionedGame is MultisigScript {
// TODO: Confirm expected version
string public constant EXPECTED_VERSION = "1.4.1";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is this EXPECTED_VERSION variable used?


address public immutable OWNER_SAFE;

SystemConfig internal immutable _SYSTEM_CONFIG = SystemConfig(vm.envAddress("SYSTEM_CONFIG"));

IAnchorStateRegistry anchorStateRegistry;

constructor() {
OWNER_SAFE = vm.envAddress("OWNER_SAFE");
}

function setUp() public {
DisputeGameFactory dgfProxy = DisputeGameFactory(_SYSTEM_CONFIG.disputeGameFactory());
FaultDisputeGame currentFdg = FaultDisputeGame(address(dgfProxy.gameImpls(GameTypes.CANNON)));
anchorStateRegistry = currentFdg.anchorStateRegistry();
}

// Confirm the retirementTimestamp is updated to the block time and the
// respectedGameType is updated to PERMISSIONED_CANNON.
function _postCheck(Vm.AccountAccess[] memory, Simulation.Payload memory) internal view override {
require(anchorStateRegistry.retirementTimestamp() == block.timestamp, "post-110");
require(
GameType.unwrap(anchorStateRegistry.respectedGameType()) == GameType.unwrap(GameTypes.PERMISSIONED_CANNON),
"post-111"
);
}

function _buildCalls() internal view override returns (IMulticall3.Call3Value[] memory) {
IMulticall3.Call3Value[] memory calls = new IMulticall3.Call3Value[](2);

calls[0] = IMulticall3.Call3Value({
target: address(anchorStateRegistry),
allowFailure: false,
callData: abi.encodeCall(IAnchorStateRegistry.setRespectedGameType, (GameTypes.PERMISSIONED_CANNON)),
value: 0
});

calls[1] = IMulticall3.Call3Value({
target: address(anchorStateRegistry),
allowFailure: false,
callData: abi.encodeCall(IAnchorStateRegistry.updateRetirementTimestamp, ()),
value: 0
});

return calls;
}

function _ownerSafe() internal view override returns (address) {
return OWNER_SAFE;
}
}
Loading