Repository: ethereum-optimism/superchain-ops
Pull request #953: Mode Sepolia to permissioned FPs
Author: login: Wazabie
Created: 2025-05-05T23:17:07Z | Merged: 2025-05-29T21:57:54Z

Description
Adds a task to get Mode Sepolia to use permissioned fault proofs.

Adding initial files.

Only the input file is correct, the others need to be adjusted for this task.


Diff:
diff --git a/.circleci/config.yml b/.circleci/config.yml
index e7399c6f2a..01887766d3 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -505,6 +505,10 @@ workflows:
       - just_simulate_sc_rehearsal_4:
           context:
             - circleci-repo-readonly-authenticated-github-token
+      - just_simulate_nested:
+          task: "/sep/mode-002-fp-upgrade"
+          context:
+            - circleci-repo-readonly-authenticated-github-token
 
       - simulate_sequence:
           name: simulate_sequence_eth
@@ -517,7 +521,7 @@ workflows:
       - simulate_sequence:
           name: simulate_sequence_sep
           network: "sep"
-          tasks: ""
+          tasks: "mode-002"
           block_number: "" # If not specified, the latest block number is used.
           context:
             - circleci-repo-readonly-authenticated-github-token
diff --git a/tasks/sep/mode-002-fp-upgrade/.env b/tasks/sep/mode-002-fp-upgrade/.env
new file mode 100644
index 0000000000..3848bbb676
--- /dev/null
+++ b/tasks/sep/mode-002-fp-upgrade/.env
@@ -0,0 +1,30 @@
+ETH_RPC_URL="https://ethereum-sepolia.publicnode.com"
+
+OWNER_SAFE=0x1Eb2fFc903729a0F03966B917003800b145F56E2
+COUNCIL_SAFE=0xf64bc17485f0B4Ea5F06A96514182FC4cB561977
+FOUNDATION_SAFE=0xDEe57160aAfCF04c34C887B5962D0a69676d3C8B
+LIVENESS_GUARD=0xc26977310bC89DAee5823C2e2a73195E85382cC7
+
+# SAFE_NONCE values are specified below
+SAFE_NONCE_0X1EB2FFC903729A0F03966B917003800B145F56E2=28
+SAFE_NONCE_0XF64BC17485F0B4EA5F06A96514182FC4CB561977=37
+SAFE_NONCE_0XDEE57160AAFCF04C34C887B5962D0A69676D3C8B=42
+
+# Expected prestate is cannon32 1.6.0-rc.2
+EXPECTED_PRESTATE=0x03513e996556589f633fe1d38d694f63bc93cca5df559af37631b30875a829e9
+
+# Expected Guardian address is the STANDARD config role Sepolia Guardian
+EXPECTED_GUARDIAN=0x7a50f00e8D05b95F98fE38d8BeE366a7324dCf7E
+
+# Contracts deployed prior to the upgrade
+EXPECTED_ANCHOR_STATE_REGISTRY_PROXY=0x5C30E13389686AE0ddF41859FbD4BD2CBE2Aaf1D
+EXPECTED_ANCHOR_STATE_REGISTRY_IMPL=0x43c0EA5cf1614a3F16b51804F3283f95d09a903f
+EXPECTED_PERMISSIONED_DISPUTE_GAME_IMPL=0xdC0c2Cb09512490B0b81292b9153415C3f092D4b
+EXPECTED_PERMISSIONED_DELAYED_WETH_PROXY=0xD92Bf98a4049097C4b2288734748dce90803E1C1
+EXPECTED_DISPUTE_GAME_FACTORY_PROXY=0x7Bb634B42373A87712Da14064deD13Db8b8b14f4
+
+# OP Sepolia contracts for bytecode comparison
+# Note that the PermissionedDisputeGame implementation is the one that was used on OP Sepolia until
+# the MT Cannon upgrade and address was pulled from task 019
+COMPARISON_ANCHOR_STATE_REGISTRY_IMPL=0x666D2f5316B8562e9F7B74D0B72a980E8E6F8D5C
+COMPARISON_PERMISSIONED_DISPUTE_GAME_IMPL=0x4Ed046e66c96600DaE1a4ec39267bB0cE476E8cc
diff --git a/tasks/sep/mode-002-fp-upgrade/NestedSignFromJson.s.sol b/tasks/sep/mode-002-fp-upgrade/NestedSignFromJson.s.sol
new file mode 100644
index 0000000000..18e9cdbe69
--- /dev/null
+++ b/tasks/sep/mode-002-fp-upgrade/NestedSignFromJson.s.sol
@@ -0,0 +1,500 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.15;
+
+import {console2 as console} from "forge-std/console2.sol";
+import {Vm, VmSafe} from "forge-std/Vm.sol";
+import {stdJson} from "forge-std/StdJson.sol";
+import {Simulation} from "@base-contracts/script/universal/Simulation.sol";
+import {LibString} from "@solady/utils/LibString.sol";
+import {NestedSignFromJson as OriginalNestedSignFromJson} from "script/NestedSignFromJson.s.sol";
+import {CouncilFoundationNestedSign} from "script/verification/CouncilFoundationNestedSign.s.sol";
+import {SuperchainRegistry} from "script/verification/Verification.s.sol";
+import {BytecodeComparison} from "src/libraries/BytecodeComparison.sol";
+import {GameType} from "@eth-optimism-bedrock/src/dispute/lib/Types.sol";
+import {IProxy} from "@eth-optimism-bedrock/interfaces/universal/IProxy.sol";
+import {IDisputeGameFactory} from "@eth-optimism-bedrock/interfaces/dispute/IDisputeGameFactory.sol";
+import {IPermissionedDisputeGame} from "@eth-optimism-bedrock/interfaces/dispute/IPermissionedDisputeGame.sol";
+import {IAnchorStateRegistry} from "@eth-optimism-bedrock/interfaces/dispute/IAnchorStateRegistry.sol";
+import {IDelayedWETH} from "@eth-optimism-bedrock/interfaces/dispute/IDelayedWETH.sol";
+import {IOptimismPortal2} from "@eth-optimism-bedrock/interfaces/L1/IOptimismPortal2.sol";
+import {ISystemConfig} from "@eth-optimism-bedrock/interfaces/L1/ISystemConfig.sol";
+import {IL1CrossDomainMessenger} from "@eth-optimism-bedrock/interfaces/L1/IL1CrossDomainMessenger.sol";
+import {IL1StandardBridge} from "@eth-optimism-bedrock/interfaces/L1/IL1StandardBridge.sol";
+import {IL1ERC721Bridge} from "@eth-optimism-bedrock/interfaces/L1/IL1ERC721Bridge.sol";
+import {IAddressManager} from "@eth-optimism-bedrock/interfaces/legacy/IAddressManager.sol";
+import {IL1ChugSplashProxy} from "@eth-optimism-bedrock/interfaces/legacy/IL1ChugSplashProxy.sol";
+import {IOptimismMintableERC20Factory} from
+    "@eth-optimism-bedrock/interfaces/universal/IOptimismMintableERC20Factory.sol";
+
+import {AccountAccessParser} from "src/libraries/AccountAccessParser.sol";
+
+interface ISystemConfigLegacy is ISystemConfig {
+    function l2OutputOracle() external view returns (address);
+}
+
+contract NestedSignFromJson is OriginalNestedSignFromJson, CouncilFoundationNestedSign, SuperchainRegistry {
+    using AccountAccessParser for VmSafe.AccountAccess[];
+    /// @notice Expected address for the AnchorStateRegistry proxy.
+    IAnchorStateRegistry expectedAnchorStateRegistryProxy =
+        IAnchorStateRegistry(vm.envAddress("EXPECTED_ANCHOR_STATE_REGISTRY_PROXY"));
+
+    /// @notice Expected address for the AnchorStateRegistry implementation.
+    IAnchorStateRegistry expectedAnchorStateRegistryImpl =
+        IAnchorStateRegistry(vm.envAddress("EXPECTED_ANCHOR_STATE_REGISTRY_IMPL"));
+
+    /// @notice OP Sepolia address for the AnchorStateRegistry implementation for comparison.
+    IAnchorStateRegistry comparisonAnchorStateRegistryImpl =
+        IAnchorStateRegistry(vm.envAddress("COMPARISON_ANCHOR_STATE_REGISTRY_IMPL"));
+
+    /// @notice Expected address for the PermissionedDisputeGame implementation.
+    IPermissionedDisputeGame expectedPermissionedDisputeGameImpl =
+        IPermissionedDisputeGame(vm.envAddress("EXPECTED_PERMISSIONED_DISPUTE_GAME_IMPL"));
+
+    /// @notice OP Sepolia address for the PermissionedDisputeGame implementation for comparison.
+    IPermissionedDisputeGame comparisonPermissionedDisputeGameImpl =
+        IPermissionedDisputeGame(vm.envAddress("COMPARISON_PERMISSIONED_DISPUTE_GAME_IMPL"));
+
+    /// @notice Expected address for the DelayedWETH proxy.
+    IDelayedWETH expectedDelayedWETHProxy =
+        IDelayedWETH(payable(vm.envAddress("EXPECTED_PERMISSIONED_DELAYED_WETH_PROXY")));
+
+    /// @notice Expected address for the DisputeGameFactory proxy.
+    IDisputeGameFactory expectedDisputeGameFactoryProxy =
+        IDisputeGameFactory(vm.envAddress("EXPECTED_DISPUTE_GAME_FACTORY_PROXY"));
+
+    /// @notice Expected prestate.
+    bytes32 expectedPrestate = vm.envBytes32("EXPECTED_PRESTATE");
+
+    /// @notice Expected guardian address.
+    address expectedGuardian = vm.envAddress("EXPECTED_GUARDIAN");
+
+    /// @notice Script constructor.
+    constructor() SuperchainRegistry("sepolia", "mode", "v1.8.0-rc.4") {}
+
+    /// @notice Sets up the script.
+    function setUp() public view {
+        _preCheck();
+    }
+
+    /// @notice Returns addresses that are allowed to not have any code.
+    /// @return allowed_ The addresses that are allowed to not have any code.
+    function getCodeExceptions() internal view override returns (address[] memory allowed_) {
+        allowed_ = new address[](4);
+        allowed_[0] = ISystemConfig(proxies.SystemConfig).owner();
+        allowed_[1] = address(uint160(uint256(ISystemConfig(proxies.SystemConfig).batcherHash())));
+        allowed_[2] = ISystemConfig(proxies.SystemConfig).unsafeBlockSigner();
+        allowed_[3] = ISystemConfig(proxies.SystemConfig).batchInbox();
+    }
+
+    /// @notice Returns addresses that are allowed to access storage.
+    /// @return allowed_ The addresses that are allowed to access storage.
+    function getAllowedStorageAccess() internal view override returns (address[] memory allowed_) {
+        allowed_ = new address[](11);
+        allowed_[0] = vm.envAddress("OWNER_SAFE");
+        allowed_[1] = vm.envAddress("FOUNDATION_SAFE");
+        allowed_[2] = vm.envAddress("COUNCIL_SAFE");
+        allowed_[3] = vm.envAddress("LIVENESS_GUARD");
+        allowed_[4] = proxies.OptimismPortal;
+        allowed_[5] = proxies.SystemConfig;
+        allowed_[6] = addressManager;
+        allowed_[7] = proxies.L1CrossDomainMessenger;
+        allowed_[8] = proxies.L1StandardBridge;
+        allowed_[9] = proxies.L1ERC721Bridge;
+        allowed_[10] = proxies.OptimismMintableERC20Factory;
+    }
+
+    /// @notice Checks correctness prior to execution.
+    function _preCheck() internal view {
+        console.log("Running pre-deploy assertions");
+        checkInputJson();
+        console.log("All assertions passed!");
+    }
+
+    /// @notice Checks correctness after execution.
+    function _postCheck(Vm.AccountAccess[] memory accesses, Simulation.Payload memory) internal override {
+        console.log("Running post-deploy assertions");
+        checkStateDiff(accesses);
+        checkOptimismPortal();
+        checkSystemConfig();
+        checkL1CrossDomainMessenger();
+        checkL1StandardBridge();
+        checkL1ERC721Bridge();
+        checkOptimismMintableERC20Factory();
+        checkAnchorStateRegistry();
+        checkDelayedWETH();
+        checkDisputeGameFactory();
+        checkPermissionedDisputeGame();
+        console.log("All assertions passed!");
+
+        accesses.decodeAndPrint(address(0), bytes32(0));
+    }
+
+    /// @notice Checks the input to the script.
+    function checkInputJson() internal view {
+        string memory inputJson;
+        string memory path = "/tasks/sep/mode-002-fp-upgrade/input.json";
+        try vm.readFile(string.concat(vm.projectRoot(), path)) returns (string memory data) {
+            inputJson = data;
+        } catch {
+            revert(string.concat("Failed to read ", path));
+        }
+
+        // Check that the OptimismPortal proxy and implementation addresses are correct.
+        require(
+            stdJson.readAddress(inputJson, "$.transactions[3].contractInputsValues._proxy")
+                == address(proxies.OptimismPortal),
+            "checkInput-20"
+        );
+        require(
+            stdJson.readAddress(inputJson, "$.transactions[3].contractInputsValues._implementation")
+                == standardVersions.OptimismPortal.implementation,
+            "checkInput-40"
+        );
+
+        // Check that the SystemConfig proxy and implementation addresses are correct.
+        require(
+            stdJson.readAddress(inputJson, "$.transactions[9].contractInputsValues._proxy")
+                == address(proxies.SystemConfig),
+            "checkInput-60"
+        );
+        require(
+            stdJson.readAddress(inputJson, "$.transactions[9].contractInputsValues._implementation")
+                == standardVersions.SystemConfig.implementation,
+            "checkInput-80"
+        );
+
+        // Check that the L1CrossDomainMessenger proxy and implementation addresses are correct.
+        require(
+            stdJson.readAddress(inputJson, "$.transactions[12].contractInputsValues._proxy")
+                == address(proxies.L1CrossDomainMessenger),
+            "checkInput-100"
+        );
+        require(
+            stdJson.readAddress(inputJson, "$.transactions[12].contractInputsValues._implementation")
+                == standardVersions.L1CrossDomainMessenger.implementation,
+            "checkInput-120"
+        );
+
+        // Check that the L1StandardBridge proxy and implementation addresses are correct
+        require(
+            stdJson.readAddress(inputJson, "$.transactions[16].contractInputsValues._proxy")
+                == address(proxies.L1StandardBridge),
+            "checkInput-140"
+        );
+        require(
+            stdJson.readAddress(inputJson, "$.transactions[16].contractInputsValues._implementation")
+                == standardVersions.L1StandardBridge.implementation,
+            "checkInput-160"
+        );
+
+        // Check that the L1ERC721Bridge proxy and implementation addresses are correct
+        require(
+            stdJson.readAddress(inputJson, "$.transactions[20].contractInputsValues._proxy")
+                == address(proxies.L1ERC721Bridge),
+            "checkInput-180"
+        );
+        require(
+            stdJson.readAddress(inputJson, "$.transactions[20].contractInputsValues._implementation")
+                == standardVersions.L1ERC721Bridge.implementation,
+            "checkInput-200"
+        );
+
+        // Check that the OptimismMintableERC20Factory proxy and implementation addresses are correct
+        require(
+            stdJson.readAddress(inputJson, "$.transactions[22].contractInputsValues._proxy")
+                == address(proxies.OptimismMintableERC20Factory),
+            "checkInput-220"
+        );
+        require(
+            stdJson.readAddress(inputJson, "$.transactions[22].contractInputsValues._implementation")
+                == standardVersions.OptimismMintableERC20Factory.implementation,
+            "checkInput-240"
+        );
+    }
+
+    /// @notice Checks that the OptimismPortal was handled correctly.
+    function checkOptimismPortal() internal {
+        // Load contract into correct type.
+        IOptimismPortal2 optimismPortal = IOptimismPortal2(payable(proxies.OptimismPortal));
+
+        // Check that the OptimismPortal implementation is correct.
+        require(
+            _getImplementation(address(optimismPortal)) == standardVersions.OptimismPortal.implementation,
+            "checkOptimismPortal-20"
+        );
+
+        // Check that the OptimismPortal is initialized.
+        require(vm.load(address(optimismPortal), bytes32(uint256(0))) == bytes32(uint256(1)), "checkOptimismPortal-40");
+
+        // Check that the OptimismPortal refers to the correct DisputeGameFactory.
+        require(
+            address(optimismPortal.disputeGameFactory()) == address(expectedDisputeGameFactoryProxy),
+            "checkOptimismPortal-60"
+        );
+
+        // Check that the OptimismPortal refers to the correct SystemConfig.
+        require(address(optimismPortal.systemConfig()) == proxies.SystemConfig, "checkOptimismPortal-80");
+
+        // Check that the OptimismPortal refers to the correct SuperchainConfig.
+        require(address(optimismPortal.superchainConfig()) == proxies.SuperchainConfig, "checkOptimismPortal-100");
+
+        // Check that the OptimismPortal's initial respected game type is 1 (permissioned).
+        require(optimismPortal.respectedGameType().raw() == 1, "checkOptimismPortal-120");
+
+        // Check that the OptimismPortal's l2Sender is the default sender.
+        require(optimismPortal.l2Sender() == address(0xdead), "checkOptimismPortal-140");
+    
+            // Check that the OptimismPortal's guardian is correct.
+        require(optimismPortal.guardian() == expectedGuardian, "checkOptimismPortal-160");
+    }
+
+    /// @notice Checks that the SystemConfig was handled correctly.
+    function checkSystemConfig() internal {
+        // Load contract into correct type.
+        ISystemConfig systemConfig = ISystemConfig(proxies.SystemConfig);
+
+        // Check that the SystemConfig implementation is correct.
+        require(
+            _getImplementation(address(systemConfig)) == standardVersions.SystemConfig.implementation,
+            "checkSystemConfig-20"
+        );
+
+        // Check that the SystemConfig is initialized.
+        require(vm.load(address(systemConfig), bytes32(uint256(0))) == bytes32(uint256(1)), "checkSystemConfig-40");
+
+        // Check that the SystemConfig's DisputeGameFactory reference is correct.
+        require(
+            address(systemConfig.disputeGameFactory()) == address(expectedDisputeGameFactoryProxy),
+            "checkSystemConfig-60"
+        );
+
+        // Check that the SystemConfig's L2OutputOracle reference is removed.
+        try ISystemConfigLegacy(address(systemConfig)).l2OutputOracle() returns (address) {
+            // Function should no longer exist.
+            revert("checkSystemConfig-80");
+        } catch {
+            // Ok.
+        }
+    }
+
+    /// @notice Checks that the L1CrossDomainMessenger was handled correctly.
+    function checkL1CrossDomainMessenger() internal view {
+        // Load contract into correct type.
+        IL1CrossDomainMessenger l1CrossDomainMessenger = IL1CrossDomainMessenger(proxies.L1CrossDomainMessenger);
+
+        // Check that the L1CrossDomainMessenger implementation is correct.
+        require(
+            IAddressManager(addressManager).getAddress("OVM_L1CrossDomainMessenger")
+                == standardVersions.L1CrossDomainMessenger.implementation,
+            "checkL1CrossDomainMessenger-20"
+        );
+
+        // Check that the L1CrossDomainMessenger is initialized.
+        require(
+            vm.load(address(l1CrossDomainMessenger), bytes32(uint256(0)))
+                == bytes32(0x0000000000000000000000010000000000000000000000000000000000000000),
+            "checkL1CrossDomainMessenger-40"
+        );
+
+        // Check that the L1CrossDomainMessenger's SuperchainConfig reference is correct.
+        require(
+            address(l1CrossDomainMessenger.superchainConfig()) == proxies.SuperchainConfig,
+            "checkL1CrossDomainMessenger-60"
+        );
+    }
+
+    /// @notice Checks that the L1StandardBridge was handled correctly.
+    function checkL1StandardBridge() internal {
+        // Load contract into correct type.
+        IL1StandardBridge l1StandardBridge = IL1StandardBridge(payable(proxies.L1StandardBridge));
+
+        // Check that the L1StandardBridge implementation is correct.
+        vm.prank(address(0));
+        require(
+            IL1ChugSplashProxy(payable(l1StandardBridge)).getImplementation()
+                == standardVersions.L1StandardBridge.implementation,
+            "checkL1StandardBridge-20"
+        );
+
+        // Check that the L1StandardBridge is initialized.
+        require(
+            vm.load(address(l1StandardBridge), bytes32(uint256(0))) == bytes32(uint256(1)), "checkL1StandardBridge-40"
+        );
+
+        // Check that the L1StandardBridge's SuperchainConfig reference is correct.
+        require(address(l1StandardBridge.superchainConfig()) == proxies.SuperchainConfig, "checkL1StandardBridge-60");
+    }
+
+    /// @notice Checks that the L1ERC721Bridge was handled correctly.
+    function checkL1ERC721Bridge() internal {
+        // Load contract into correct type.
+        IL1ERC721Bridge l1ERC721Bridge = IL1ERC721Bridge(proxies.L1ERC721Bridge);
+
+        // Check that the L1ERC721Bridge implementation is correct.
+        require(
+            _getImplementation(address(l1ERC721Bridge)) == standardVersions.L1ERC721Bridge.implementation,
+            "checkL1ERC721Bridge-20"
+        );
+
+        // Check that the L1ERC721Bridge is initialized.
+        require(vm.load(address(l1ERC721Bridge), bytes32(uint256(0))) == bytes32(uint256(1)), "checkL1ERC721Bridge-40");
+    }
+
+    /// @notice Checks that the OptimismMintableERC20Factory was handled correctly.
+    function checkOptimismMintableERC20Factory() internal {
+        // Load contract into correct type.
+        IOptimismMintableERC20Factory optimismMintableERC20Factory =
+            IOptimismMintableERC20Factory(proxies.OptimismMintableERC20Factory);
+
+        // Check that the OptimismMintableERC20Factory implementation is correct.
+        require(
+            _getImplementation(address(optimismMintableERC20Factory))
+                == standardVersions.OptimismMintableERC20Factory.implementation,
+            "checkOptimismMintableERC20Factory-20"
+        );
+
+        // Check that the OptimismMintableERC20Factory is initialized.
+        require(
+            vm.load(address(optimismMintableERC20Factory), bytes32(uint256(0))) == bytes32(uint256(1)),
+            "checkOptimismMintableERC20Factory-40"
+        );
+    }
+
+    /// @notice Checks that the AnchorStateRegistry was handled correctly.
+    function checkAnchorStateRegistry() internal {
+        // Check that the AnchorStateRegistry implementation is correct.
+        require(
+            _getImplementation(address(expectedAnchorStateRegistryProxy)) == address(expectedAnchorStateRegistryImpl),
+            "checkAnchorStateRegistry-20"
+        );
+
+        // Check that the AnchorStateRegistry is initialized.
+        require(
+            vm.load(address(expectedAnchorStateRegistryProxy), bytes32(uint256(0))) == bytes32(uint256(1)),
+            "checkAnchorStateRegistry-40"
+        );
+
+        // Check that the AnchorStateRegistry's DisputeGameFactory reference is correct.
+        require(
+            address(expectedAnchorStateRegistryProxy.disputeGameFactory()) == address(expectedDisputeGameFactoryProxy),
+            "checkAnchorStateRegistry-60"
+        );
+
+        // Check that the AnchorStateRegistry version is correct.
+        require(LibString.eq(expectedAnchorStateRegistryProxy.version(), "2.0.0"), "checkAnchorStateRegistry-80");
+
+        // Check that only bytecode diffs vs comparison contract are expected.
+        BytecodeComparison.Diff[] memory diffs = new BytecodeComparison.Diff[](3);
+        diffs[0] = BytecodeComparison.Diff({start: 387, content: abi.encode(expectedDisputeGameFactoryProxy)});
+        diffs[1] = BytecodeComparison.Diff({start: 828, content: abi.encode(expectedDisputeGameFactoryProxy)});
+        diffs[2] = BytecodeComparison.Diff({start: 2296, content: abi.encode(expectedDisputeGameFactoryProxy)});
+        require(
+            BytecodeComparison.compare(
+                address(comparisonAnchorStateRegistryImpl), address(expectedAnchorStateRegistryImpl), diffs
+            ),
+            "checkAnchorStateRegistry-100"
+        );
+    }
+
+    /// @notice Checks that the DelayedWETH was handled correctly.
+    function checkDelayedWETH() internal {
+        // Check that the DelayedWETH implementation is correct.
+        require(
+            _getImplementation(address(expectedDelayedWETHProxy)) == standardVersions.DelayedWETH.implementation,
+            "checkDelayedWETH-20"
+        );
+
+        // Check that the DelayedWETH is initialized.
+        require(
+            vm.load(address(expectedDelayedWETHProxy), bytes32(uint256(0))) == bytes32(uint256(1)),
+            "checkDelayedWETH-40"
+        );
+
+        // Check that the DelayedWETH's owner is correct.
+        require(expectedDelayedWETHProxy.owner() == _ownerSafe(), "checkDelayedWETH-40");
+
+        // Check that the DelayedWETH's SuperchainConfig reference is correct.
+        require(address(expectedDelayedWETHProxy.config()) == proxies.SuperchainConfig, "checkDelayedWETH-60");
+    }
+
+    /// @notice Checks that the DisputeGameFactory was handled correctly.
+    function checkDisputeGameFactory() internal {
+        // Check that the DisputeGameFactory implementation is correct.
+        require(
+            _getImplementation(address(expectedDisputeGameFactoryProxy))
+                == standardVersions.DisputeGameFactory.implementation,
+            "checkDisputeGameFactory-20"
+        );
+
+        // Check that the DisputeGameFactory is initialized.
+        require(
+            vm.load(address(expectedDisputeGameFactoryProxy), bytes32(uint256(0))) == bytes32(uint256(1)),
+            "checkDisputeGameFactory-40"
+        );
+
+        // Check that the DisputeGameFactory's owner is correct.
+        require(expectedDisputeGameFactoryProxy.owner() == _ownerSafe(), "checkDisputeGameFactory-60");
+
+        // Check that the DisputeGameFactory's PermissionedDisputeGame implementation is correct.
+        require(
+            address(expectedDisputeGameFactoryProxy.gameImpls(GameType.wrap(1)))
+                == address(expectedPermissionedDisputeGameImpl),
+            "checkDisputeGameFactory-80"
+        );
+
+        // Check that the DisputeGameFactory has no FaultDisputeGame implementation.
+        require(
+            address(expectedDisputeGameFactoryProxy.gameImpls(GameType.wrap(0))) == address(0),
+            "checkDisputeGameFactory-100"
+        );
+    }
+
+/// @notice Checks that the PermissionedDisputeGame was handled correctly.
+    function checkPermissionedDisputeGame() internal view {
+        // Check that the PermissionedDisputeGame version is correct.
+        require(LibString.eq(expectedPermissionedDisputeGameImpl.version(), "1.3.1"), "checkPermissionedDisputeGame-20");
+
+        // Check that the PermissionedDisputeGame's prestate is correct.
+        require(expectedPermissionedDisputeGameImpl.absolutePrestate().raw() == expectedPrestate, "checkPermissionedDisputeGame-40");
+
+        // Check that the PermissionedDisputeGame's Challenger is correct.
+        // Should be the same as the reference implementation.
+        require(expectedPermissionedDisputeGameImpl.challenger() == comparisonPermissionedDisputeGameImpl.challenger(), "checkPermissionedDisputeGame-60");
+
+        // Check that only bytecode diffs vs comparison contract are expected.
+        BytecodeComparison.Diff[] memory diffs = new BytecodeComparison.Diff[](19);
+        diffs[0] = BytecodeComparison.Diff({start: 1341, content: abi.encode(expectedDelayedWETHProxy)});
+        diffs[1] = BytecodeComparison.Diff({start: 1411, content: abi.encode(chainConfig.challenger)});
+        diffs[2] = BytecodeComparison.Diff({start: 1628, content: abi.encode(expectedAnchorStateRegistryProxy)});
+        diffs[3] = BytecodeComparison.Diff({start: 1999, content: abi.encode(expectedPrestate)});
+        diffs[4] = BytecodeComparison.Diff({start: 2254, content: abi.encode(chainConfig.proposer)});
+        diffs[5] = BytecodeComparison.Diff({start: 2714, content: abi.encode(chainConfig.chainId)});
+        diffs[6] = BytecodeComparison.Diff({start: 6150, content: abi.encode(expectedAnchorStateRegistryProxy)});
+        diffs[7] = BytecodeComparison.Diff({start: 6600, content: abi.encode(expectedDelayedWETHProxy)});
+        diffs[8] = BytecodeComparison.Diff({start: 6870, content: abi.encode(chainConfig.proposer)});
+        diffs[9] = BytecodeComparison.Diff({start: 6933, content: abi.encode(chainConfig.challenger)});
+        diffs[10] = BytecodeComparison.Diff({start: 7076, content: abi.encode(chainConfig.proposer)});
+        diffs[11] = BytecodeComparison.Diff({start: 8310, content: abi.encode(chainConfig.proposer)});
+        diffs[12] = BytecodeComparison.Diff({start: 8373, content: abi.encode(chainConfig.challenger)});
+        diffs[13] = BytecodeComparison.Diff({start: 9555, content: abi.encode(chainConfig.chainId)});
+        diffs[14] = BytecodeComparison.Diff({start: 10798, content: abi.encode(expectedDelayedWETHProxy)});
+        diffs[15] = BytecodeComparison.Diff({start: 13599, content: abi.encode(expectedDelayedWETHProxy)});
+        diffs[16] = BytecodeComparison.Diff({start: 13946, content: abi.encode(expectedAnchorStateRegistryProxy)});
+        diffs[17] = BytecodeComparison.Diff({start: 14972, content: abi.encode(expectedDelayedWETHProxy)});
+        diffs[18] = BytecodeComparison.Diff({start: 17022, content: abi.encode(expectedPrestate)});
+        require(
+            BytecodeComparison.compare(
+                address(comparisonPermissionedDisputeGameImpl), address(expectedPermissionedDisputeGameImpl), diffs
+            ),
+            "checkPermissionedDisputeGame-80"
+        );
+    }
+
+    /// @notice Returns the implementation of a proxy.
+    /// @param _proxy The proxy to get the implementation of.
+    /// @return implementation_ The implementation of the proxy.
+    function _getImplementation(address _proxy) internal returns (address implementation_) {
+        vm.prank(address(0));
+        implementation_ = IProxy(payable(_proxy)).implementation();
+    }
+}
\ No newline at end of file
diff --git a/tasks/sep/mode-002-fp-upgrade/README.md b/tasks/sep/mode-002-fp-upgrade/README.md
new file mode 100644
index 0000000000..6c055a4864
--- /dev/null
+++ b/tasks/sep/mode-002-fp-upgrade/README.md
@@ -0,0 +1,39 @@
+# Mode Sepolia Permissioned Fault Proofs
+
+Status: [DRAFT, NOT READY TO SIGN]
+
+## Objective
+
+The objective of this task is to upgrade Mode Sepolia to Permissioned Fault Proofs at contracts
+version `op-contracts/v1.8.0`.
+
+## Simulation
+
+Please see "Simulating and Verifying the Transaction" in [NESTED.md](../../../NESTED.md).
+
+When simulating, ensure the logs say:
+
+```sh
+Using script /your/path/to/superchain-ops/tasks/sep/mode-002-fp-upgrade/NestedSignFromJson.s.sol
+```
+
+This ensures all safety checks are run. If the default `NestedSignFromJson.s.sol` script is shown
+(without the full path), something is wrong and the safety checks **WILL NOT RUN**.
+
+## State Validations
+
+Please see the instructions for [validation](./VALIDATION.md).
+
+## Execution
+
+At this point you may resume following the execution instructions in the "Execute the Transaction"
+section of [NESTED.md](../../../NESTED.md).
+
+When executing, ensure the logs say:
+
+```sh
+Using script Using script /your/path/to/superchain-ops/tasks/sep/mode-002-fp-upgrade/NestedSignFromJson.s.sol
+```
+
+This ensures all safety checks are run. If the default `NestedSignFromJson.s.sol` script is shown
+(without the full path), something is wrong and the safety checks **WILL NOT RUN**.
diff --git a/tasks/sep/mode-002-fp-upgrade/VALIDATION.md b/tasks/sep/mode-002-fp-upgrade/VALIDATION.md
new file mode 100644
index 0000000000..2fd4956916
--- /dev/null
+++ b/tasks/sep/mode-002-fp-upgrade/VALIDATION.md
@@ -0,0 +1,85 @@
+# Validation
+
+This document can be used to validate the state diff resulting from the execution of the upgrade
+transaction. For each contract listed in the state diff, please verify that no contracts or state
+changes shown in the Tenderly diff are missing from this document.
+
+Additionally, please verify that for each contract:
+
+- The following state changes (and none others) are made to that contract. This validates that no
+  unexpected state changes occur.
+- All addresses (in section headers and storage values) match the provided name, using the
+  Etherscan and Superchain Registry links provided. This validates the bytecode deployed at the
+  addresses contains the correct logic.
+- All key values match the semantic meaning provided, which can be validated using the storage
+  layout links provided.
+
+## Predeploys
+
+- **DisputeGameFactoryProxy**: `0x7Bb634B42373A87712Da14064deD13Db8b8b14f4`
+- **AnchorStateRegistryProxy**: `0x5C30E13389686AE0ddF41859FbD4BD2CBE2Aaf1D`
+- **AnchorStateRegistryImpl**: `0x43c0EA5cf1614a3F16b51804F3283f95d09a903f`
+- **PermissionedDelayedWETHProxy**: `0xD92Bf98a4049097C4b2288734748dce90803E1C1`
+- **PermissionedDisputeGame**: `0xdC0c2Cb09512490B0b81292b9153415C3f092D4b`
+
+## Expected Domain and Message Hashes
+
+> [!CAUTION]
+>
+> Before signing, ensure the below hashes match what is on your ledger.
+>
+> ### Security Council
+>
+> - Domain Hash: `0xbe081970e9fc104bd1ea27e375cd21ec7bb1eec56bfe43347c3e36c5d27b8533`
+> - Message Hash: `0xbc522fd52b91ac9639f0058838fadfa2ef69ed5ba7937cdeb220a44cf8d70bf1`
+>
+> ### Optimism Foundation
+>
+> - Domain Hash: `0x37e1f5dd3b92a004a23589b741196c8a214629d4ea3a690ec8e41ae45c689cbb`
+> - Message Hash: `0x1dfa5b291917dc6fa60b42a0d8dc0e928f2c83524beac422454070bae22620c0`
+
+## Nested Safe State Overrides and Changes
+
+This task is executed by the nested 2/2 `ProxyAdminOwner` Safe. Refer to the
+[generic nested Safe execution validation document](../../../NESTED-VALIDATION.md) for the expected
+state overrides and changes.
+
+The `approvedHashes` mapping **key** of the `ProxyAdminOwner` that should change during the
+simulation is:
+
+- Council simulation: `0xc8975897b3a17dd64187fa6ed2bab49497341305f1b6a2e7f2e53dbe56217eb4`
+- Foundation simulation: `0x7023b0002c2f5b2122afd072918fee774d8f036da616618afaf3b870bac96692`
+
+## State Changes
+
+### `0x15cd4f6e0CE3B4832B33cB9c6f6Fe6fc246754c2` (`SystemConfigProxy` on Mode Sepolia)
+
+- **Key**: `0x52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa906`
+- **Before**: `0x0000000000000000000000000000000000000000000000000000000000000000`
+- **After**: `0x0000000000000000000000007bb634b42373a87712da14064ded13db8b8b14f4`
+- **Meaning**: Slot at keccak(systemconfig.disputegamefactory)-1 set to address of
+  DisputeGameFactoryProxy deployed via upgrade script
+
+- **Key**: `0xe52a667f71ec761b9b381c7b76ca9b852adf7e8905da0e0ad49986a0a6871815`
+- **Before**: `0x0000000000000000000000002634BD65ba27AB63811c74A63118ACb312701Bfa`
+- **After**: `0x0000000000000000000000000000000000000000000000000000000000000000`
+- **Meaning**: Slot at keccak(systemconfig.l2outputoracle)-1 deleted
+
+### `0x320e1580effF37E008F1C92700d1eBa47c1B23fD` (`OptimismPortalProxy` on Mode Sepolia)
+
+- **Key**: `0x0000000000000000000000000000000000000000000000000000000000000038`
+- **Before**: `0x0000000000000000000000000000000000000000000000000000000000000000`
+- **After**: `0x0000000000000000000000007bb634b42373a87712da14064ded13db8b8b14f4`
+- **Meaning**: DisputeGameFactory address variable set to the address deployed in upgrade script
+
+- **Key**: `0x000000000000000000000000000000000000000000000000000000000000003b`
+- **Before**: `0x0000000000000000000000000000000000000000000000000000000000000000`
+- **After**: `0x00000000000000000000000000000000000000000000000TIMESTAMP00000001`
+- **Meaning**: Sets the respectedGameType to 1 (permissioned game) and sets the
+  respectedGameTypeUpdatedAt timestamp to the time when the upgrade transaction was executed (will
+  be a dynamic value)
+
+- **Key**: `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`
+- **Before**: `0x0000000000000000000000002d778797049fe9259d947d1ed8e5442226dfb589`
+- **After**: `0x00000000000000000000000035028bae87d71cbc192d545d38f960ba30b4b233`
+- **Meaning**: Implementation address updated
diff --git a/tasks/sep/mode-002-fp-upgrade/input.json b/tasks/sep/mode-002-fp-upgrade/input.json
new file mode 100644
index 0000000000..9684115ced
--- /dev/null
+++ b/tasks/sep/mode-002-fp-upgrade/input.json
@@ -0,0 +1,607 @@
+{
+  "version": "1.0",
+  "chainId": "11155111",
+  "createdAt": 1746479915431,
+  "meta": {
+    "name": "Transactions Batch",
+    "description": "",
+    "txBuilderVersion": "1.17.0",
+    "createdFromSafeAddress": "",
+    "createdFromOwnerAddress": ""
+  },
+  "transactions": [
+    {
+      "to": "0xE7413127F29E050Df65ac3FC9335F85bB10091AE",
+      "value": "0",
+      "data": "0x99a88ec4000000000000000000000000320e1580efff37e008f1c92700d1eba47c1b23fd000000000000000000000000d81f43edbcacb4c29a9ba38a13ee5d79278270cc",
+      "contractMethod": {
+        "inputs": [
+          {
+            "name": "_proxy",
+            "type": "address",
+            "internalType": "address payable"
+          },
+          {
+            "name": "_implementation",
+            "type": "address",
+            "internalType": "address"
+          }
+        ],
+        "name": "upgrade",
+        "payable": false
+      },
+      "contractInputsValues": {
+        "_proxy": "0x320e1580effF37E008F1C92700d1eBa47c1B23fD",
+        "_implementation": "0xd81f43edbcacb4c29a9ba38a13ee5d79278270cc"
+      }
+    },
+    {
+      "to": "0x320e1580effF37E008F1C92700d1eBa47c1B23fD",
+      "value": "0",
+      "data": "0x4e91db0800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+      "contractMethod": {
+        "inputs": [
+          {
+            "name": "_slot",
+            "type": "bytes32",
+            "internalType": "bytes32"
+          },
+          {
+            "name": "_value",
+            "type": "bytes32",
+            "internalType": "bytes32"
+          }
+        ],
+        "name": "setBytes32",
+        "payable": false
+      },
+      "contractInputsValues": {
+        "_slot": "0x0000000000000000000000000000000000000000000000000000000000000000",
+        "_value": "0x0000000000000000000000000000000000000000000000000000000000000000"
+      }
+    },
+    {
+      "to": "0x320e1580effF37E008F1C92700d1eBa47c1B23fD",
+      "value": "0",
+      "data": "0x4e91db0800000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000000",
+      "contractMethod": {
+        "inputs": [
+          {
+            "name": "_slot",
+            "type": "bytes32",
+            "internalType": "bytes32"
+          },
+          {
+            "name": "_value",
+            "type": "bytes32",
+            "internalType": "bytes32"
+          }
+        ],
+        "name": "setBytes32",
+        "payable": false
+      },
+      "contractInputsValues": {
+        "_slot": "0x0000000000000000000000000000000000000000000000000000000000000032",
+        "_value": "0x0000000000000000000000000000000000000000000000000000000000000000"
+      }
+    },
+    {
+      "to": "0xE7413127F29E050Df65ac3FC9335F85bB10091AE",
+      "value": "0",
+      "data": "0x99a88ec4000000000000000000000000320e1580efff37e008f1c92700d1eba47c1b23fd00000000000000000000000035028bae87d71cbc192d545d38f960ba30b4b233",
+      "contractMethod": {
+        "inputs": [
+          {
+            "name": "_proxy",
+            "type": "address",
+            "internalType": "address payable"
+          },
+          {
+            "name": "_implementation",
+            "type": "address",
+            "internalType": "address"
+          }
+        ],
+        "name": "upgrade",
+        "payable": false
+      },
+      "contractInputsValues": {
+        "_proxy": "0x320e1580effF37E008F1C92700d1eBa47c1B23fD",
+        "_implementation": "0x35028bae87d71cbc192d545d38f960ba30b4b233"
+      }
+    },
+    {
+      "to": "0x320e1580effF37E008F1C92700d1eBa47c1B23fD",
+      "value": "0",
+      "data": "0x8e819e540000000000000000000000007bb634b42373a87712da14064ded13db8b8b14f400000000000000000000000015cd4f6e0ce3b4832b33cb9c6f6fe6fc246754c2000000000000000000000000c2be75506d5724086deb7245bd260cc9753911be0000000000000000000000000000000000000000000000000000000000000001",
+      "contractMethod": {
+        "inputs": [
+          {
+            "name": "_disputeGameFactory",
+            "type": "address",
+            "internalType": "contract DisputeGameFactory"
+          },
+          {
+            "name": "_systemConfig",
+            "type": "address",
+            "internalType": "contract SystemConfig"
+          },
+          {
+            "name": "_superchainConfig",
+            "type": "address",
+            "internalType": "contract SuperchainConfig"
+          },
+          {
+            "name": "_initialRespectedGameType",
+            "type": "uint32",
+            "internalType": "GameType"
+          }
+        ],
+        "name": "initialize",
+        "payable": false
+      },
+      "contractInputsValues": {
+        "_disputeGameFactory": "0x7Bb634B42373A87712Da14064deD13Db8b8b14f4",
+        "_systemConfig": "0x15cd4f6e0CE3B4832B33cB9c6f6Fe6fc246754c2",
+        "_superchainConfig": "0xC2Be75506d5724086DEB7245bd260Cc9753911Be",
+        "_initialRespectedGameType": "1"
+      }
+    },
+    {
+      "to": "0xE7413127F29E050Df65ac3FC9335F85bB10091AE",
+      "value": "0",
+      "data": "0x99a88ec400000000000000000000000015cd4f6e0ce3b4832b33cb9c6f6fe6fc246754c2000000000000000000000000d81f43edbcacb4c29a9ba38a13ee5d79278270cc",
+      "contractMethod": {
+        "inputs": [
+          {
+            "name": "_proxy",
+            "type": "address",
+            "internalType": "address payable"
+          },
+          {
+            "name": "_implementation",
+            "type": "address",
+            "internalType": "address"
+          }
+        ],
+        "name": "upgrade",
+        "payable": false
+      },
+      "contractInputsValues": {
+        "_proxy": "0x15cd4f6e0CE3B4832B33cB9c6f6Fe6fc246754c2",
+        "_implementation": "0xd81f43edbcacb4c29a9ba38a13ee5d79278270cc"
+      }
+    },
+    {
+      "to": "0x15cd4f6e0CE3B4832B33cB9c6f6Fe6fc246754c2",
+      "value": "0",
+      "data": "0x4e91db08e52a667f71ec761b9b381c7b76ca9b852adf7e8905da0e0ad49986a0a68718150000000000000000000000000000000000000000000000000000000000000000",
+      "contractMethod": {
+        "inputs": [
+          {
+            "name": "_slot",
+            "type": "bytes32",
+            "internalType": "bytes32"
+          },
+          {
+            "name": "_value",
+            "type": "bytes32",
+            "internalType": "bytes32"
+          }
+        ],
+        "name": "setBytes32",
+        "payable": false
+      },
+      "contractInputsValues": {
+        "_slot": "0xe52a667f71ec761b9b381c7b76ca9b852adf7e8905da0e0ad49986a0a6871815",
+        "_value": "0x0000000000000000000000000000000000000000000000000000000000000000"
+      }
+    },
+    {
+      "to": "0x15cd4f6e0CE3B4832B33cB9c6f6Fe6fc246754c2",
+      "value": "0",
+      "data": "0xca446dd952322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa9060000000000000000000000007bb634b42373a87712da14064ded13db8b8b14f4",
+      "contractMethod": {
+        "inputs": [
+          {
+            "name": "_slot",
+            "type": "bytes32",
+            "internalType": "bytes32"
+          },
+          {
+            "name": "_address",
+            "type": "address",
+            "internalType": "address"
+          }
+        ],
+        "name": "setAddress",
+        "payable": false
+      },
+      "contractInputsValues": {
+        "_slot": "0x52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa906",
+        "_address": "0x7Bb634B42373A87712Da14064deD13Db8b8b14f4"
+      }
+    },
+    {
+      "to": "0x15cd4f6e0CE3B4832B33cB9c6f6Fe6fc246754c2",
+      "value": "0",
+      "data": "0x4e91db0800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+      "contractMethod": {
+        "inputs": [
+          {
+            "name": "_slot",
+            "type": "bytes32",
+            "internalType": "bytes32"
+          },
+          {
+            "name": "_value",
+            "type": "bytes32",
+            "internalType": "bytes32"
+          }
+        ],
+        "name": "setBytes32",
+        "payable": false
+      },
+      "contractInputsValues": {
+        "_slot": "0x0000000000000000000000000000000000000000000000000000000000000000",
+        "_value": "0x0000000000000000000000000000000000000000000000000000000000000000"
+      }
+    },
+    {
+      "to": "0xE7413127F29E050Df65ac3FC9335F85bB10091AE",
+      "value": "0",
+      "data": "0x9623609d00000000000000000000000015cd4f6e0ce3b4832b33cb9c6f6fe6fc246754c200000000000000000000000033b83e4c305c908b2fc181dda36e230213058d7d00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000284db9040fa00000000000000000000000023ba22dd7923f3a3f2495bb32a6f3c9b9cd1ec6c00000000000000000000000000000000000000000000000000000000000003d1000000000000000000000000000000000000000000000000000000000008ee870000000000000000000000004e6bd53883107b063c502ddd49f9600dc51b3ddc0000000000000000000000000000000000000000000000000000000001c9c38000000000000000000000000093a14e6894eeb4ff6a373e1ad4f498c3a207afe40000000000000000000000000000000000000000000000000000000001312d00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000003b9aca0000000000000000000000000000000000000000000000000000000000000f424000000000000000000000000000000000ffffffffffffffffffffffffffffffff000000000000000000000000cddae6148da1e003c230e4527f9baedc8a204e7e000000000000000000000000c19a60d9e8c27b9a43527c3283b4dd8edc8be15c000000000000000000000000015a8c2e0a5fed579dbb05fd290e413adc6fc24a000000000000000000000000bc5c679879b2965296756cd959c3c739769995e20000000000000000000000007bb634b42373a87712da14064ded13db8b8b14f4000000000000000000000000320e1580efff37e008f1c92700d1eba47c1b23fd00000000000000000000000000f7ab8c72d32f55cff15e8901c2f9f2bf29a3c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+      "contractMethod": {
+        "inputs": [
+          {
+            "name": "_proxy",
+            "type": "address",
+            "internalType": "address payable"
+          },
+          {
+            "name": "_implementation",
+            "type": "address",
+            "internalType": "address"
+          },
+          {
+            "internalType": "bytes",
+            "name": "_data",
+            "type": "bytes"
+          }
+        ],
+        "name": "upgradeAndCall",
+        "payable": false
+      },
+      "contractInputsValues": {
+        "_data": "0xdb9040fa00000000000000000000000023ba22dd7923f3a3f2495bb32a6f3c9b9cd1ec6c00000000000000000000000000000000000000000000000000000000000003d1000000000000000000000000000000000000000000000000000000000008ee870000000000000000000000004e6bd53883107b063c502ddd49f9600dc51b3ddc0000000000000000000000000000000000000000000000000000000001c9c38000000000000000000000000093a14e6894eeb4ff6a373e1ad4f498c3a207afe40000000000000000000000000000000000000000000000000000000001312d00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000003b9aca0000000000000000000000000000000000000000000000000000000000000f424000000000000000000000000000000000ffffffffffffffffffffffffffffffff000000000000000000000000cddae6148da1e003c230e4527f9baedc8a204e7e000000000000000000000000c19a60d9e8c27b9a43527c3283b4dd8edc8be15c000000000000000000000000015a8c2e0a5fed579dbb05fd290e413adc6fc24a000000000000000000000000bc5c679879b2965296756cd959c3c739769995e20000000000000000000000007bb634b42373a87712da14064ded13db8b8b14f4000000000000000000000000320e1580efff37e008f1c92700d1eba47c1b23fd00000000000000000000000000f7ab8c72d32f55cff15e8901c2f9f2bf29a3c00000000000000000000000000000000000000000000000000000000000000000",
+        "_proxy": "0x15cd4f6e0CE3B4832B33cB9c6f6Fe6fc246754c2",
+        "_implementation": "0x33b83E4C305c908B2Fc181dDa36e230213058d7d"
+      }
+    },
+    {
+      "to": "0xE7413127F29E050Df65ac3FC9335F85bB10091AE",
+      "value": "0",
+      "data": "0x99a88ec4000000000000000000000000c19a60d9e8c27b9a43527c3283b4dd8edc8be15c000000000000000000000000d81f43edbcacb4c29a9ba38a13ee5d79278270cc",
+      "contractMethod": {
+        "inputs": [
+          {
+            "name": "_proxy",
+            "type": "address",
+            "internalType": "address payable"
+          },
+          {
+            "name": "_implementation",
+            "type": "address",
+            "internalType": "address"
+          }
+        ],
+        "name": "upgrade",
+        "payable": false
+      },
+      "contractInputsValues": {
+        "_proxy": "0xc19a60d9E8C27B9A43527c3283B4dd8eDC8bE15C",
+        "_implementation": "0xd81f43edbcacb4c29a9ba38a13ee5d79278270cc"
+      }
+    },
+    {
+      "to": "0xc19a60d9E8C27B9A43527c3283B4dd8eDC8bE15C",
+      "value": "0",
+      "data": "0x4e91db0800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+      "contractMethod": {
+        "inputs": [
+          {
+            "name": "_slot",
+            "type": "bytes32",
+            "internalType": "bytes32"
+          },
+          {
+            "name": "_value",
+            "type": "bytes32",
+            "internalType": "bytes32"
+          }
+        ],
+        "name": "setBytes32",
+        "payable": false
+      },
+      "contractInputsValues": {
+        "_slot": "0x0000000000000000000000000000000000000000000000000000000000000000",
+        "_value": "0x0000000000000000000000000000000000000000000000000000000000000000"
+      }
+    },
+    {
+      "to": "0xE7413127F29E050Df65ac3FC9335F85bB10091AE",
+      "value": "0",
+      "data": "0x99a88ec4000000000000000000000000c19a60d9e8c27b9a43527c3283b4dd8edc8be15c000000000000000000000000d3494713a5cfad3f5359379dfa074e2ac8c6fd65",
+      "contractMethod": {
+        "inputs": [
+          {
+            "name": "_proxy",
+            "type": "address",
+            "internalType": "address payable"
+          },
+          {
+            "name": "_implementation",
+            "type": "address",
+            "internalType": "address"
+          }
+        ],
+        "name": "upgrade",
+        "payable": false
+      },
+      "contractInputsValues": {
+        "_proxy": "0xc19a60d9E8C27B9A43527c3283B4dd8eDC8bE15C",
+        "_implementation": "0xD3494713A5cfaD3F5359379DfA074E2Ac8C6Fd65"
+      }
+    },
+    {
+      "to": "0xc19a60d9E8C27B9A43527c3283B4dd8eDC8bE15C",
+      "value": "0",
+      "data": "0x485cc955000000000000000000000000c2be75506d5724086deb7245bd260cc9753911be000000000000000000000000320e1580efff37e008f1c92700d1eba47c1b23fd",
+      "contractMethod": {
+        "inputs": [
+          {
+            "internalType": "contract SuperchainConfig",
+            "name": "_superchainConfig",
+            "type": "address"
+          },
+          {
+            "internalType": "contract OptimismPortal",
+            "name": "_portal",
+            "type": "address"
+          }
+        ],
+        "name": "initialize",
+        "payable": false
+      },
+      "contractInputsValues": {
+        "_superchainConfig": "0xC2Be75506d5724086DEB7245bd260Cc9753911Be",
+        "_portal": "0x320e1580effF37E008F1C92700d1eBa47c1B23fD"
+      }
+    },
+    {
+      "to": "0xE7413127F29E050Df65ac3FC9335F85bB10091AE",
+      "value": "0",
+      "data": "0x99a88ec4000000000000000000000000bc5c679879b2965296756cd959c3c739769995e2000000000000000000000000d81f43edbcacb4c29a9ba38a13ee5d79278270cc",
+      "contractMethod": {
+        "inputs": [
+          {
+            "name": "_proxy",
+            "type": "address",
+            "internalType": "address payable"
+          },
+          {
+            "name": "_implementation",
+            "type": "address",
+            "internalType": "address"
+          }
+        ],
+        "name": "upgrade",
+        "payable": false
+      },
+      "contractInputsValues": {
+        "_proxy": "0xbC5C679879B2965296756CD959C3C739769995E2",
+        "_implementation": "0xd81f43edbcacb4c29a9ba38a13ee5d79278270cc"
+      }
+    },
+    {
+      "to": "0xbC5C679879B2965296756CD959C3C739769995E2",
+      "value": "0",
+      "data": "0x4e91db0800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+      "contractMethod": {
+        "inputs": [
+          {
+            "name": "_slot",
+            "type": "bytes32",
+            "internalType": "bytes32"
+          },
+          {
+            "name": "_value",
+            "type": "bytes32",
+            "internalType": "bytes32"
+          }
+        ],
+        "name": "setBytes32",
+        "payable": false
+      },
+      "contractInputsValues": {
+        "_slot": "0x0000000000000000000000000000000000000000000000000000000000000000",
+        "_value": "0x0000000000000000000000000000000000000000000000000000000000000000"
+      }
+    },
+    {
+      "to": "0xE7413127F29E050Df65ac3FC9335F85bB10091AE",
+      "value": "0",
+      "data": "0x99a88ec4000000000000000000000000bc5c679879b2965296756cd959c3c739769995e200000000000000000000000064b5a5ed26dcb17370ff4d33a8d503f0fbd06cff",
+      "contractMethod": {
+        "inputs": [
+          {
+            "name": "_proxy",
+            "type": "address",
+            "internalType": "address payable"
+          },
+          {
+            "name": "_implementation",
+            "type": "address",
+            "internalType": "address"
+          }
+        ],
+        "name": "upgrade",
+        "payable": false
+      },
+      "contractInputsValues": {
+        "_proxy": "0xbC5C679879B2965296756CD959C3C739769995E2",
+        "_implementation": "0x64b5a5ed26dcb17370ff4d33a8d503f0fbd06cff"
+      }
+    },
+    {
+      "to": "0xbC5C679879B2965296756CD959C3C739769995E2",
+      "value": "0",
+      "data": "0x485cc955000000000000000000000000c19a60d9e8c27b9a43527c3283b4dd8edc8be15c000000000000000000000000c2be75506d5724086deb7245bd260cc9753911be",
+      "contractMethod": {
+        "inputs": [
+          {
+            "internalType": "contract CrossDomainMessenger",
+            "name": "_messenger",
+            "type": "address"
+          },
+          {
+            "internalType": "contract SuperchainConfig",
+            "name": "_superchainConfig",
+            "type": "address"
+          }
+        ],
+        "name": "initialize",
+        "payable": false
+      },
+      "contractInputsValues": {
+        "_messenger": "0xc19a60d9E8C27B9A43527c3283B4dd8eDC8bE15C",
+        "_superchainConfig": "0xC2Be75506d5724086DEB7245bd260Cc9753911Be"
+      }
+    },
+    {
+      "to": "0xE7413127F29E050Df65ac3FC9335F85bB10091AE",
+      "value": "0",
+      "data": "0x99a88ec4000000000000000000000000015a8c2e0a5fed579dbb05fd290e413adc6fc24a000000000000000000000000d81f43edbcacb4c29a9ba38a13ee5d79278270cc",
+      "contractMethod": {
+        "inputs": [
+          {
+            "name": "_proxy",
+            "type": "address",
+            "internalType": "address payable"
+          },
+          {
+            "name": "_implementation",
+            "type": "address",
+            "internalType": "address"
+          }
+        ],
+        "name": "upgrade",
+        "payable": false
+      },
+      "contractInputsValues": {
+        "_proxy": "0x015a8c2e0a5fEd579dbb05fd290e413Adc6FC24A",
+        "_implementation": "0xd81f43edbcacb4c29a9ba38a13ee5d79278270cc"
+      }
+    },
+    {
+      "to": "0x015a8c2e0a5fEd579dbb05fd290e413Adc6FC24A",
+      "value": "0",
+      "data": "0x4e91db0800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+      "contractMethod": {
+        "inputs": [
+          {
+            "name": "_slot",
+            "type": "bytes32",
+            "internalType": "bytes32"
+          },
+          {
+            "name": "_value",
+            "type": "bytes32",
+            "internalType": "bytes32"
+          }
+        ],
+        "name": "setBytes32",
+        "payable": false
+      },
+      "contractInputsValues": {
+        "_slot": "0x0000000000000000000000000000000000000000000000000000000000000000",
+        "_value": "0x0000000000000000000000000000000000000000000000000000000000000000"
+      }
+    },
+    {
+      "to": "0xE7413127F29E050Df65ac3FC9335F85bB10091AE",
+      "value": "0",
+      "data": "0x99a88ec4000000000000000000000000015a8c2e0a5fed579dbb05fd290e413adc6fc24a000000000000000000000000ae2af01232a6c4a4d3012c5ec5b1b35059caf10d",
+      "contractMethod": {
+        "inputs": [
+          {
+            "name": "_proxy",
+            "type": "address",
+            "internalType": "address payable"
+          },
+          {
+            "name": "_implementation",
+            "type": "address",
+            "internalType": "address"
+          }
+        ],
+        "name": "upgrade",
+        "payable": false
+      },
+      "contractInputsValues": {
+        "_proxy": "0x015a8c2e0a5fEd579dbb05fd290e413Adc6FC24A",
+        "_implementation": "0xae2af01232a6c4a4d3012c5ec5b1b35059caf10d"
+      }
+    },
+    {
+      "to": "0x015a8c2e0a5fEd579dbb05fd290e413Adc6FC24A",
+      "value": "0",
+      "data": "0x485cc955000000000000000000000000c19a60d9e8c27b9a43527c3283b4dd8edc8be15c000000000000000000000000c2be75506d5724086deb7245bd260cc9753911be",
+      "contractMethod": {
+        "inputs": [
+          {
+            "name": "_messenger",
+            "type": "address",
+            "internalType": "contract CrossDomainMessenger"
+          },
+          {
+            "name": "_superchainConfig",
+            "type": "address",
+            "internalType": "contract SuperchainConfig"
+          }
+        ],
+        "name": "initialize",
+        "payable": false
+      },
+      "contractInputsValues": {
+        "_messenger": "0xc19a60d9E8C27B9A43527c3283B4dd8eDC8bE15C",
+        "_superchainConfig": "0xC2Be75506d5724086DEB7245bd260Cc9753911Be"
+      }
+    },
+    {
+      "to": "0xE7413127F29E050Df65ac3FC9335F85bB10091AE",
+      "value": "0",
+      "data": "0x99a88ec400000000000000000000000000f7ab8c72d32f55cff15e8901c2f9f2bf29a3c0000000000000000000000000e01efbeb1089d1d1db9c6c8b135c934c0734c846",
+      "contractMethod": {
+        "inputs": [
+          {
+            "name": "_proxy",
+            "type": "address",
+            "internalType": "address payable"
+          },
+          {
+            "name": "_implementation",
+            "type": "address",
+            "internalType": "address"
+          }
+        ],
+        "name": "upgrade",
+        "payable": false
+      },
+      "contractInputsValues": {
+        "_proxy": "0x00F7ab8c72D32f55cFf15e8901C2F9f2BF29A3C0",
+        "_implementation": "0xe01efbeb1089d1d1db9c6c8b135c934c0734c846"
+      }
+    }
+  ]
+}


