-
Notifications
You must be signed in to change notification settings - Fork 45
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Base Sepolia Holocene FP Upgrade Task (#376)
* Add Base Sepolia holocene fp upgrade task * Updated status and made changes to the md files
- Loading branch information
1 parent
1fd8d7b
commit 5a499c6
Showing
6 changed files
with
349 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
ETH_RPC_URL="https://ethereum-sepolia.publicnode.com" | ||
OWNER_SAFE=0x0fe884546476dDd290eC46318785046ef68a0BA9 | ||
SAFE_NONCE="" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# Holocene Hardfork - Proof Contract Upgrades | ||
Upgrades the `MIPS.sol`, `FaultDisputeGame.sol`, and `PermissionedDisputeGame.sol` contracts for Holocene. | ||
|
||
The batch will be executed on chain ID `11155111`, and contains `2` transactions. | ||
|
||
## Tx #1: Upgrade `PERMISSIONED_CANNON` game type in `DisputeGameFactory` | ||
Upgrades the `PERMISSIONED_CANNON` game type to the new Holocene deployment, with an updated version of `op-program` as the absolute prestate hash, an updated MIPS VM, and an updated version. | ||
|
||
**Function Signature:** `setImplementation(uint32,address)` | ||
|
||
**To:** `0xd6E6dBf4F7EA0ac412fD8b65ED297e64BB7a06E1` | ||
|
||
**Value:** `0 WEI` | ||
|
||
**Raw Input Data:** `0x14f6b1a3000000000000000000000000000000000000000000000000000000000000000100000000000000000000000068f600e592799c16d1b096616edbf1681fb9c0de` | ||
|
||
### Inputs | ||
**_impl:** `0x68f600e592799c16d1b096616edbf1681fb9c0de` | ||
|
||
**_gameType:** `1` | ||
|
||
|
||
## Tx #2: Upgrade `CANNON` game type in `DisputeGameFactory` | ||
Upgrades the `CANNON` game type to the new Holocene deployment, with an updated version of `op-program` as the absolute prestate hash, an updated MIPS VM, and an updated version. | ||
|
||
**Function Signature:** `setImplementation(uint32,address)` | ||
|
||
**To:** `0xd6E6dBf4F7EA0ac412fD8b65ED297e64BB7a06E1` | ||
|
||
**Value:** `0 WEI` | ||
|
||
**Raw Input Data:** `0x14f6b1a30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b7fb44a61fde2b9db28a84366e168b14d1a1b103` | ||
|
||
### Inputs | ||
**_gameType:** `0` | ||
|
||
**_impl:** `0xb7fb44a61fde2b9db28a84366e168b14d1a1b103` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# Holocene Hardfork Upgrade - Base Sepolia | ||
|
||
Status: [EXECUTED](https://sepolia.etherscan.io/tx/0x3ab5ff5700afe57b89d7d23c0ad9e535f38a68b55c571e66c642719d85bcb888) | ||
|
||
## Objective | ||
|
||
Upgrades the Fault Proof contracts of Base Sepolia for the Holocene hardfork. | ||
|
||
This upgrades the Fault Proof contracts in the | ||
[op-contracts/v1.8.0-rc.2](https://github.com/ethereum-optimism/optimism/tree/op-contracts/v1.8.0-rc.2) release. | ||
|
||
## Pre-deployments | ||
|
||
- `MIPS` - `0x69470D6970Cd2A006b84B1d4d70179c892cFCE01` | ||
- `FaultDisputeGame` - `0xB7fB44a61fdE2b9DB28a84366e168b14D1a1b103` | ||
- `PermissionedDisputeGame` - `0x68f600e592799c16D1b096616eDbf1681FB9c0De` | ||
|
||
## Simulation | ||
|
||
Please see the "Simulating and Verifying the Transaction" instructions in [SINGLE.md](../../../SINGLE.md). | ||
When simulating, ensure the logs say `Using script /your/path/to/superchain-ops/tasks/sep/base-005-fp-holocene-upgrade/SignFromJson.s.sol`. | ||
This ensures all safety checks are run. If the default `SignFromJson.s.sol` script is shown (without the full path), something is wrong and the safety checks will not run. | ||
|
||
## State Validation | ||
|
||
Please see the instructions for [validation](./VALIDATION.md). | ||
|
||
## Execution | ||
|
||
This upgrade | ||
* Changes dispute game implementation of the `CANNON` and `PERMISSIONED_CANNON` game types to contain a `op-program` release for the Holocene hardfork, which contains | ||
the Holocene fork implementation as well as a `ChainConfig` and `RollupConfig` for the L2 chain being upgraded. | ||
* Upgrades `MIPS.sol` to support the `F_GETFD` syscall, required by the golang 1.22+ runtime. | ||
|
||
See the [overview](./OVERVIEW.md) and `input.json` bundle for more details. |
161 changes: 161 additions & 0 deletions
161
tasks/sep/base-005-fp-holocene-upgrade/SignFromJson.s.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.15; | ||
|
||
import {SignFromJson as OriginalSignFromJson} from "script/SignFromJson.s.sol"; | ||
import {Simulation} from "@base-contracts/script/universal/Simulation.sol"; | ||
import {console2 as console} from "forge-std/console2.sol"; | ||
import {stdJson} from "forge-std/StdJson.sol"; | ||
import {Vm, VmSafe} from "forge-std/Vm.sol"; | ||
import {GnosisSafe} from "safe-contracts/GnosisSafe.sol"; | ||
import {LibString} from "solady/utils/LibString.sol"; | ||
import "@eth-optimism-bedrock/src/dispute/lib/Types.sol"; | ||
import {DisputeGameFactory} from "@eth-optimism-bedrock/src/dispute/DisputeGameFactory.sol"; | ||
import {FaultDisputeGame} from "@eth-optimism-bedrock/src/dispute/FaultDisputeGame.sol"; | ||
import {PermissionedDisputeGame} from "@eth-optimism-bedrock/src/dispute/PermissionedDisputeGame.sol"; | ||
import {MIPS} from "@eth-optimism-bedrock/src/cannon/MIPS.sol"; | ||
import {ISemver} from "@eth-optimism-bedrock/src/universal/ISemver.sol"; | ||
|
||
contract SignFromJson is OriginalSignFromJson { | ||
using LibString for string; | ||
|
||
// Safe contract for this task. | ||
GnosisSafe ownerSafe = GnosisSafe(payable(vm.envAddress("OWNER_SAFE"))); | ||
|
||
// Current dispute game implementations | ||
FaultDisputeGame currentFDG; | ||
PermissionedDisputeGame currentPDG; | ||
|
||
// New dispute game implementations | ||
FaultDisputeGame newFDG; | ||
PermissionedDisputeGame newPDG; | ||
|
||
// https://github.com/ethereum-optimism/superchain-registry/blob/main/superchain/configs/sepolia/base.toml#L56 | ||
DisputeGameFactory constant dgfProxy = DisputeGameFactory(0xd6E6dBf4F7EA0ac412fD8b65ED297e64BB7a06E1); | ||
|
||
// Other expected values | ||
bytes32 constant absolutePrestate = 0x03925193e3e89f87835bbdf3a813f60b2aa818a36bbe71cd5d8fd7e79f5e8afe; | ||
address constant newMips = 0x69470D6970Cd2A006b84B1d4d70179c892cFCE01; | ||
// https://docs.base.org/docs/base-contracts/#ethereum-testnet-sepolia | ||
address constant oracle = 0x92240135b46fc1142dA181f550aE8f595B858854; | ||
string constant gameVersion = "1.3.1"; | ||
uint256 constant chainId = 84532; | ||
|
||
function setUp() public { | ||
// Get the current dispute game implementations | ||
currentFDG = FaultDisputeGame( | ||
address(dgfProxy.gameImpls(GameTypes.CANNON)) | ||
); | ||
currentPDG = PermissionedDisputeGame( | ||
address(dgfProxy.gameImpls(GameTypes.PERMISSIONED_CANNON)) | ||
); | ||
|
||
// Get the new dispute game implementations, parsed from the input.json | ||
string memory inputJson; | ||
string memory path = "/tasks/sep/base-005-fp-holocene-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)); | ||
} | ||
|
||
newPDG = PermissionedDisputeGame(stdJson.readAddress(inputJson, "$.transactions[0].contractInputsValues._impl")); | ||
newFDG = FaultDisputeGame(stdJson.readAddress(inputJson, "$.transactions[1].contractInputsValues._impl")); | ||
|
||
// Check the correctness of the new dispute games with the current ones | ||
_precheckDisputeGameImplementation(); | ||
} | ||
|
||
function _precheckDisputeGameImplementation() internal view { | ||
console.log("pre-check new game implementations"); | ||
|
||
// check the current and new fault dispute game implementations | ||
require(address(currentFDG.anchorStateRegistry()) == address(newFDG.anchorStateRegistry()), "precheck-100"); | ||
require(currentFDG.l2ChainId() == newFDG.l2ChainId(), "precheck-101"); | ||
require(currentFDG.splitDepth() == newFDG.splitDepth(), "precheck-102"); | ||
require(currentFDG.maxGameDepth() == newFDG.maxGameDepth(), "precheck-103"); | ||
require( | ||
uint64(Duration.unwrap(currentFDG.maxClockDuration())) == | ||
uint64(Duration.unwrap(newFDG.maxClockDuration())), | ||
"precheck-104" | ||
); | ||
require( | ||
uint64(Duration.unwrap(currentFDG.clockExtension())) == | ||
uint64(Duration.unwrap(newFDG.clockExtension())), | ||
"precheck-105" | ||
); | ||
|
||
// check the current and new permissioned dispute game implementations | ||
require(address(currentPDG.anchorStateRegistry()) == address(newPDG.anchorStateRegistry()), "precheck-200"); | ||
require(currentPDG.l2ChainId() == newPDG.l2ChainId(), "precheck-201"); | ||
require(currentPDG.splitDepth() == newPDG.splitDepth(), "precheck-202"); | ||
require(currentPDG.maxGameDepth() == newPDG.maxGameDepth(), "precheck-203"); | ||
require( | ||
uint64(Duration.unwrap(currentPDG.maxClockDuration())) == | ||
uint64(Duration.unwrap(newPDG.maxClockDuration())), | ||
"precheck-204" | ||
); | ||
require( | ||
uint64(Duration.unwrap(currentPDG.clockExtension())) == | ||
uint64(Duration.unwrap(newPDG.clockExtension())), | ||
"precheck-205" | ||
); | ||
require(address(currentPDG.proposer()) == address(newPDG.proposer()), "precheck-206"); | ||
require(address(currentPDG.challenger()) == address(newPDG.challenger()), "precheck-207"); | ||
} | ||
|
||
function getAllowedStorageAccess() | ||
internal | ||
view | ||
override | ||
returns (address[] memory allowed) | ||
{ | ||
allowed = new address[](2); | ||
allowed[0] = address(dgfProxy); | ||
allowed[1] = address(ownerSafe); | ||
} | ||
|
||
function getCodeExceptions() internal view override returns (address[] memory exceptions) { | ||
// No exceptions are expected in this task, but it must be implemented. | ||
} | ||
|
||
/// @notice Checks the correctness of the deployment | ||
function _postCheck( | ||
Vm.AccountAccess[] memory accesses, | ||
Simulation.Payload memory /* simPayload */ | ||
) internal view override { | ||
console.log("Running post-deploy assertions"); | ||
|
||
checkStateDiff(accesses); | ||
checkDGFProxyAndGames(); | ||
checkMips(); | ||
|
||
console.log("All assertions passed!"); | ||
} | ||
|
||
function checkDGFProxyAndGames() internal view { | ||
console.log("check dispute game implementations"); | ||
|
||
require(address(newFDG) == address(dgfProxy.gameImpls(GameTypes.CANNON)), "dgf-100"); | ||
require(address(newPDG) == address(dgfProxy.gameImpls(GameTypes.PERMISSIONED_CANNON)), "dgf-200"); | ||
|
||
require(newFDG.version().eq(gameVersion), "game-100"); | ||
require(newPDG.version().eq(gameVersion), "game-200"); | ||
|
||
require(newFDG.absolutePrestate().raw() == absolutePrestate, "game-300"); | ||
require(newPDG.absolutePrestate().raw() == absolutePrestate, "game-400"); | ||
|
||
require(address(newFDG.vm()) == newMips, "game-500"); | ||
require(address(newPDG.vm()) == newMips, "game-600"); | ||
|
||
require(newFDG.l2ChainId() == chainId, "game-700"); | ||
require(newPDG.l2ChainId() == chainId, "game-800"); | ||
} | ||
|
||
function checkMips() internal view{ | ||
console.log("check MIPS"); | ||
|
||
require(newMips.code.length != 0, "MIPS-100"); | ||
vm.assertEq(ISemver(newMips).version(), "1.2.1"); | ||
require(address(MIPS(newMips).oracle()) == oracle, "MIPS-200"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
# 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. | ||
|
||
## State Overrides | ||
|
||
The following state override should be seen: | ||
|
||
### `0x0fe884546476dDd290eC46318785046ef68a0BA9` (Gnosis Safe `ProxyAdmin` owner) | ||
|
||
Links: | ||
- [Sepolia Etherscan](https://sepolia.etherscan.io/address/0x0fe884546476ddd290ec46318785046ef68a0ba9) | ||
|
||
Overrides: | ||
- **Key:** `0x0000000000000000000000000000000000000000000000000000000000000004` <br/> | ||
**Value:** `0x0000000000000000000000000000000000000000000000000000000000000001` <br/> | ||
**Meaning:** Enables the simulation by setting the signature threshold to 1. The key can be validated by the location of the `threshold` variable in | ||
the [Safe's Storage Layout](https://github.com/safe-global/safe-smart-account/blob/v1.3.0/contracts/examples/libraries/GnosisSafeStorage.sol#L14) | ||
|
||
## State Changes | ||
|
||
### `0x0fe884546476dDd290eC46318785046ef68a0BA9` (Gnosis Safe `ProxyAdmin` owner) | ||
|
||
- **Key**: `0x0000000000000000000000000000000000000000000000000000000000000005` <br/> | ||
**Before**: `0x0000000000000000000000000000000000000000000000000000000000000009` <br/> | ||
**After**: `0x000000000000000000000000000000000000000000000000000000000000000a` <br/> | ||
**Meaning**: The nonce in slot `0x05` of the L1 Gnosis Safe `ProxyAdmin` owner is incremented from 9 to 10. | ||
|
||
### `0xd6E6dBf4F7EA0ac412fD8b65ED297e64BB7a06E1` (`DisputeGameFactoryProxy`) | ||
|
||
- **Key**: `0xffdfc1249c027f9191656349feb0761381bb32c9f557e01f419fd08754bf5a1b` <br/> | ||
**Before**: `0x0000000000000000000000005062792ed6a85cf72a1424a1b7f39ed0f7972a4b` <br/> | ||
**After**: `0x000000000000000000000000b7fb44a61fde2b9db28a84366e168b14d1a1b103` <br/> | ||
**Meaning**: Updates the CANNON game type implementation. Prior to this upgrade running, verify the old implementation is set using `cast call 0xd6E6dBf4F7EA0ac412fD8b65ED297e64BB7a06E1 "gameImpls(uint32)(address)" 0`. Where `0` is the [`CANNON` game type](https://github.com/ethereum-optimism/optimism/blob/op-contracts/v1.4.0/packages/contracts-bedrock/src/dispute/lib/Types.sol#L28). Once the upgrade has been executed, the same command should now return the new implementation address. | ||
|
||
- **Key**: `0x4d5a9bd2e41301728d41c8e705190becb4e74abe869f75bdb405b63716a35f9e` <br/> | ||
**Before**: `0x000000000000000000000000593d20c4c69485b95d11507239be2c725ea2a6fd` <br/> | ||
**After**: `0x00000000000000000000000068f600e592799c16d1b096616edbf1681fb9c0de` <br/> | ||
**Meaning**: Updates the PERMISSIONED_CANNON game type implementation. Prior to this upgrade running, verify the old implementation is set using `cast call 0xd6E6dBf4F7EA0ac412fD8b65ED297e64BB7a06E1 "gameImpls(uint32)(address)" 1`. Where `1` is the [`PERMISSIONED_CANNON` game type](https://github.com/ethereum-optimism/optimism/blob/op-contracts/v1.4.0/packages/contracts-bedrock/src/dispute/lib/Types.sol#L31). Once the upgrade has been executed, the same command should now return the new implementation address. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
{ | ||
"chainId": 11155111, | ||
"metadata": { | ||
"name": "Holocene Hardfork - Proof Contract Upgrades", | ||
"description": "Upgrades the `MIPS.sol`, `FaultDisputeGame.sol`, and `PermissionedDisputeGame.sol` contracts for Holocene." | ||
}, | ||
"transactions": [ | ||
{ | ||
"metadata": { | ||
"name": "Upgrade `PERMISSIONED_CANNON` game type in `DisputeGameFactory`", | ||
"description": "Upgrades the `PERMISSIONED_CANNON` game type to the new Holocene deployment, with an updated version of `op-program` as the absolute prestate hash." | ||
}, | ||
"to": "0xd6E6dBf4F7EA0ac412fD8b65ED297e64BB7a06E1", | ||
"value": "0x0", | ||
"data": "0x14f6b1a3000000000000000000000000000000000000000000000000000000000000000100000000000000000000000068f600e592799c16d1b096616edbf1681fb9c0de", | ||
"contractMethod": { | ||
"type": "function", | ||
"name": "setImplementation", | ||
"inputs": [ | ||
{ | ||
"name": "_gameType", | ||
"type": "uint32" | ||
}, | ||
{ | ||
"name": "_impl", | ||
"type": "address" | ||
} | ||
], | ||
"outputs": [], | ||
"stateMutability": "nonpayable" | ||
}, | ||
"contractInputsValues": { | ||
"_gameType": 1, | ||
"_impl": "0x68f600e592799c16d1b096616edbf1681fb9c0de" | ||
} | ||
}, | ||
{ | ||
"metadata": { | ||
"name": "Upgrade `CANNON` game type in `DisputeGameFactory`", | ||
"description": "Upgrades the `CANNON` game type to the new Holocene deployment, with an updated version of `op-program` as the absolute prestate hash." | ||
}, | ||
"to": "0xd6E6dBf4F7EA0ac412fD8b65ED297e64BB7a06E1", | ||
"value": "0x0", | ||
"data": "0x14f6b1a30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b7fb44a61fde2b9db28a84366e168b14d1a1b103", | ||
"contractMethod": { | ||
"type": "function", | ||
"name": "setImplementation", | ||
"inputs": [ | ||
{ | ||
"name": "_gameType", | ||
"type": "uint32" | ||
}, | ||
{ | ||
"name": "_impl", | ||
"type": "address" | ||
} | ||
], | ||
"outputs": [], | ||
"stateMutability": "nonpayable" | ||
}, | ||
"contractInputsValues": { | ||
"_gameType": 0, | ||
"_impl": "0xb7fb44a61fde2b9db28a84366e168b14d1a1b103" | ||
} | ||
} | ||
] | ||
} |