From a7865882278beddc35ed60716d8d04ae9265cd11 Mon Sep 17 00:00:00 2001 From: Joby Thundil Date: Wed, 15 Oct 2025 14:37:22 -0400 Subject: [PATCH 1/9] init run --- Makefile | 6 + .../.env | 22 ++ .../Makefile | 54 +++++ .../README.md | 193 ++++++++++++++++++ .../foundry.toml | 20 ++ .../script/UpdateRetirementTimestamp.s.sol | 83 ++++++++ .../template-update-retirement-timestamp/.env | 20 ++ .../Makefile | 54 +++++ .../README.md | 193 ++++++++++++++++++ .../foundry.toml | 20 ++ .../script/UpdateRetirementTimestamp.s.sol | 83 ++++++++ 11 files changed, 748 insertions(+) create mode 100644 mainnet/2025-10-15-update-retirement-timestamp/.env create mode 100644 mainnet/2025-10-15-update-retirement-timestamp/Makefile create mode 100644 mainnet/2025-10-15-update-retirement-timestamp/README.md create mode 100644 mainnet/2025-10-15-update-retirement-timestamp/foundry.toml create mode 100644 mainnet/2025-10-15-update-retirement-timestamp/script/UpdateRetirementTimestamp.s.sol create mode 100644 setup-templates/template-update-retirement-timestamp/.env create mode 100644 setup-templates/template-update-retirement-timestamp/Makefile create mode 100644 setup-templates/template-update-retirement-timestamp/README.md create mode 100644 setup-templates/template-update-retirement-timestamp/foundry.toml create mode 100644 setup-templates/template-update-retirement-timestamp/script/UpdateRetirementTimestamp.s.sol diff --git a/Makefile b/Makefile index 4e81995f..c77b5c4b 100644 --- a/Makefile +++ b/Makefile @@ -5,6 +5,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 +UPDATE_RETIREMENT_TIMESTAMP_DIR=$(network)/$(shell date +'%Y-%m-%d')-update-retirement-timestamp TEMPLATE_GENERIC = setup-templates/template-generic TEMPLATE_GAS_INCREASE = setup-templates/template-gas-increase @@ -13,6 +14,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_UPDATE_RETIREMENT_TIMESTAMP= setup-templates/template-update-retirement-timestamp ifndef $(GOPATH) GOPATH=$(shell go env GOPATH) @@ -61,6 +63,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-update-retirement-timestamp: + rm -rf $(TEMPLATE_UPDATE_RETIREMENT_TIMESTAMP)/cache $(TEMPLATE_UPDATE_RETIREMENT_TIMESTAMP)/lib $(TEMPLATE_UPDATE_RETIREMENT_TIMESTAMP)/out + cp -r $(TEMPLATE_UPDATE_RETIREMENT_TIMESTAMP) $(UPDATE_RETIREMENT_TIMESTAMP_DIR) + ## # Solidity Setup ## diff --git a/mainnet/2025-10-15-update-retirement-timestamp/.env b/mainnet/2025-10-15-update-retirement-timestamp/.env new file mode 100644 index 00000000..0185f43c --- /dev/null +++ b/mainnet/2025-10-15-update-retirement-timestamp/.env @@ -0,0 +1,22 @@ +OP_COMMIT=ad12b8da0785da6938ebdb9c477c0f55d6ae834d +BASE_CONTRACTS_COMMIT=132ba0f33cb455ffff783924588df8864767bd9c + +CURRENT_RETIREMENT_TIMESTAMP=1759862579 + +# Mainnet Config +SYSTEM_CONFIG=0x73a79Fab69143498Ed3712e519A88a918e1f4072 + +OWNER_SAFE=0x7bB41C3008B3f03FE483B28b8DB90e19Cf07595c +CB_SIGNER_SAFE_ADDR=0x9855054731540A48b28990B63DcF4f33d8AE46A1 +CB_NESTED_SAFE_ADDR=0x20AcF55A3DCfe07fC4cecaCFa1628F788EC8A4Dd +CB_SC_SAFE_ADDR=0x9C4a57Feb77e294Fd7BF5EBE9AB01CAA0a90A110 +OP_SIGNER_SAFE_ADDR=0x9BA6e03D8B90dE867373Db8cF1A58d2F7F006b3A + +# # Sepolia Config +# SYSTEM_CONFIG=0xf272670eb55e895584501d564AfEB048bEd26194 + +# OWNER_SAFE=0x0fe884546476dDd290eC46318785046ef68a0BA9 +# CB_SIGNER_SAFE_ADDR=0x646132A1667ca7aD00d36616AFBA1A28116C770A +# CB_NESTED_SAFE_ADDR=0x5dfEB066334B67355A15dc9b67317fD2a2e1f77f +# CB_SC_SAFE_ADDR=0x6AF0674791925f767060Dd52f7fB20984E8639d8 +# OP_SIGNER_SAFE_ADDR=0x6AF0674791925f767060Dd52f7fB20984E8639d8 diff --git a/mainnet/2025-10-15-update-retirement-timestamp/Makefile b/mainnet/2025-10-15-update-retirement-timestamp/Makefile new file mode 100644 index 00000000..ce9b646e --- /dev/null +++ b/mainnet/2025-10-15-update-retirement-timestamp/Makefile @@ -0,0 +1,54 @@ +include ../../Makefile +include ../../Multisig.mk + +include ../.env +include .env + +ifndef LEDGER_ACCOUNT +override LEDGER_ACCOUNT = 0 +endif + +# Mainnet Commands + +# OWNER_SAFE/ +# ├── CB_SIGNER_SAFE_ADDR/ +# │ ├── CB_NESTED_SAFE_ADDR/ +# │ │ └── Signers +# │ └── CB_SC_SAFE_ADDR/ +# │ └── Signers +# └── OP_SIGNER_SAFE_ADDR/ +# └── Signers + +RPC_URL = $(L1_RPC_URL) +SCRIPT_NAME = UpdateRetirementTimestamp + +# CB +.PHONY: sign-cb +sign-cb: + $(call MULTISIG_SIGN,$(CB_NESTED_SAFE_ADDR) $(CB_SIGNER_SAFE_ADDR)) + +.PHONY: approve-cb +approve-cb: + $(call MULTISIG_APPROVE,$(CB_NESTED_SAFE_ADDR) $(CB_SIGNER_SAFE_ADDR),$(SIGNATURES)) + +.PHONY: sign-cb-sc +sign-cb-sc: + $(call MULTISIG_SIGN,$(CB_SC_SAFE_ADDR) $(CB_SIGNER_SAFE_ADDR)) + +.PHONY: approve-cb-sc +approve-cb-sc: + $(call MULTISIG_APPROVE,$(CB_SC_SAFE_ADDR) $(CB_SIGNER_SAFE_ADDR),$(SIGNATURES)) + +# OP +.PHONY: sign-op +sign-op: + $(call MULTISIG_SIGN,$(OP_SIGNER_SAFE_ADDR)) + +.PHONY: approve-op +approve-op: + $(call MULTISIG_APPROVE,$(OP_SIGNER_SAFE_ADDR),$(SIGNATURES)) + +# Execute +.PHONY: execute +execute: + $(call MULTISIG_EXECUTE,0x) diff --git a/mainnet/2025-10-15-update-retirement-timestamp/README.md b/mainnet/2025-10-15-update-retirement-timestamp/README.md new file mode 100644 index 00000000..bbff6d1b --- /dev/null +++ b/mainnet/2025-10-15-update-retirement-timestamp/README.md @@ -0,0 +1,193 @@ +# Upgrade Fault Proofs + +Status: PENDING + +## Description + +This task contains two scripts. One for deploying new versions of the `FaultDisputeGame` and `PermissionedDisputeGame` contracts, and one for updating the `DisputeGameFactory` contract to reference the new dispute game contracts. + +## Procedure + +### 1. Update repo: + +```bash +cd contract-deployments +git pull +cd /-upgrade-fault-proofs +make deps +``` + +### 2. Setup Ledger + +Your Ledger needs to be connected and unlocked. The Ethereum +application needs to be opened on Ledger with the message "Application +is ready". + +### 3. Run relevant script(s) + +#### 3.1 Deploy new Dispute Game Implementations + +```bash +make deploy +``` + +This will output the new addresses of the `FaultDisputeGame` and `PermissionedDisputeGame` contracts to an `addresses.json` file. You will need to commit this file to the repo before signers can sign. + +#### 3.2 Sign the transaction + +**If on testnet**: + +```bash +make sign +``` + +**If on mainnet**: + +Coinbase signer: + +```bash +make sign-cb +``` + +Op signer: + +```bash +make sign-op +``` + +You will see a "Simulation link" from the output. + +Paste this URL in your browser. A prompt may ask you to choose a +project, any project will do. You can create one if necessary. + +Click "Simulate Transaction". + +We will be performing 3 validations and extract the domain hash and message hash to approve on your Ledger: + +1. Validate integrity of the simulation. +2. Validate correctness of the state diff. +3. Validate and extract domain hash and message hash to approve. + +##### 3.2.1 Validate integrity of the simulation. + +Make sure you are on the "Summary" tab of the tenderly simulation, to +validate integrity of the simulation, we need to check the following: + +1. "Network": Check the network is Sepolia or Mainnet. +2. "Timestamp": Check the simulation is performed on a block with a + recent timestamp (i.e. close to when you run the script). +3. "Sender": Check the address shown is your signer account. If not see the derivation path Note above. + +##### 3.2.2. Validate correctness of the state diff. + +Now click on the "State" tab, and refer to the [State Validations](./VALIDATION.md) instructions for the transaction you are signing. +Once complete return to this document to complete the signing. + +##### 3.2.3. Extract the domain hash and the message hash to approve. + +Now that we have verified the transaction performs the right +operation, we need to extract the domain hash and the message hash to +approve. + +Go back to the "Summary" tab, and find the +`GnosisSafe.checkSignatures` (for OP signers) or `Safe.checkSignatures` (for Coinbase signers) call. +This call's `data` parameter contains both the domain hash and the +message hash that will show up in your Ledger. + +It will be a concatenation of `0x1901`, the domain hash, and the +message hash: `0x1901[domain hash][message hash]`. + +Note down this value. You will need to compare it with the ones +displayed on the Ledger screen at signing. + +Once the validations are done, it's time to actually sign the +transaction. + +> [!WARNING] +> This is the most security critical part of the playbook: make sure the +> domain hash and message hash in the following two places match: +> +> 1. On your Ledger screen. +> 2. In the Tenderly simulation. You should use the same Tenderly +> simulation as the one you used to verify the state diffs, instead +> of opening the new one printed in the console. +> +> There is no need to verify anything printed in the console. There is +> no need to open the new Tenderly simulation link either. + +After verification, sign the transaction. You will see the `Data`, +`Signer` and `Signature` printed in the console. Format should be +something like this: + +```shell +Data: +Signer:
+Signature: +``` + +Double check the signer address is the right one. + +##### 3.2.4 Send the output to Facilitator(s) + +Nothing has occurred onchain - these are offchain signatures which +will be collected by Facilitators for execution. Execution can occur +by anyone once a threshold of signatures are collected, so a +Facilitator will do the final execution for convenience. + +Share the `Data`, `Signer` and `Signature` with the Facilitator, and +congrats, you are done! + +### [For Facilitator ONLY] How to execute + +#### Execute the transaction + +1. IMPORTANT: Ensure op-challenger has been updated before executing. +1. Collect outputs from all participating signers. +1. Concatenate all signatures and export it as the `SIGNATURES` + environment variable, i.e. `export +SIGNATURES="[SIGNATURE1][SIGNATURE2]..."`. +1. Run the `make execute` or `make approve` command as described below to execute the transaction. + +For example, if the quorum is 2 and you get the following outputs: + +```shell +Data: 0xDEADBEEF +Signer: 0xC0FFEE01 +Signature: AAAA +``` + +```shell +Data: 0xDEADBEEF +Signer: 0xC0FFEE02 +Signature: BBBB +``` + +If on testnet, then you should run: + +Coinbase facilitator: + +```bash +SIGNATURES=AAAABBBB make execute +``` + +If on mainnet, then you should run: + +Coinbase facilitator: + +```bash +SIGNATURES=AAAABBBB make approve-cb +``` + +Optimism facilitator: + +```bash +SIGNATURES=AAAABBBB make approve-op +``` + +#### If on mainnet, execute the transaction + +Once the signatures have been submitted approving the transaction for all nested Safes run: + +```bash +make execute +``` diff --git a/mainnet/2025-10-15-update-retirement-timestamp/foundry.toml b/mainnet/2025-10-15-update-retirement-timestamp/foundry.toml new file mode 100644 index 00000000..7a443d45 --- /dev/null +++ b/mainnet/2025-10-15-update-retirement-timestamp/foundry.toml @@ -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 diff --git a/mainnet/2025-10-15-update-retirement-timestamp/script/UpdateRetirementTimestamp.s.sol b/mainnet/2025-10-15-update-retirement-timestamp/script/UpdateRetirementTimestamp.s.sol new file mode 100644 index 00000000..7a0e5288 --- /dev/null +++ b/mainnet/2025-10-15-update-retirement-timestamp/script/UpdateRetirementTimestamp.s.sol @@ -0,0 +1,83 @@ +// 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 {DisputeGameFactory} from "@eth-optimism-bedrock/src/dispute/DisputeGameFactory.sol"; +import {FaultDisputeGame} from "@eth-optimism-bedrock/src/dispute/PermissionedDisputeGame.sol"; +import {GameTypes} 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 UpdateRetirementTimestamp 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 CURRENT_RETIREMENT_TIMESTAMP; + + SystemConfig internal _SYSTEM_CONFIG = SystemConfig(vm.envAddress("SYSTEM_CONFIG")); + + IAnchorStateRegistry anchorStateRegistry; + + constructor() { + OWNER_SAFE = vm.envAddress("OWNER_SAFE"); + CURRENT_RETIREMENT_TIMESTAMP = uint64(vm.envUint("CURRENT_RETIREMENT_TIMESTAMP")); + } + + function setUp() public { + DisputeGameFactory dgfProxy = DisputeGameFactory(_SYSTEM_CONFIG.disputeGameFactory()); + FaultDisputeGame currentFdg = FaultDisputeGame(address(dgfProxy.gameImpls(GameTypes.CANNON))); + anchorStateRegistry = currentFdg.anchorStateRegistry(); + + _precheckRetirementTimestamp(); + } + + // Checks that the current state matches the CURRENT_RETIREMENT_TIMESTAMP + function _precheckRetirementTimestamp() internal view { + console.log("pre-check current retirement timestamp", CURRENT_RETIREMENT_TIMESTAMP); + require(anchorStateRegistry.retirementTimestamp() == CURRENT_RETIREMENT_TIMESTAMP, "00"); + } + + // Confirm the CURRENT_RETIREMENT_TIMESTAMP is updated to the block time. + function _postCheck(Vm.AccountAccess[] memory, Simulation.Payload memory) internal view override { + require(anchorStateRegistry.retirementTimestamp() == block.timestamp, "post-110"); + } + + // // Checks the anchor state for the source game type still exists after re-initialization. The actual anchor state + // // may have been updated since the task was defined so just assert it exists, not that it has a specific value. + // function _postcheckHasAnchorState(uint32 gameType) internal view { + // console.log("check anchor state exists", gameType); + + // IFaultDisputeGame impl = IFaultDisputeGame(dgfProxy.gameImpls(gameType)); + // (bytes32 root, uint256 rootBlockNumber) = IAnchorStateRegistry(impl.anchorStateRegistry()).anchors(gameType); + + // require(root != bytes32(0), "check-300"); + // require(rootBlockNumber != 0, "check-310"); + // } + + 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.updateRetirementTimestamp, ()), + value: 0 + }); + + return calls; + } + + function _ownerSafe() internal view override returns (address) { + return OWNER_SAFE; + } +} diff --git a/setup-templates/template-update-retirement-timestamp/.env b/setup-templates/template-update-retirement-timestamp/.env new file mode 100644 index 00000000..827f496b --- /dev/null +++ b/setup-templates/template-update-retirement-timestamp/.env @@ -0,0 +1,20 @@ +OP_COMMIT= +BASE_CONTRACTS_COMMIT= + +# Mainnet Config +SYSTEM_CONFIG=0x73a79Fab69143498Ed3712e519A88a918e1f4072 + +OWNER_SAFE=0x7bB41C3008B3f03FE483B28b8DB90e19Cf07595c +CB_SIGNER_SAFE_ADDR=0x9855054731540A48b28990B63DcF4f33d8AE46A1 +CB_NESTED_SAFE_ADDR=0x20AcF55A3DCfe07fC4cecaCFa1628F788EC8A4Dd +CB_SC_SAFE_ADDR=0x9C4a57Feb77e294Fd7BF5EBE9AB01CAA0a90A110 +OP_SIGNER_SAFE_ADDR=0x9BA6e03D8B90dE867373Db8cF1A58d2F7F006b3A + +# # Sepolia Config +# SYSTEM_CONFIG=0xf272670eb55e895584501d564AfEB048bEd26194 + +# OWNER_SAFE=0x0fe884546476dDd290eC46318785046ef68a0BA9 +# CB_SIGNER_SAFE_ADDR=0x646132A1667ca7aD00d36616AFBA1A28116C770A +# CB_NESTED_SAFE_ADDR=0x5dfEB066334B67355A15dc9b67317fD2a2e1f77f +# CB_SC_SAFE_ADDR=0x6AF0674791925f767060Dd52f7fB20984E8639d8 +# OP_SIGNER_SAFE_ADDR=0x6AF0674791925f767060Dd52f7fB20984E8639d8 diff --git a/setup-templates/template-update-retirement-timestamp/Makefile b/setup-templates/template-update-retirement-timestamp/Makefile new file mode 100644 index 00000000..ce9b646e --- /dev/null +++ b/setup-templates/template-update-retirement-timestamp/Makefile @@ -0,0 +1,54 @@ +include ../../Makefile +include ../../Multisig.mk + +include ../.env +include .env + +ifndef LEDGER_ACCOUNT +override LEDGER_ACCOUNT = 0 +endif + +# Mainnet Commands + +# OWNER_SAFE/ +# ├── CB_SIGNER_SAFE_ADDR/ +# │ ├── CB_NESTED_SAFE_ADDR/ +# │ │ └── Signers +# │ └── CB_SC_SAFE_ADDR/ +# │ └── Signers +# └── OP_SIGNER_SAFE_ADDR/ +# └── Signers + +RPC_URL = $(L1_RPC_URL) +SCRIPT_NAME = UpdateRetirementTimestamp + +# CB +.PHONY: sign-cb +sign-cb: + $(call MULTISIG_SIGN,$(CB_NESTED_SAFE_ADDR) $(CB_SIGNER_SAFE_ADDR)) + +.PHONY: approve-cb +approve-cb: + $(call MULTISIG_APPROVE,$(CB_NESTED_SAFE_ADDR) $(CB_SIGNER_SAFE_ADDR),$(SIGNATURES)) + +.PHONY: sign-cb-sc +sign-cb-sc: + $(call MULTISIG_SIGN,$(CB_SC_SAFE_ADDR) $(CB_SIGNER_SAFE_ADDR)) + +.PHONY: approve-cb-sc +approve-cb-sc: + $(call MULTISIG_APPROVE,$(CB_SC_SAFE_ADDR) $(CB_SIGNER_SAFE_ADDR),$(SIGNATURES)) + +# OP +.PHONY: sign-op +sign-op: + $(call MULTISIG_SIGN,$(OP_SIGNER_SAFE_ADDR)) + +.PHONY: approve-op +approve-op: + $(call MULTISIG_APPROVE,$(OP_SIGNER_SAFE_ADDR),$(SIGNATURES)) + +# Execute +.PHONY: execute +execute: + $(call MULTISIG_EXECUTE,0x) diff --git a/setup-templates/template-update-retirement-timestamp/README.md b/setup-templates/template-update-retirement-timestamp/README.md new file mode 100644 index 00000000..bbff6d1b --- /dev/null +++ b/setup-templates/template-update-retirement-timestamp/README.md @@ -0,0 +1,193 @@ +# Upgrade Fault Proofs + +Status: PENDING + +## Description + +This task contains two scripts. One for deploying new versions of the `FaultDisputeGame` and `PermissionedDisputeGame` contracts, and one for updating the `DisputeGameFactory` contract to reference the new dispute game contracts. + +## Procedure + +### 1. Update repo: + +```bash +cd contract-deployments +git pull +cd /-upgrade-fault-proofs +make deps +``` + +### 2. Setup Ledger + +Your Ledger needs to be connected and unlocked. The Ethereum +application needs to be opened on Ledger with the message "Application +is ready". + +### 3. Run relevant script(s) + +#### 3.1 Deploy new Dispute Game Implementations + +```bash +make deploy +``` + +This will output the new addresses of the `FaultDisputeGame` and `PermissionedDisputeGame` contracts to an `addresses.json` file. You will need to commit this file to the repo before signers can sign. + +#### 3.2 Sign the transaction + +**If on testnet**: + +```bash +make sign +``` + +**If on mainnet**: + +Coinbase signer: + +```bash +make sign-cb +``` + +Op signer: + +```bash +make sign-op +``` + +You will see a "Simulation link" from the output. + +Paste this URL in your browser. A prompt may ask you to choose a +project, any project will do. You can create one if necessary. + +Click "Simulate Transaction". + +We will be performing 3 validations and extract the domain hash and message hash to approve on your Ledger: + +1. Validate integrity of the simulation. +2. Validate correctness of the state diff. +3. Validate and extract domain hash and message hash to approve. + +##### 3.2.1 Validate integrity of the simulation. + +Make sure you are on the "Summary" tab of the tenderly simulation, to +validate integrity of the simulation, we need to check the following: + +1. "Network": Check the network is Sepolia or Mainnet. +2. "Timestamp": Check the simulation is performed on a block with a + recent timestamp (i.e. close to when you run the script). +3. "Sender": Check the address shown is your signer account. If not see the derivation path Note above. + +##### 3.2.2. Validate correctness of the state diff. + +Now click on the "State" tab, and refer to the [State Validations](./VALIDATION.md) instructions for the transaction you are signing. +Once complete return to this document to complete the signing. + +##### 3.2.3. Extract the domain hash and the message hash to approve. + +Now that we have verified the transaction performs the right +operation, we need to extract the domain hash and the message hash to +approve. + +Go back to the "Summary" tab, and find the +`GnosisSafe.checkSignatures` (for OP signers) or `Safe.checkSignatures` (for Coinbase signers) call. +This call's `data` parameter contains both the domain hash and the +message hash that will show up in your Ledger. + +It will be a concatenation of `0x1901`, the domain hash, and the +message hash: `0x1901[domain hash][message hash]`. + +Note down this value. You will need to compare it with the ones +displayed on the Ledger screen at signing. + +Once the validations are done, it's time to actually sign the +transaction. + +> [!WARNING] +> This is the most security critical part of the playbook: make sure the +> domain hash and message hash in the following two places match: +> +> 1. On your Ledger screen. +> 2. In the Tenderly simulation. You should use the same Tenderly +> simulation as the one you used to verify the state diffs, instead +> of opening the new one printed in the console. +> +> There is no need to verify anything printed in the console. There is +> no need to open the new Tenderly simulation link either. + +After verification, sign the transaction. You will see the `Data`, +`Signer` and `Signature` printed in the console. Format should be +something like this: + +```shell +Data: +Signer:
+Signature: +``` + +Double check the signer address is the right one. + +##### 3.2.4 Send the output to Facilitator(s) + +Nothing has occurred onchain - these are offchain signatures which +will be collected by Facilitators for execution. Execution can occur +by anyone once a threshold of signatures are collected, so a +Facilitator will do the final execution for convenience. + +Share the `Data`, `Signer` and `Signature` with the Facilitator, and +congrats, you are done! + +### [For Facilitator ONLY] How to execute + +#### Execute the transaction + +1. IMPORTANT: Ensure op-challenger has been updated before executing. +1. Collect outputs from all participating signers. +1. Concatenate all signatures and export it as the `SIGNATURES` + environment variable, i.e. `export +SIGNATURES="[SIGNATURE1][SIGNATURE2]..."`. +1. Run the `make execute` or `make approve` command as described below to execute the transaction. + +For example, if the quorum is 2 and you get the following outputs: + +```shell +Data: 0xDEADBEEF +Signer: 0xC0FFEE01 +Signature: AAAA +``` + +```shell +Data: 0xDEADBEEF +Signer: 0xC0FFEE02 +Signature: BBBB +``` + +If on testnet, then you should run: + +Coinbase facilitator: + +```bash +SIGNATURES=AAAABBBB make execute +``` + +If on mainnet, then you should run: + +Coinbase facilitator: + +```bash +SIGNATURES=AAAABBBB make approve-cb +``` + +Optimism facilitator: + +```bash +SIGNATURES=AAAABBBB make approve-op +``` + +#### If on mainnet, execute the transaction + +Once the signatures have been submitted approving the transaction for all nested Safes run: + +```bash +make execute +``` diff --git a/setup-templates/template-update-retirement-timestamp/foundry.toml b/setup-templates/template-update-retirement-timestamp/foundry.toml new file mode 100644 index 00000000..7a443d45 --- /dev/null +++ b/setup-templates/template-update-retirement-timestamp/foundry.toml @@ -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 diff --git a/setup-templates/template-update-retirement-timestamp/script/UpdateRetirementTimestamp.s.sol b/setup-templates/template-update-retirement-timestamp/script/UpdateRetirementTimestamp.s.sol new file mode 100644 index 00000000..7a0e5288 --- /dev/null +++ b/setup-templates/template-update-retirement-timestamp/script/UpdateRetirementTimestamp.s.sol @@ -0,0 +1,83 @@ +// 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 {DisputeGameFactory} from "@eth-optimism-bedrock/src/dispute/DisputeGameFactory.sol"; +import {FaultDisputeGame} from "@eth-optimism-bedrock/src/dispute/PermissionedDisputeGame.sol"; +import {GameTypes} 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 UpdateRetirementTimestamp 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 CURRENT_RETIREMENT_TIMESTAMP; + + SystemConfig internal _SYSTEM_CONFIG = SystemConfig(vm.envAddress("SYSTEM_CONFIG")); + + IAnchorStateRegistry anchorStateRegistry; + + constructor() { + OWNER_SAFE = vm.envAddress("OWNER_SAFE"); + CURRENT_RETIREMENT_TIMESTAMP = uint64(vm.envUint("CURRENT_RETIREMENT_TIMESTAMP")); + } + + function setUp() public { + DisputeGameFactory dgfProxy = DisputeGameFactory(_SYSTEM_CONFIG.disputeGameFactory()); + FaultDisputeGame currentFdg = FaultDisputeGame(address(dgfProxy.gameImpls(GameTypes.CANNON))); + anchorStateRegistry = currentFdg.anchorStateRegistry(); + + _precheckRetirementTimestamp(); + } + + // Checks that the current state matches the CURRENT_RETIREMENT_TIMESTAMP + function _precheckRetirementTimestamp() internal view { + console.log("pre-check current retirement timestamp", CURRENT_RETIREMENT_TIMESTAMP); + require(anchorStateRegistry.retirementTimestamp() == CURRENT_RETIREMENT_TIMESTAMP, "00"); + } + + // Confirm the CURRENT_RETIREMENT_TIMESTAMP is updated to the block time. + function _postCheck(Vm.AccountAccess[] memory, Simulation.Payload memory) internal view override { + require(anchorStateRegistry.retirementTimestamp() == block.timestamp, "post-110"); + } + + // // Checks the anchor state for the source game type still exists after re-initialization. The actual anchor state + // // may have been updated since the task was defined so just assert it exists, not that it has a specific value. + // function _postcheckHasAnchorState(uint32 gameType) internal view { + // console.log("check anchor state exists", gameType); + + // IFaultDisputeGame impl = IFaultDisputeGame(dgfProxy.gameImpls(gameType)); + // (bytes32 root, uint256 rootBlockNumber) = IAnchorStateRegistry(impl.anchorStateRegistry()).anchors(gameType); + + // require(root != bytes32(0), "check-300"); + // require(rootBlockNumber != 0, "check-310"); + // } + + 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.updateRetirementTimestamp, ()), + value: 0 + }); + + return calls; + } + + function _ownerSafe() internal view override returns (address) { + return OWNER_SAFE; + } +} From f76142439b5ccab41a1475aeb68e7990a490ca25 Mon Sep 17 00:00:00 2001 From: Joby Thundil Date: Wed, 15 Oct 2025 22:42:12 -0400 Subject: [PATCH 2/9] update only template --- .../.env | 22 -- .../Makefile | 54 ----- .../README.md | 193 ------------------ .../foundry.toml | 20 -- .../script/UpdateRetirementTimestamp.s.sol | 83 -------- .../template-update-retirement-timestamp/.env | 9 +- .../Makefile | 32 +-- .../script/UpdateRetirementTimestamp.s.sol | 15 +- 8 files changed, 7 insertions(+), 421 deletions(-) delete mode 100644 mainnet/2025-10-15-update-retirement-timestamp/.env delete mode 100644 mainnet/2025-10-15-update-retirement-timestamp/Makefile delete mode 100644 mainnet/2025-10-15-update-retirement-timestamp/README.md delete mode 100644 mainnet/2025-10-15-update-retirement-timestamp/foundry.toml delete mode 100644 mainnet/2025-10-15-update-retirement-timestamp/script/UpdateRetirementTimestamp.s.sol diff --git a/mainnet/2025-10-15-update-retirement-timestamp/.env b/mainnet/2025-10-15-update-retirement-timestamp/.env deleted file mode 100644 index 0185f43c..00000000 --- a/mainnet/2025-10-15-update-retirement-timestamp/.env +++ /dev/null @@ -1,22 +0,0 @@ -OP_COMMIT=ad12b8da0785da6938ebdb9c477c0f55d6ae834d -BASE_CONTRACTS_COMMIT=132ba0f33cb455ffff783924588df8864767bd9c - -CURRENT_RETIREMENT_TIMESTAMP=1759862579 - -# Mainnet Config -SYSTEM_CONFIG=0x73a79Fab69143498Ed3712e519A88a918e1f4072 - -OWNER_SAFE=0x7bB41C3008B3f03FE483B28b8DB90e19Cf07595c -CB_SIGNER_SAFE_ADDR=0x9855054731540A48b28990B63DcF4f33d8AE46A1 -CB_NESTED_SAFE_ADDR=0x20AcF55A3DCfe07fC4cecaCFa1628F788EC8A4Dd -CB_SC_SAFE_ADDR=0x9C4a57Feb77e294Fd7BF5EBE9AB01CAA0a90A110 -OP_SIGNER_SAFE_ADDR=0x9BA6e03D8B90dE867373Db8cF1A58d2F7F006b3A - -# # Sepolia Config -# SYSTEM_CONFIG=0xf272670eb55e895584501d564AfEB048bEd26194 - -# OWNER_SAFE=0x0fe884546476dDd290eC46318785046ef68a0BA9 -# CB_SIGNER_SAFE_ADDR=0x646132A1667ca7aD00d36616AFBA1A28116C770A -# CB_NESTED_SAFE_ADDR=0x5dfEB066334B67355A15dc9b67317fD2a2e1f77f -# CB_SC_SAFE_ADDR=0x6AF0674791925f767060Dd52f7fB20984E8639d8 -# OP_SIGNER_SAFE_ADDR=0x6AF0674791925f767060Dd52f7fB20984E8639d8 diff --git a/mainnet/2025-10-15-update-retirement-timestamp/Makefile b/mainnet/2025-10-15-update-retirement-timestamp/Makefile deleted file mode 100644 index ce9b646e..00000000 --- a/mainnet/2025-10-15-update-retirement-timestamp/Makefile +++ /dev/null @@ -1,54 +0,0 @@ -include ../../Makefile -include ../../Multisig.mk - -include ../.env -include .env - -ifndef LEDGER_ACCOUNT -override LEDGER_ACCOUNT = 0 -endif - -# Mainnet Commands - -# OWNER_SAFE/ -# ├── CB_SIGNER_SAFE_ADDR/ -# │ ├── CB_NESTED_SAFE_ADDR/ -# │ │ └── Signers -# │ └── CB_SC_SAFE_ADDR/ -# │ └── Signers -# └── OP_SIGNER_SAFE_ADDR/ -# └── Signers - -RPC_URL = $(L1_RPC_URL) -SCRIPT_NAME = UpdateRetirementTimestamp - -# CB -.PHONY: sign-cb -sign-cb: - $(call MULTISIG_SIGN,$(CB_NESTED_SAFE_ADDR) $(CB_SIGNER_SAFE_ADDR)) - -.PHONY: approve-cb -approve-cb: - $(call MULTISIG_APPROVE,$(CB_NESTED_SAFE_ADDR) $(CB_SIGNER_SAFE_ADDR),$(SIGNATURES)) - -.PHONY: sign-cb-sc -sign-cb-sc: - $(call MULTISIG_SIGN,$(CB_SC_SAFE_ADDR) $(CB_SIGNER_SAFE_ADDR)) - -.PHONY: approve-cb-sc -approve-cb-sc: - $(call MULTISIG_APPROVE,$(CB_SC_SAFE_ADDR) $(CB_SIGNER_SAFE_ADDR),$(SIGNATURES)) - -# OP -.PHONY: sign-op -sign-op: - $(call MULTISIG_SIGN,$(OP_SIGNER_SAFE_ADDR)) - -.PHONY: approve-op -approve-op: - $(call MULTISIG_APPROVE,$(OP_SIGNER_SAFE_ADDR),$(SIGNATURES)) - -# Execute -.PHONY: execute -execute: - $(call MULTISIG_EXECUTE,0x) diff --git a/mainnet/2025-10-15-update-retirement-timestamp/README.md b/mainnet/2025-10-15-update-retirement-timestamp/README.md deleted file mode 100644 index bbff6d1b..00000000 --- a/mainnet/2025-10-15-update-retirement-timestamp/README.md +++ /dev/null @@ -1,193 +0,0 @@ -# Upgrade Fault Proofs - -Status: PENDING - -## Description - -This task contains two scripts. One for deploying new versions of the `FaultDisputeGame` and `PermissionedDisputeGame` contracts, and one for updating the `DisputeGameFactory` contract to reference the new dispute game contracts. - -## Procedure - -### 1. Update repo: - -```bash -cd contract-deployments -git pull -cd /-upgrade-fault-proofs -make deps -``` - -### 2. Setup Ledger - -Your Ledger needs to be connected and unlocked. The Ethereum -application needs to be opened on Ledger with the message "Application -is ready". - -### 3. Run relevant script(s) - -#### 3.1 Deploy new Dispute Game Implementations - -```bash -make deploy -``` - -This will output the new addresses of the `FaultDisputeGame` and `PermissionedDisputeGame` contracts to an `addresses.json` file. You will need to commit this file to the repo before signers can sign. - -#### 3.2 Sign the transaction - -**If on testnet**: - -```bash -make sign -``` - -**If on mainnet**: - -Coinbase signer: - -```bash -make sign-cb -``` - -Op signer: - -```bash -make sign-op -``` - -You will see a "Simulation link" from the output. - -Paste this URL in your browser. A prompt may ask you to choose a -project, any project will do. You can create one if necessary. - -Click "Simulate Transaction". - -We will be performing 3 validations and extract the domain hash and message hash to approve on your Ledger: - -1. Validate integrity of the simulation. -2. Validate correctness of the state diff. -3. Validate and extract domain hash and message hash to approve. - -##### 3.2.1 Validate integrity of the simulation. - -Make sure you are on the "Summary" tab of the tenderly simulation, to -validate integrity of the simulation, we need to check the following: - -1. "Network": Check the network is Sepolia or Mainnet. -2. "Timestamp": Check the simulation is performed on a block with a - recent timestamp (i.e. close to when you run the script). -3. "Sender": Check the address shown is your signer account. If not see the derivation path Note above. - -##### 3.2.2. Validate correctness of the state diff. - -Now click on the "State" tab, and refer to the [State Validations](./VALIDATION.md) instructions for the transaction you are signing. -Once complete return to this document to complete the signing. - -##### 3.2.3. Extract the domain hash and the message hash to approve. - -Now that we have verified the transaction performs the right -operation, we need to extract the domain hash and the message hash to -approve. - -Go back to the "Summary" tab, and find the -`GnosisSafe.checkSignatures` (for OP signers) or `Safe.checkSignatures` (for Coinbase signers) call. -This call's `data` parameter contains both the domain hash and the -message hash that will show up in your Ledger. - -It will be a concatenation of `0x1901`, the domain hash, and the -message hash: `0x1901[domain hash][message hash]`. - -Note down this value. You will need to compare it with the ones -displayed on the Ledger screen at signing. - -Once the validations are done, it's time to actually sign the -transaction. - -> [!WARNING] -> This is the most security critical part of the playbook: make sure the -> domain hash and message hash in the following two places match: -> -> 1. On your Ledger screen. -> 2. In the Tenderly simulation. You should use the same Tenderly -> simulation as the one you used to verify the state diffs, instead -> of opening the new one printed in the console. -> -> There is no need to verify anything printed in the console. There is -> no need to open the new Tenderly simulation link either. - -After verification, sign the transaction. You will see the `Data`, -`Signer` and `Signature` printed in the console. Format should be -something like this: - -```shell -Data: -Signer:
-Signature: -``` - -Double check the signer address is the right one. - -##### 3.2.4 Send the output to Facilitator(s) - -Nothing has occurred onchain - these are offchain signatures which -will be collected by Facilitators for execution. Execution can occur -by anyone once a threshold of signatures are collected, so a -Facilitator will do the final execution for convenience. - -Share the `Data`, `Signer` and `Signature` with the Facilitator, and -congrats, you are done! - -### [For Facilitator ONLY] How to execute - -#### Execute the transaction - -1. IMPORTANT: Ensure op-challenger has been updated before executing. -1. Collect outputs from all participating signers. -1. Concatenate all signatures and export it as the `SIGNATURES` - environment variable, i.e. `export -SIGNATURES="[SIGNATURE1][SIGNATURE2]..."`. -1. Run the `make execute` or `make approve` command as described below to execute the transaction. - -For example, if the quorum is 2 and you get the following outputs: - -```shell -Data: 0xDEADBEEF -Signer: 0xC0FFEE01 -Signature: AAAA -``` - -```shell -Data: 0xDEADBEEF -Signer: 0xC0FFEE02 -Signature: BBBB -``` - -If on testnet, then you should run: - -Coinbase facilitator: - -```bash -SIGNATURES=AAAABBBB make execute -``` - -If on mainnet, then you should run: - -Coinbase facilitator: - -```bash -SIGNATURES=AAAABBBB make approve-cb -``` - -Optimism facilitator: - -```bash -SIGNATURES=AAAABBBB make approve-op -``` - -#### If on mainnet, execute the transaction - -Once the signatures have been submitted approving the transaction for all nested Safes run: - -```bash -make execute -``` diff --git a/mainnet/2025-10-15-update-retirement-timestamp/foundry.toml b/mainnet/2025-10-15-update-retirement-timestamp/foundry.toml deleted file mode 100644 index 7a443d45..00000000 --- a/mainnet/2025-10-15-update-retirement-timestamp/foundry.toml +++ /dev/null @@ -1,20 +0,0 @@ -[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 diff --git a/mainnet/2025-10-15-update-retirement-timestamp/script/UpdateRetirementTimestamp.s.sol b/mainnet/2025-10-15-update-retirement-timestamp/script/UpdateRetirementTimestamp.s.sol deleted file mode 100644 index 7a0e5288..00000000 --- a/mainnet/2025-10-15-update-retirement-timestamp/script/UpdateRetirementTimestamp.s.sol +++ /dev/null @@ -1,83 +0,0 @@ -// 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 {DisputeGameFactory} from "@eth-optimism-bedrock/src/dispute/DisputeGameFactory.sol"; -import {FaultDisputeGame} from "@eth-optimism-bedrock/src/dispute/PermissionedDisputeGame.sol"; -import {GameTypes} 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 UpdateRetirementTimestamp 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 CURRENT_RETIREMENT_TIMESTAMP; - - SystemConfig internal _SYSTEM_CONFIG = SystemConfig(vm.envAddress("SYSTEM_CONFIG")); - - IAnchorStateRegistry anchorStateRegistry; - - constructor() { - OWNER_SAFE = vm.envAddress("OWNER_SAFE"); - CURRENT_RETIREMENT_TIMESTAMP = uint64(vm.envUint("CURRENT_RETIREMENT_TIMESTAMP")); - } - - function setUp() public { - DisputeGameFactory dgfProxy = DisputeGameFactory(_SYSTEM_CONFIG.disputeGameFactory()); - FaultDisputeGame currentFdg = FaultDisputeGame(address(dgfProxy.gameImpls(GameTypes.CANNON))); - anchorStateRegistry = currentFdg.anchorStateRegistry(); - - _precheckRetirementTimestamp(); - } - - // Checks that the current state matches the CURRENT_RETIREMENT_TIMESTAMP - function _precheckRetirementTimestamp() internal view { - console.log("pre-check current retirement timestamp", CURRENT_RETIREMENT_TIMESTAMP); - require(anchorStateRegistry.retirementTimestamp() == CURRENT_RETIREMENT_TIMESTAMP, "00"); - } - - // Confirm the CURRENT_RETIREMENT_TIMESTAMP is updated to the block time. - function _postCheck(Vm.AccountAccess[] memory, Simulation.Payload memory) internal view override { - require(anchorStateRegistry.retirementTimestamp() == block.timestamp, "post-110"); - } - - // // Checks the anchor state for the source game type still exists after re-initialization. The actual anchor state - // // may have been updated since the task was defined so just assert it exists, not that it has a specific value. - // function _postcheckHasAnchorState(uint32 gameType) internal view { - // console.log("check anchor state exists", gameType); - - // IFaultDisputeGame impl = IFaultDisputeGame(dgfProxy.gameImpls(gameType)); - // (bytes32 root, uint256 rootBlockNumber) = IAnchorStateRegistry(impl.anchorStateRegistry()).anchors(gameType); - - // require(root != bytes32(0), "check-300"); - // require(rootBlockNumber != 0, "check-310"); - // } - - 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.updateRetirementTimestamp, ()), - value: 0 - }); - - return calls; - } - - function _ownerSafe() internal view override returns (address) { - return OWNER_SAFE; - } -} diff --git a/setup-templates/template-update-retirement-timestamp/.env b/setup-templates/template-update-retirement-timestamp/.env index 827f496b..7c10af70 100644 --- a/setup-templates/template-update-retirement-timestamp/.env +++ b/setup-templates/template-update-retirement-timestamp/.env @@ -1,14 +1,13 @@ OP_COMMIT= BASE_CONTRACTS_COMMIT= +CURRENT_RETIREMENT_TIMESTAMP= + # Mainnet Config SYSTEM_CONFIG=0x73a79Fab69143498Ed3712e519A88a918e1f4072 -OWNER_SAFE=0x7bB41C3008B3f03FE483B28b8DB90e19Cf07595c -CB_SIGNER_SAFE_ADDR=0x9855054731540A48b28990B63DcF4f33d8AE46A1 -CB_NESTED_SAFE_ADDR=0x20AcF55A3DCfe07fC4cecaCFa1628F788EC8A4Dd -CB_SC_SAFE_ADDR=0x9C4a57Feb77e294Fd7BF5EBE9AB01CAA0a90A110 -OP_SIGNER_SAFE_ADDR=0x9BA6e03D8B90dE867373Db8cF1A58d2F7F006b3A +OWNER_SAFE=0x09f7150D8c019BeF34450d6920f6B3608ceFdAf2 # Optimism Guardian Multisig (controls Anchor State Registry) +OP_SECURITY_COUNCIL_SAFE=0xc2819DC788505Aac350142A7A707BF9D03E3Bd03 # Owner of Optimism Guardian Multisig # # Sepolia Config # SYSTEM_CONFIG=0xf272670eb55e895584501d564AfEB048bEd26194 diff --git a/setup-templates/template-update-retirement-timestamp/Makefile b/setup-templates/template-update-retirement-timestamp/Makefile index ce9b646e..b63dfec4 100644 --- a/setup-templates/template-update-retirement-timestamp/Makefile +++ b/setup-templates/template-update-retirement-timestamp/Makefile @@ -8,45 +8,17 @@ ifndef LEDGER_ACCOUNT override LEDGER_ACCOUNT = 0 endif -# Mainnet Commands - -# OWNER_SAFE/ -# ├── CB_SIGNER_SAFE_ADDR/ -# │ ├── CB_NESTED_SAFE_ADDR/ -# │ │ └── Signers -# │ └── CB_SC_SAFE_ADDR/ -# │ └── Signers -# └── OP_SIGNER_SAFE_ADDR/ -# └── Signers - RPC_URL = $(L1_RPC_URL) SCRIPT_NAME = UpdateRetirementTimestamp -# CB -.PHONY: sign-cb -sign-cb: - $(call MULTISIG_SIGN,$(CB_NESTED_SAFE_ADDR) $(CB_SIGNER_SAFE_ADDR)) - -.PHONY: approve-cb -approve-cb: - $(call MULTISIG_APPROVE,$(CB_NESTED_SAFE_ADDR) $(CB_SIGNER_SAFE_ADDR),$(SIGNATURES)) - -.PHONY: sign-cb-sc -sign-cb-sc: - $(call MULTISIG_SIGN,$(CB_SC_SAFE_ADDR) $(CB_SIGNER_SAFE_ADDR)) - -.PHONY: approve-cb-sc -approve-cb-sc: - $(call MULTISIG_APPROVE,$(CB_SC_SAFE_ADDR) $(CB_SIGNER_SAFE_ADDR),$(SIGNATURES)) - # OP .PHONY: sign-op sign-op: - $(call MULTISIG_SIGN,$(OP_SIGNER_SAFE_ADDR)) + $(call MULTISIG_SIGN,$(OP_SECURITY_COUNCIL_SAFE)) .PHONY: approve-op approve-op: - $(call MULTISIG_APPROVE,$(OP_SIGNER_SAFE_ADDR),$(SIGNATURES)) + $(call MULTISIG_APPROVE,$(OP_SECURITY_COUNCIL_SAFE),$(SIGNATURES)) # Execute .PHONY: execute diff --git a/setup-templates/template-update-retirement-timestamp/script/UpdateRetirementTimestamp.s.sol b/setup-templates/template-update-retirement-timestamp/script/UpdateRetirementTimestamp.s.sol index 7a0e5288..b7a52b35 100644 --- a/setup-templates/template-update-retirement-timestamp/script/UpdateRetirementTimestamp.s.sol +++ b/setup-templates/template-update-retirement-timestamp/script/UpdateRetirementTimestamp.s.sol @@ -43,7 +43,6 @@ contract UpdateRetirementTimestamp is MultisigScript { // Checks that the current state matches the CURRENT_RETIREMENT_TIMESTAMP function _precheckRetirementTimestamp() internal view { - console.log("pre-check current retirement timestamp", CURRENT_RETIREMENT_TIMESTAMP); require(anchorStateRegistry.retirementTimestamp() == CURRENT_RETIREMENT_TIMESTAMP, "00"); } @@ -52,21 +51,9 @@ contract UpdateRetirementTimestamp is MultisigScript { require(anchorStateRegistry.retirementTimestamp() == block.timestamp, "post-110"); } - // // Checks the anchor state for the source game type still exists after re-initialization. The actual anchor state - // // may have been updated since the task was defined so just assert it exists, not that it has a specific value. - // function _postcheckHasAnchorState(uint32 gameType) internal view { - // console.log("check anchor state exists", gameType); - - // IFaultDisputeGame impl = IFaultDisputeGame(dgfProxy.gameImpls(gameType)); - // (bytes32 root, uint256 rootBlockNumber) = IAnchorStateRegistry(impl.anchorStateRegistry()).anchors(gameType); - - // require(root != bytes32(0), "check-300"); - // require(rootBlockNumber != 0, "check-310"); - // } function _buildCalls() internal view override returns (IMulticall3.Call3Value[] memory) { - IMulticall3.Call3Value[] memory calls = new IMulticall3.Call3Value[](2); - + IMulticall3.Call3Value[] memory calls = new IMulticall3.Call3Value[](1); calls[0] = IMulticall3.Call3Value({ target: address(anchorStateRegistry), allowFailure: false, From 28bf2bde4f66b4074fc0a76f542cceeeab646fd8 Mon Sep 17 00:00:00 2001 From: Joby Thundil Date: Wed, 15 Oct 2025 23:02:11 -0400 Subject: [PATCH 3/9] rename to switch to permissioned game --- Makefile | 10 +++++----- .../.env | 7 ++----- .../Makefile | 0 .../README.md | 0 .../foundry.toml | 0 .../script/SwitchToPermissionedGame.sol} | 12 ++++++++++-- 6 files changed, 17 insertions(+), 12 deletions(-) rename setup-templates/{template-update-retirement-timestamp => template-switch-to-permissioned-game}/.env (58%) rename setup-templates/{template-update-retirement-timestamp => template-switch-to-permissioned-game}/Makefile (100%) rename setup-templates/{template-update-retirement-timestamp => template-switch-to-permissioned-game}/README.md (100%) rename setup-templates/{template-update-retirement-timestamp => template-switch-to-permissioned-game}/foundry.toml (100%) rename setup-templates/{template-update-retirement-timestamp/script/UpdateRetirementTimestamp.s.sol => template-switch-to-permissioned-game/script/SwitchToPermissionedGame.sol} (89%) diff --git a/Makefile b/Makefile index c77b5c4b..76ae0cfd 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,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 -UPDATE_RETIREMENT_TIMESTAMP_DIR=$(network)/$(shell date +'%Y-%m-%d')-update-retirement-timestamp +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 @@ -14,7 +14,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_UPDATE_RETIREMENT_TIMESTAMP= setup-templates/template-update-retirement-timestamp +TEMPLATE_SWITCH_TO_PERMISSIONED_GAME = setup-templates/template-switch-to-permissioned-game ifndef $(GOPATH) GOPATH=$(shell go env GOPATH) @@ -63,9 +63,9 @@ 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-update-retirement-timestamp: - rm -rf $(TEMPLATE_UPDATE_RETIREMENT_TIMESTAMP)/cache $(TEMPLATE_UPDATE_RETIREMENT_TIMESTAMP)/lib $(TEMPLATE_UPDATE_RETIREMENT_TIMESTAMP)/out - cp -r $(TEMPLATE_UPDATE_RETIREMENT_TIMESTAMP) $(UPDATE_RETIREMENT_TIMESTAMP_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 diff --git a/setup-templates/template-update-retirement-timestamp/.env b/setup-templates/template-switch-to-permissioned-game/.env similarity index 58% rename from setup-templates/template-update-retirement-timestamp/.env rename to setup-templates/template-switch-to-permissioned-game/.env index 7c10af70..9cb2e0ad 100644 --- a/setup-templates/template-update-retirement-timestamp/.env +++ b/setup-templates/template-switch-to-permissioned-game/.env @@ -12,8 +12,5 @@ OP_SECURITY_COUNCIL_SAFE=0xc2819DC788505Aac350142A7A707BF9D03E3Bd03 # Owner of O # # Sepolia Config # SYSTEM_CONFIG=0xf272670eb55e895584501d564AfEB048bEd26194 -# OWNER_SAFE=0x0fe884546476dDd290eC46318785046ef68a0BA9 -# CB_SIGNER_SAFE_ADDR=0x646132A1667ca7aD00d36616AFBA1A28116C770A -# CB_NESTED_SAFE_ADDR=0x5dfEB066334B67355A15dc9b67317fD2a2e1f77f -# CB_SC_SAFE_ADDR=0x6AF0674791925f767060Dd52f7fB20984E8639d8 -# OP_SIGNER_SAFE_ADDR=0x6AF0674791925f767060Dd52f7fB20984E8639d8 +# OWNER_SAFE=0x7a50f00e8D05b95F98fE38d8BeE366a7324dCf7E # Optimism Guardian Multisig (controls Anchor State Registry) +# OP_SECURITY_COUNCIL_SAFE=0xf64bc17485f0B4Ea5F06A96514182FC4cB561977 # Owner of Optimism Guardian Multisig diff --git a/setup-templates/template-update-retirement-timestamp/Makefile b/setup-templates/template-switch-to-permissioned-game/Makefile similarity index 100% rename from setup-templates/template-update-retirement-timestamp/Makefile rename to setup-templates/template-switch-to-permissioned-game/Makefile diff --git a/setup-templates/template-update-retirement-timestamp/README.md b/setup-templates/template-switch-to-permissioned-game/README.md similarity index 100% rename from setup-templates/template-update-retirement-timestamp/README.md rename to setup-templates/template-switch-to-permissioned-game/README.md diff --git a/setup-templates/template-update-retirement-timestamp/foundry.toml b/setup-templates/template-switch-to-permissioned-game/foundry.toml similarity index 100% rename from setup-templates/template-update-retirement-timestamp/foundry.toml rename to setup-templates/template-switch-to-permissioned-game/foundry.toml diff --git a/setup-templates/template-update-retirement-timestamp/script/UpdateRetirementTimestamp.s.sol b/setup-templates/template-switch-to-permissioned-game/script/SwitchToPermissionedGame.sol similarity index 89% rename from setup-templates/template-update-retirement-timestamp/script/UpdateRetirementTimestamp.s.sol rename to setup-templates/template-switch-to-permissioned-game/script/SwitchToPermissionedGame.sol index b7a52b35..067ec5ad 100644 --- a/setup-templates/template-update-retirement-timestamp/script/UpdateRetirementTimestamp.s.sol +++ b/setup-templates/template-switch-to-permissioned-game/script/SwitchToPermissionedGame.sol @@ -15,7 +15,7 @@ import {Simulation} from "@base-contracts/script/universal/Simulation.sol"; /// @notice This script updates the FaultDisputeGame and PermissionedDisputeGame implementations in the /// DisputeGameFactory contract. -contract UpdateRetirementTimestamp is MultisigScript { +contract SwitchToPermissionedGame is MultisigScript { using stdJson for string; // TODO: Confirm expected version @@ -53,8 +53,16 @@ contract UpdateRetirementTimestamp is MultisigScript { function _buildCalls() internal view override returns (IMulticall3.Call3Value[] memory) { - IMulticall3.Call3Value[] memory calls = new IMulticall3.Call3Value[](1); + IMulticall3.Call3Value[] memory calls = new IMulticall3.Call3Value[](2); + calls[0] = IMulticall3.Call3Value({ + target: address(anchorStateRegistry), + allowFailure: false, + callData: abi.encodeCall(IAnchorStateRegistry.setRespectedGameType, (GameType.PERMISSIONED_CANNON)), + value: 0 + }); + + calls[1] = IMulticall3.Call3Value({ target: address(anchorStateRegistry), allowFailure: false, callData: abi.encodeCall(IAnchorStateRegistry.updateRetirementTimestamp, ()), From eda82fac3b624ab06a5242ee0fb12c3c962b9e59 Mon Sep 17 00:00:00 2001 From: Joby Thundil Date: Wed, 15 Oct 2025 23:11:13 -0400 Subject: [PATCH 4/9] update script name --- setup-templates/template-switch-to-permissioned-game/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup-templates/template-switch-to-permissioned-game/Makefile b/setup-templates/template-switch-to-permissioned-game/Makefile index b63dfec4..da400129 100644 --- a/setup-templates/template-switch-to-permissioned-game/Makefile +++ b/setup-templates/template-switch-to-permissioned-game/Makefile @@ -9,7 +9,7 @@ override LEDGER_ACCOUNT = 0 endif RPC_URL = $(L1_RPC_URL) -SCRIPT_NAME = UpdateRetirementTimestamp +SCRIPT_NAME = SwitchToPermissionedGame # OP .PHONY: sign-op From 9fb2d57bdf735867055fc8875d0d720695787d10 Mon Sep 17 00:00:00 2001 From: Joby Thundil Date: Wed, 15 Oct 2025 23:17:29 -0400 Subject: [PATCH 5/9] update readme --- .../README.md | 33 +++---------------- 1 file changed, 4 insertions(+), 29 deletions(-) diff --git a/setup-templates/template-switch-to-permissioned-game/README.md b/setup-templates/template-switch-to-permissioned-game/README.md index bbff6d1b..9a6ba8f9 100644 --- a/setup-templates/template-switch-to-permissioned-game/README.md +++ b/setup-templates/template-switch-to-permissioned-game/README.md @@ -4,7 +4,8 @@ Status: PENDING ## Description -This task contains two scripts. One for deploying new versions of the `FaultDisputeGame` and `PermissionedDisputeGame` contracts, and one for updating the `DisputeGameFactory` contract to reference the new dispute game contracts. +This task contains a single script that will update the `respectedGameType` and `retirementTimestamp` 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. ## Procedure @@ -13,7 +14,7 @@ This task contains two scripts. One for deploying new versions of the `FaultDisp ```bash cd contract-deployments git pull -cd /-upgrade-fault-proofs +cd /-switch-to-permissioned-game make deps ``` @@ -25,30 +26,10 @@ is ready". ### 3. Run relevant script(s) -#### 3.1 Deploy new Dispute Game Implementations - -```bash -make deploy -``` - -This will output the new addresses of the `FaultDisputeGame` and `PermissionedDisputeGame` contracts to an `addresses.json` file. You will need to commit this file to the repo before signers can sign. - -#### 3.2 Sign the transaction - -**If on testnet**: - -```bash -make sign -``` +#### 3.1 Sign the transaction **If on mainnet**: -Coinbase signer: - -```bash -make sign-cb -``` - Op signer: ```bash @@ -172,12 +153,6 @@ SIGNATURES=AAAABBBB make execute If on mainnet, then you should run: -Coinbase facilitator: - -```bash -SIGNATURES=AAAABBBB make approve-cb -``` - Optimism facilitator: ```bash From 6a57626baf230632cce51799338ddd90333afd32 Mon Sep 17 00:00:00 2001 From: Joby Thundil Date: Fri, 24 Oct 2025 11:09:30 -0400 Subject: [PATCH 6/9] fix typo --- .../script/SwitchToPermissionedGame.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup-templates/template-switch-to-permissioned-game/script/SwitchToPermissionedGame.sol b/setup-templates/template-switch-to-permissioned-game/script/SwitchToPermissionedGame.sol index 067ec5ad..f18d6f70 100644 --- a/setup-templates/template-switch-to-permissioned-game/script/SwitchToPermissionedGame.sol +++ b/setup-templates/template-switch-to-permissioned-game/script/SwitchToPermissionedGame.sol @@ -58,7 +58,7 @@ contract SwitchToPermissionedGame is MultisigScript { calls[0] = IMulticall3.Call3Value({ target: address(anchorStateRegistry), allowFailure: false, - callData: abi.encodeCall(IAnchorStateRegistry.setRespectedGameType, (GameType.PERMISSIONED_CANNON)), + callData: abi.encodeCall(IAnchorStateRegistry.setRespectedGameType, (GameTypes.PERMISSIONED_CANNON)), value: 0 }); From 4013a7ec2692b9571af28002721bfdbd7aeb3d63 Mon Sep 17 00:00:00 2001 From: Joby Thundil Date: Fri, 24 Oct 2025 11:13:19 -0400 Subject: [PATCH 7/9] add postcheck for permissioned cannon --- .../script/SwitchToPermissionedGame.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/setup-templates/template-switch-to-permissioned-game/script/SwitchToPermissionedGame.sol b/setup-templates/template-switch-to-permissioned-game/script/SwitchToPermissionedGame.sol index f18d6f70..e505b2d7 100644 --- a/setup-templates/template-switch-to-permissioned-game/script/SwitchToPermissionedGame.sol +++ b/setup-templates/template-switch-to-permissioned-game/script/SwitchToPermissionedGame.sol @@ -49,6 +49,7 @@ contract SwitchToPermissionedGame is MultisigScript { // Confirm the CURRENT_RETIREMENT_TIMESTAMP is updated to the block time. function _postCheck(Vm.AccountAccess[] memory, Simulation.Payload memory) internal view override { require(anchorStateRegistry.retirementTimestamp() == block.timestamp, "post-110"); + require(anchorStateRegistry.respectedGameType() == GameTypes.PERMISSIONED_CANNON, "post-111"); } From fc54b9701b6ff0ba63a2590562d3acf80f51dc17 Mon Sep 17 00:00:00 2001 From: Joby Thundil Date: Fri, 24 Oct 2025 11:35:28 -0400 Subject: [PATCH 8/9] add gametype postcheck --- .../script/SwitchToPermissionedGame.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup-templates/template-switch-to-permissioned-game/script/SwitchToPermissionedGame.sol b/setup-templates/template-switch-to-permissioned-game/script/SwitchToPermissionedGame.sol index e505b2d7..fe3b79b6 100644 --- a/setup-templates/template-switch-to-permissioned-game/script/SwitchToPermissionedGame.sol +++ b/setup-templates/template-switch-to-permissioned-game/script/SwitchToPermissionedGame.sol @@ -9,7 +9,7 @@ import {IAnchorStateRegistry} from "@eth-optimism-bedrock/src/dispute/FaultDispu 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} from "@eth-optimism-bedrock/src/dispute/lib/Types.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"; @@ -49,7 +49,7 @@ contract SwitchToPermissionedGame is MultisigScript { // Confirm the CURRENT_RETIREMENT_TIMESTAMP is updated to the block time. function _postCheck(Vm.AccountAccess[] memory, Simulation.Payload memory) internal view override { require(anchorStateRegistry.retirementTimestamp() == block.timestamp, "post-110"); - require(anchorStateRegistry.respectedGameType() == GameTypes.PERMISSIONED_CANNON, "post-111"); + require(GameType.unwrap(anchorStateRegistry.respectedGameType()) == GameType.unwrap(GameTypes.PERMISSIONED_CANNON), "post-111"); } From 88d35c97c98fe628bb7cf1d6bfe0c8119f646e01 Mon Sep 17 00:00:00 2001 From: Joby Thundil Date: Fri, 24 Oct 2025 11:47:21 -0400 Subject: [PATCH 9/9] add filled in senders for base simulation --- .../template-switch-to-permissioned-game/Makefile | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/setup-templates/template-switch-to-permissioned-game/Makefile b/setup-templates/template-switch-to-permissioned-game/Makefile index da400129..12f0b7b0 100644 --- a/setup-templates/template-switch-to-permissioned-game/Makefile +++ b/setup-templates/template-switch-to-permissioned-game/Makefile @@ -24,3 +24,12 @@ approve-op: .PHONY: execute execute: $(call MULTISIG_EXECUTE,0x) + +# Base -- used for simulating the transcations as op-signers by base engineers +.PHONY: sign-base-sepolia +sign-base-mainnet: + $(call MULTISIG_SIGN,$(OP_SECURITY_COUNCIL_SAFE)) --sender 0x1822b35B09f5ce1C78ecbC06AC0A4e17885b925e + +.PHONY: sign-base-sepolia +sign-base-sepolia: + $(call MULTISIG_SIGN,$(OP_SECURITY_COUNCIL_SAFE)) --sender 0x1084092Ac2f04c866806CF3d4a385Afa4F6A6C97