Reviews:
user: login: ajsutton
body: This generally looks pretty sane but the predeployed DisputeGameFactory is using version 1.0.0 instead of 1.3.1.  There may be other issues with the deployed contracts but the different version makes it hard to compare against expected configs.
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-29T05:33:43Z
user: login: ajsutton
body: Apart from the addresses in the validation headings and the need to confirm the challenger role change, this LGTM.

The deployed dispute game checks out in terms of expected contract versions and config settings.
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-29T05:42:47Z
user: login: Wazabie
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-29T15:02:05Z
user: login: ajsutton
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-29T21:03:44Z
user: login: mds1
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-29T21:47:17Z

Review comments:
diff_hunk: @@ -0,0 +1,85 @@
+# Validation
+
+This document can be used to validate the state diff resulting from the execution of the upgrade
+transaction. For each contract listed in the state diff, please verify that no contracts or state
+changes shown in the Tenderly diff are missing from this document.
+
+Additionally, please verify that for each contract:
+
+- The following state changes (and none others) are made to that contract. This validates that no
+  unexpected state changes occur.
+- All addresses (in section headers and storage values) match the provided name, using the
+  Etherscan and Superchain Registry links provided. This validates the bytecode deployed at the
+  addresses contains the correct logic.
+- All key values match the semantic meaning provided, which can be validated using the storage
+  layout links provided.
+
+## Predeploys
+
+- **DisputeGameFactoryProxy**: `0x7Bb634B42373A87712Da14064deD13Db8b8b14f4`
+- **AnchorStateRegistryProxy**: `0x5C30E13389686AE0ddF41859FbD4BD2CBE2Aaf1D`
+- **AnchorStateRegistryImpl**: `0x43c0EA5cf1614a3F16b51804F3283f95d09a903f`
+- **PermissionedDelayedWETHProxy**: `0xD92Bf98a4049097C4b2288734748dce90803E1C1`
+- **PermissionedDisputeGame**: `0xdC0c2Cb09512490B0b81292b9153415C3f092D4b`
+
+## Expected Domain and Message Hashes
+
+> [!CAUTION]
+>
+> Before signing, ensure the below hashes match what is on your ledger.
+>
+> ### Security Council
+>
+> - Domain Hash: `0xbe081970e9fc104bd1ea27e375cd21ec7bb1eec56bfe43347c3e36c5d27b8533`
+> - Message Hash: `0xbc522fd52b91ac9639f0058838fadfa2ef69ed5ba7937cdeb220a44cf8d70bf1`
+>
+> ### Optimism Foundation
+>
+> - Domain Hash: `0x37e1f5dd3b92a004a23589b741196c8a214629d4ea3a690ec8e41ae45c689cbb`
+> - Message Hash: `0x1dfa5b291917dc6fa60b42a0d8dc0e928f2c83524beac422454070bae22620c0`
+
+## Nested Safe State Overrides and Changes
+
+This task is executed by the nested 2/2 `ProxyAdminOwner` Safe. Refer to the
+[generic nested Safe execution validation document](../../../NESTED-VALIDATION.md) for the expected
+state overrides and changes.
+
+The `approvedHashes` mapping **key** of the `ProxyAdminOwner` that should change during the
+simulation is:
+
+- Council simulation: `0xc8975897b3a17dd64187fa6ed2bab49497341305f1b6a2e7f2e53dbe56217eb4`
+- Foundation simulation: `0x7023b0002c2f5b2122afd072918fee774d8f036da616618afaf3b870bac96692`
+
+## State Changes
+
+### `0xA3cAB0126d5F504B071b81a3e8A2BBBF17930d86` (`SystemConfigProxy` on Mode Sepolia)
path: tasks/sep/mode-002-fp-upgrade/VALIDATION.md
user: login: ajsutton
body: This is not the address for SystemConfigProxy for mode-sepolia.
created_at: 2025-05-29T05:26:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,85 @@
+# Validation
+
+This document can be used to validate the state diff resulting from the execution of the upgrade
+transaction. For each contract listed in the state diff, please verify that no contracts or state
+changes shown in the Tenderly diff are missing from this document.
+
+Additionally, please verify that for each contract:
+
+- The following state changes (and none others) are made to that contract. This validates that no
+  unexpected state changes occur.
+- All addresses (in section headers and storage values) match the provided name, using the
+  Etherscan and Superchain Registry links provided. This validates the bytecode deployed at the
+  addresses contains the correct logic.
+- All key values match the semantic meaning provided, which can be validated using the storage
+  layout links provided.
+
+## Predeploys
+
+- **DisputeGameFactoryProxy**: `0x7Bb634B42373A87712Da14064deD13Db8b8b14f4`
+- **AnchorStateRegistryProxy**: `0x5C30E13389686AE0ddF41859FbD4BD2CBE2Aaf1D`
+- **AnchorStateRegistryImpl**: `0x43c0EA5cf1614a3F16b51804F3283f95d09a903f`
+- **PermissionedDelayedWETHProxy**: `0xD92Bf98a4049097C4b2288734748dce90803E1C1`
+- **PermissionedDisputeGame**: `0xdC0c2Cb09512490B0b81292b9153415C3f092D4b`
+
+## Expected Domain and Message Hashes
+
+> [!CAUTION]
+>
+> Before signing, ensure the below hashes match what is on your ledger.
+>
+> ### Security Council
+>
+> - Domain Hash: `0xbe081970e9fc104bd1ea27e375cd21ec7bb1eec56bfe43347c3e36c5d27b8533`
+> - Message Hash: `0xbc522fd52b91ac9639f0058838fadfa2ef69ed5ba7937cdeb220a44cf8d70bf1`
+>
+> ### Optimism Foundation
+>
+> - Domain Hash: `0x37e1f5dd3b92a004a23589b741196c8a214629d4ea3a690ec8e41ae45c689cbb`
+> - Message Hash: `0x1dfa5b291917dc6fa60b42a0d8dc0e928f2c83524beac422454070bae22620c0`
+
+## Nested Safe State Overrides and Changes
+
+This task is executed by the nested 2/2 `ProxyAdminOwner` Safe. Refer to the
+[generic nested Safe execution validation document](../../../NESTED-VALIDATION.md) for the expected
+state overrides and changes.
+
+The `approvedHashes` mapping **key** of the `ProxyAdminOwner` that should change during the
+simulation is:
+
+- Council simulation: `0xc8975897b3a17dd64187fa6ed2bab49497341305f1b6a2e7f2e53dbe56217eb4`
+- Foundation simulation: `0x7023b0002c2f5b2122afd072918fee774d8f036da616618afaf3b870bac96692`
+
+## State Changes
+
+### `0xA3cAB0126d5F504B071b81a3e8A2BBBF17930d86` (`SystemConfigProxy` on Mode Sepolia)
+
+- **Key**: `0x52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa906`
+- **Before**: `0x0000000000000000000000000000000000000000000000000000000000000000`
+- **After**: `0x0000000000000000000000007bb634b42373a87712da14064ded13db8b8b14f4`
+- **Meaning**: Slot at keccak(systemconfig.disputegamefactory)-1 set to address of
+  DisputeGameFactoryProxy deployed via upgrade script
+
+- **Key**: `0xe52a667f71ec761b9b381c7b76ca9b852adf7e8905da0e0ad49986a0a6871815`
+- **Before**: `0x0000000000000000000000002634BD65ba27AB63811c74A63118ACb312701Bfa`
+- **After**: `0x0000000000000000000000000000000000000000000000000000000000000000`
+- **Meaning**: Slot at keccak(systemconfig.l2outputoracle)-1 deleted
+
+### `0x1a0ad011913A150f69f6A19DF447A0CfD9551054` (`OptimismPortalProxy` on Mode Sepolia)
path: tasks/sep/mode-002-fp-upgrade/VALIDATION.md
user: login: ajsutton
body: This address is Zora not mode. :)
created_at: 2025-05-29T05:27:14Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,30 @@
+ETH_RPC_URL="https://ethereum-sepolia.publicnode.com"
+
+OWNER_SAFE=0x1Eb2fFc903729a0F03966B917003800b145F56E2
+COUNCIL_SAFE=0xf64bc17485f0B4Ea5F06A96514182FC4cB561977
+FOUNDATION_SAFE=0xDEe57160aAfCF04c34C887B5962D0a69676d3C8B
+LIVENESS_GUARD=0xc26977310bC89DAee5823C2e2a73195E85382cC7
+
+# No SAFE_NONCE_* values are specified, we just use the current nonces
+# SAFE_NONCE_0X1EB2FFC903729A0F03966B917003800B145F56E2=
+# SAFE_NONCE_0XF64BC17485F0B4EA5F06A96514182FC4CB561977=
+# SAFE_NONCE_0XDEE57160AAFCF04C34C887B5962D0A69676D3C8B=
+
+# Expected prestate is cannon32 1.6.0-rc.2
+EXPECTED_PRESTATE=0x03513e996556589f633fe1d38d694f63bc93cca5df559af37631b30875a829e9
+
+# Expected Guardian address is the STANDARD config role Sepolia Guardian
+EXPECTED_GUARDIAN=0x7a50f00e8D05b95F98fE38d8BeE366a7324dCf7E
+
+# Contracts deployed prior to the upgrade
+EXPECTED_ANCHOR_STATE_REGISTRY_PROXY=0x5C30E13389686AE0ddF41859FbD4BD2CBE2Aaf1D
+EXPECTED_ANCHOR_STATE_REGISTRY_IMPL=0x43c0EA5cf1614a3F16b51804F3283f95d09a903f
+EXPECTED_PERMISSIONED_DISPUTE_GAME_IMPL=0xdC0c2Cb09512490B0b81292b9153415C3f092D4b
+EXPECTED_PERMISSIONED_DELAYED_WETH_PROXY=0xD92Bf98a4049097C4b2288734748dce90803E1C1
+EXPECTED_DISPUTE_GAME_FACTORY_PROXY=0x7Bb634B42373A87712Da14064deD13Db8b8b14f4
path: tasks/sep/mode-002-fp-upgrade/.env
user: login: ajsutton
body: This is an incorrect version of DisputeGameFactory.  It's version 1.0.0 not version 1.3.1.
created_at: 2025-05-29T05:31:14Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,30 @@
+ETH_RPC_URL="https://ethereum-sepolia.publicnode.com"
+
+OWNER_SAFE=0x1Eb2fFc903729a0F03966B917003800b145F56E2
+COUNCIL_SAFE=0xf64bc17485f0B4Ea5F06A96514182FC4cB561977
+FOUNDATION_SAFE=0xDEe57160aAfCF04c34C887B5962D0a69676d3C8B
+LIVENESS_GUARD=0xc26977310bC89DAee5823C2e2a73195E85382cC7
+
+# No SAFE_NONCE_* values are specified, we just use the current nonces
+# SAFE_NONCE_0X1EB2FFC903729A0F03966B917003800B145F56E2=
+# SAFE_NONCE_0XF64BC17485F0B4EA5F06A96514182FC4CB561977=
+# SAFE_NONCE_0XDEE57160AAFCF04C34C887B5962D0A69676D3C8B=
+
+# Expected prestate is cannon32 1.6.0-rc.2
+EXPECTED_PRESTATE=0x03513e996556589f633fe1d38d694f63bc93cca5df559af37631b30875a829e9
+
+# Expected Guardian address is the STANDARD config role Sepolia Guardian
+EXPECTED_GUARDIAN=0x7a50f00e8D05b95F98fE38d8BeE366a7324dCf7E
+
+# Contracts deployed prior to the upgrade
+EXPECTED_ANCHOR_STATE_REGISTRY_PROXY=0x5C30E13389686AE0ddF41859FbD4BD2CBE2Aaf1D
+EXPECTED_ANCHOR_STATE_REGISTRY_IMPL=0x43c0EA5cf1614a3F16b51804F3283f95d09a903f
+EXPECTED_PERMISSIONED_DISPUTE_GAME_IMPL=0xdC0c2Cb09512490B0b81292b9153415C3f092D4b
+EXPECTED_PERMISSIONED_DELAYED_WETH_PROXY=0xD92Bf98a4049097C4b2288734748dce90803E1C1
+EXPECTED_DISPUTE_GAME_FACTORY_PROXY=0x7Bb634B42373A87712Da14064deD13Db8b8b14f4
path: tasks/sep/mode-002-fp-upgrade/.env
user: login: ajsutton
body: Ignore me. DisputeGameFactory should be version 1.0.0 at this point. I should have grabbed the permissioned game implementation address for my comparisons so no wonder the script didn't run properly. Sorry.
created_at: 2025-05-29T05:38:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,30 @@
+ETH_RPC_URL="https://ethereum-sepolia.publicnode.com"
+
+OWNER_SAFE=0x1Eb2fFc903729a0F03966B917003800b145F56E2
+COUNCIL_SAFE=0xf64bc17485f0B4Ea5F06A96514182FC4cB561977
+FOUNDATION_SAFE=0xDEe57160aAfCF04c34C887B5962D0a69676d3C8B
+LIVENESS_GUARD=0xc26977310bC89DAee5823C2e2a73195E85382cC7
+
+# No SAFE_NONCE_* values are specified, we just use the current nonces
+# SAFE_NONCE_0X1EB2FFC903729A0F03966B917003800B145F56E2=
+# SAFE_NONCE_0XF64BC17485F0B4EA5F06A96514182FC4CB561977=
+# SAFE_NONCE_0XDEE57160AAFCF04C34C887B5962D0A69676D3C8B=
+
+# Expected prestate is cannon32 1.6.0-rc.2
+EXPECTED_PRESTATE=0x03513e996556589f633fe1d38d694f63bc93cca5df559af37631b30875a829e9
+
+# Expected Guardian address is the STANDARD config role Sepolia Guardian
+EXPECTED_GUARDIAN=0x7a50f00e8D05b95F98fE38d8BeE366a7324dCf7E
+
+# Contracts deployed prior to the upgrade
+EXPECTED_ANCHOR_STATE_REGISTRY_PROXY=0x5C30E13389686AE0ddF41859FbD4BD2CBE2Aaf1D
+EXPECTED_ANCHOR_STATE_REGISTRY_IMPL=0x43c0EA5cf1614a3F16b51804F3283f95d09a903f
+EXPECTED_PERMISSIONED_DISPUTE_GAME_IMPL=0xdC0c2Cb09512490B0b81292b9153415C3f092D4b
path: tasks/sep/mode-002-fp-upgrade/.env
user: login: ajsutton
body: The challenger set for this contract is not the one for mode in the superchain-registry (it's the op-sepolia one).  Not an issue if that's a deliberate change but worth confirming.
created_at: 2025-05-29T05:41:03Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,30 @@
+ETH_RPC_URL="https://ethereum-sepolia.publicnode.com"
+
+OWNER_SAFE=0x1Eb2fFc903729a0F03966B917003800b145F56E2
+COUNCIL_SAFE=0xf64bc17485f0B4Ea5F06A96514182FC4cB561977
+FOUNDATION_SAFE=0xDEe57160aAfCF04c34C887B5962D0a69676d3C8B
+LIVENESS_GUARD=0xc26977310bC89DAee5823C2e2a73195E85382cC7
+
+# No SAFE_NONCE_* values are specified, we just use the current nonces
+# SAFE_NONCE_0X1EB2FFC903729A0F03966B917003800B145F56E2=
+# SAFE_NONCE_0XF64BC17485F0B4EA5F06A96514182FC4CB561977=
+# SAFE_NONCE_0XDEE57160AAFCF04C34C887B5962D0A69676D3C8B=
+
+# Expected prestate is cannon32 1.6.0-rc.2
+EXPECTED_PRESTATE=0x03513e996556589f633fe1d38d694f63bc93cca5df559af37631b30875a829e9
+
+# Expected Guardian address is the STANDARD config role Sepolia Guardian
+EXPECTED_GUARDIAN=0x7a50f00e8D05b95F98fE38d8BeE366a7324dCf7E
+
+# Contracts deployed prior to the upgrade
+EXPECTED_ANCHOR_STATE_REGISTRY_PROXY=0x5C30E13389686AE0ddF41859FbD4BD2CBE2Aaf1D
+EXPECTED_ANCHOR_STATE_REGISTRY_IMPL=0x43c0EA5cf1614a3F16b51804F3283f95d09a903f
+EXPECTED_PERMISSIONED_DISPUTE_GAME_IMPL=0xdC0c2Cb09512490B0b81292b9153415C3f092D4b
path: tasks/sep/mode-002-fp-upgrade/.env
user: login: Wazabie
body: Yes @ajsutton that is deliberate, we updated Metal, Mode and Zora challengers to be [the Standard Config Roles one](https://github.com/ethereum-optimism/superchain-registry/blob/b39a7c2dbb07a2d019bd2350ac52cb2c53e552e7/validation/standard/standard-config-roles-sepolia.toml#L2)
created_at: 2025-05-29T15:02:05Z
author_association: CONTRIBUTOR

PR comments:
user: login: Wazabie
created_at: 2025-05-09T12:32:30Z
body: **Task is Ready for Review**

**Note to Reviewer:** Please ensure to **thoroughly check the Predeploys addresses** in VALIDATION.md for correctness and consistency. Let me know if anything needs clarification.
author_association: CONTRIBUTOR
user: login: Wazabie
created_at: 2025-05-29T15:35:06Z
body: > This generally looks pretty sane but the predeployed DisputeGameFactory is using version 1.0.0 instead of 1.3.1. There may be other issues with the deployed contracts but the different version makes it hard to compare against expected configs.

Is this still applicable? Reading your following comment, I think DGF is correct to be 1.0.0 with this task?
author_association: CONTRIBUTOR