Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
a786588
init run
jjtny1 Oct 15, 2025
f761424
update only template
jjtny1 Oct 16, 2025
28bf2bd
rename to switch to permissioned game
jjtny1 Oct 16, 2025
eda82fa
update script name
jjtny1 Oct 16, 2025
9fb2d57
update readme
jjtny1 Oct 16, 2025
6a57626
fix typo
jjtny1 Oct 24, 2025
4013a7e
add postcheck for permissioned cannon
jjtny1 Oct 24, 2025
fc54b97
add gametype postcheck
jjtny1 Oct 24, 2025
88d35c9
add filled in senders for base simulation
jjtny1 Oct 24, 2025
56dd64d
Merge branch 'main' into joby.thundil/retire-games-template
jjtny1 Oct 24, 2025
1c06c68
add blacklist and rename retire
jjtny1 Oct 24, 2025
c553fca
update readmes
jjtny1 Oct 24, 2025
8db838c
add expected time to readme
jjtny1 Oct 24, 2025
23f3cb0
update game finding
jjtny1 Oct 29, 2025
6ec1146
add log statements
jjtny1 Oct 29, 2025
24e12ed
fix scripts
jjtny1 Oct 30, 2025
8839fb3
update readme
jjtny1 Oct 30, 2025
6c193ea
fix readme
jjtny1 Oct 30, 2025
15386a8
fix readme
jjtny1 Oct 30, 2025
94c1451
fix readme
jjtny1 Oct 30, 2025
a01a582
set respected game type
jjtny1 Oct 30, 2025
7384d6a
update readme
jjtny1 Oct 30, 2025
e483c92
fix makefile
jjtny1 Oct 30, 2025
f2d2846
fix makefile
jjtny1 Oct 30, 2025
c5308c9
Merge branch 'main' into joby.thundil/retire-games-template
jjtny1 Oct 30, 2025
b91345e
Merge branch 'joby.thundil/retire-games-template' into joby.thundil/b…
jjtny1 Oct 30, 2025
65e420c
add post check for permissioned
jjtny1 Oct 30, 2025
026757a
Merge branch 'main' into joby.thundil/blacklist-games-template
jjtny1 Dec 3, 2025
a52bdbd
fmt
jjtny1 Dec 3, 2025
ad4b6d2
fix readme
jjtny1 Dec 3, 2025
e69c6a7
fix main readme
jjtny1 Dec 3, 2025
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
16 changes: 11 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ SAFE_MANAGEMENT_DIR = $(network)/$(shell date +'%Y-%m-%d')-safe-management
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
SWITCH_TO_PERMISSIONED_GAME_RETIRE_DIR=$(network)/$(shell date +'%Y-%m-%d')-switch-to-permissioned-game-retire
SWITCH_TO_PERMISSIONED_GAME_BLACKLIST_DIR=$(network)/$(shell date +'%Y-%m-%d')-switch-to-permissioned-game-blacklist

TEMPLATE_GENERIC = setup-templates/template-generic
TEMPLATE_GAS_INCREASE = setup-templates/template-gas-increase
Expand All @@ -18,7 +19,8 @@ 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
TEMPLATE_SWITCH_TO_PERMISSIONED_GAME_RETIRE = setup-templates/template-switch-to-permissioned-game-retire
TEMPLATE_SWITCH_TO_PERMISSIONED_GAME_BLACKLIST = setup-templates/template-switch-to-permissioned-game-blacklist

ifndef $(GOPATH)
GOPATH=$(shell go env GOPATH)
Expand Down Expand Up @@ -72,9 +74,13 @@ 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)
setup-switch-to-permissioned-game-retire:
rm -rf $(TEMPLATE_SWITCH_TO_PERMISSIONED_GAME_RETIRE)/cache $(TEMPLATE_SWITCH_TO_PERMISSIONED_GAME_RETIRE)/lib $(TEMPLATE_SWITCH_TO_PERMISSIONED_GAME_RETIRE)/out
cp -r $(TEMPLATE_SWITCH_TO_PERMISSIONED_GAME_RETIRE) $(SWITCH_TO_PERMISSIONED_GAME_RETIRE_DIR)

setup-switch-to-permissioned-game-blacklist:
rm -rf $(TEMPLATE_SWITCH_TO_PERMISSIONED_GAME_BLACKLIST)/cache $(TEMPLATE_SWITCH_TO_PERMISSIONED_GAME_BLACKLIST)/lib $(TEMPLATE_SWITCH_TO_PERMISSIONED_GAME_BLACKLIST)/out
cp -r $(TEMPLATE_SWITCH_TO_PERMISSIONED_GAME_BLACKLIST) $(SWITCH_TO_PERMISSIONED_GAME_BLACKLIST_DIR)

##
# Solidity Setup
Expand Down
24 changes: 21 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -194,13 +194,31 @@ This template is used to pause or un-pause [Base Bridge](https://github.com/base
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
## Using the Switch to Permissioned Game Retire template

This template is used to switch Base to a Permissioned Game.
This template is used to switch Base to a Permissioned Game and retire existing games.

1. Ensure you have followed the instructions above in `setup`.
1. Run `make 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-retire 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. Set the `L2_DIVERGENCE_BLOCK_NUMBER` to the blocknumber that the chain has diverged at.
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.

## Using the Switch to Permissioned Game Blacklist template

This template is used to switch Base to a Permissioned Game and blacklist existing games.

1. Ensure you have followed the instructions above in `setup`.
1. Run `make setup-switch-to-permissioned-game-blacklist 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. Set the `L2_DIVERGENCE_BLOCK_NUMBER` to the blocknumber that the chain has diverged at.
1. The `ADDRESSES_TO_BLACKLIST` can be left blank, in which case the addresses to blacklist will be searched for onchain. This may take some time. Alternatively,
you may run `make find-dispute-games-offchain` which will search for the addresses off-chain and `ADDRESSES_TO_BLACKLIST` can be set to the output.
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`.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
OP_COMMIT=
BASE_CONTRACTS_COMMIT=

RECORD_STATE_DIFF=true

# The block number at which the divergence occurred
L2_DIVERGENCE_BLOCK_NUMBER=
# Comma seperated array of addresses to blacklist
ADDRESSES_TO_BLACKLIST=

# 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
DISPUTE_GAME_FACTORY=0x43edB88C4B80fDD2AdFF2412A7BebF9dF42cB40e
SENDER=0x1822b35B09f5ce1C78ecbC06AC0A4e17885b925e

# # 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
# DISPUTE_GAME_FACTORY=0xd6E6dBf4F7EA0ac412fD8b65ED297e64BB7a06E1
# # used to simulate
# SENDER=0x1084092Ac2f04c866806CF3d4a385Afa4F6A6C97
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
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:
mkdir validations; \
cd $(SIGNER_TOOL_PATH); \
npm ci; \
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)


.PHONY: find-dispute-games-offchain
find-dispute-games-offchain: pip-install
RPC_URL=$(RPC_URL) DISPUTE_GAME_FACTORY=$(DISPUTE_GAME_FACTORY) L2_DIVERGENCE_BLOCK_NUMBER=$(L2_DIVERGENCE_BLOCK_NUMBER) \
python3 script/fetch_dispute_games.py

.PHONY: pip-install
pip-install:
pip3 install -r script/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Switch to Permissioned Game and Blacklist Addresses

Status: PENDING

## Description

This task contains scripts that will blacklist fault dispute games after a provided L2 block number in the AnchorStateRegistry.
This can only be done by the "Optimism Guardian Multisig" which is a single-nested multisig controlled by the OP Security Council.

Because this requires searching through all dispute games, the time required for the task to execute may take some time. There are
two options:

1. If the `ADDRESSES_TO_BLACKLIST` environment variable is NOT set, the forge script will attempt to search for dispute games
Note: this may take 10+ minutes

2. If the `ADDRESSES_TO_BLACKLIST` environment variable IS set, the forge script will NOT search and will just blacklist the addresses
provided.

There is a python script provided that can be run with `make find-dispute-games-offchain` that will use the provided
RPC_URL to search for the list of games to blacklist _offchain_. This typically takes a minute or two. The output
is the comma-separated `ADDRESSES_TO_BLACKLIST` environment variable that can be copied over to the `.env` file, so that
the forge script can directly blacklist just those addresses.

## 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

You may now kill the Signer Tool process in your terminal window by running `Ctrl + C`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;

import {Vm} from "forge-std/Vm.sol";
import {stdJson} from "forge-std/StdJson.sol";
import {IMulticall3} from "forge-std/interfaces/IMulticall3.sol";
import {console} from "forge-std/console.sol";
import {IAnchorStateRegistry} from "@eth-optimism-bedrock/src/dispute/FaultDisputeGame.sol";
import {SystemConfig} from "@eth-optimism-bedrock/src/L1/SystemConfig.sol";
import {IDisputeGame, GameStatus} from "@eth-optimism-bedrock/src/dispute/AnchorStateRegistry.sol";
import {IDisputeGameFactory} from "@eth-optimism-bedrock/interfaces/dispute/IDisputeGameFactory.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 FaultDisputeGame and PermissionedDisputeGame implementations in the
/// DisputeGameFactory contract.
contract SwitchToPermissionedGame is MultisigScript {
using stdJson for string;

// TODO: Confirm expected version
string public constant EXPECTED_VERSION = "1.4.1";

address public immutable OWNER_SAFE;
uint64 public immutable L2_DIVERGENCE_BLOCK_NUMBER;
string public RAW_ADDRESSES_TO_BLACKLIST;

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

IAnchorStateRegistry anchorStateRegistry;
IDisputeGame[] gamesToBlacklist;

constructor() {
OWNER_SAFE = vm.envAddress("OWNER_SAFE");
RAW_ADDRESSES_TO_BLACKLIST = vm.envString("ADDRESSES_TO_BLACKLIST");
L2_DIVERGENCE_BLOCK_NUMBER = uint64(vm.envUint("L2_DIVERGENCE_BLOCK_NUMBER"));
}

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

// Split by commas
string[] memory parts = vm.split(RAW_ADDRESSES_TO_BLACKLIST, ",");

// vm.split("", ",") return [""] with size 1
if (parts.length == 0 || (parts.length == 1 && bytes(parts[0]).length == 0)) {
console.log("searching for addresses to blacklist");
getGamesToBlacklist(dgfProxy);
} else {
console.log("using provided address_to_blacklist list");
for (uint256 i; i < parts.length; i++) {
address address_to_blacklist = vm.parseAddress(parts[i]);
gamesToBlacklist.push(IDisputeGame(address_to_blacklist));
}
}

console.log("total games to blacklist", gamesToBlacklist.length);
}

function getGamesToBlacklist(IDisputeGameFactory dgfProxy) internal {
uint256 totalNumGames = dgfProxy.gameCount();
console.log("total games to search", totalNumGames);

for (uint256 i = 0; i < totalNumGames; i = i + 1) {
(,, IDisputeGame game) = dgfProxy.gameAtIndex(i);
if (game.status() == GameStatus.IN_PROGRESS && game.l2SequenceNumber() >= L2_DIVERGENCE_BLOCK_NUMBER) {
// this game is in progress and challenges a block at or after the divergence block
gamesToBlacklist.push(game);
}
}
}

// Confirm the CURRENT_RETIREMENT_TIMESTAMP is updated to the block time.
function _postCheck(Vm.AccountAccess[] memory, Simulation.Payload memory) internal view override {
for (uint256 i = 0; i < gamesToBlacklist.length; i = i + 1) {
require(anchorStateRegistry.isGameBlacklisted(gamesToBlacklist[i]), "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[](gamesToBlacklist.length + 1);

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

for (uint256 i = 0; i < gamesToBlacklist.length; i = i + 1) {
calls[i + 1] = IMulticall3.Call3Value({
target: address(anchorStateRegistry),
allowFailure: false,
callData: abi.encodeCall(IAnchorStateRegistry.blacklistDisputeGame, (gamesToBlacklist[i])),
value: 0
});
}

return calls;
}

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