Skip to content

Commit

Permalink
Merge branch 'main' into bm/simulate-in-ci
Browse files Browse the repository at this point in the history
  • Loading branch information
blmalone authored Dec 20, 2024
2 parents a5aacf5 + 14fd094 commit e11035d
Show file tree
Hide file tree
Showing 12 changed files with 511 additions and 1 deletion.
36 changes: 35 additions & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,23 @@ parameters:
default: 5

commands:
simulate:
description: "Runs simulations of a task"
parameters:
task:
type: string
steps:
- checkout
- run:
name: "simulate << parameters.task >>"
command: |
just install
cd tasks/<< parameters.task >>
SIMULATE_WITHOUT_LEDGER=true just \
--dotenv-path $(pwd)/.env \
--justfile ../../../single.just \
simulate
simulate_nested:
description: "Runs simulations of a nested task"
parameters:
Expand All @@ -42,6 +59,7 @@ commands:
--justfile ../../../nested.just \
simulate council
jobs:
check_sepolia_rpc_endpoints:
circleci_ip_ranges: true
Expand Down Expand Up @@ -207,6 +225,13 @@ jobs:
just simulate-council
just prepare-json
just simulate-council # simulate again to make sure the json is still valid
simulate_eth_021:
docker:
- image: << pipeline.parameters.ci_builder_image >>
steps:
- simulate:
task: "eth/021-holocene-protocol-versions"

forge_build:
docker:
Expand Down Expand Up @@ -253,7 +278,14 @@ jobs:
just --version
yq --version
forge --version
simulate_eth_022:
docker:
- image: << pipeline.parameters.ci_builder_image >>
steps:
- simulate_nested:
task: "eth/022-holocene-fp-upgrade"

workflows:
main:
jobs:
Expand Down Expand Up @@ -286,3 +318,5 @@ workflows:
# exist in the task list and simulates them to ensure that
# they are still valid.
- simulate_non_terminal_tasks
- simulate_eth_021
- simulate_eth_022
67 changes: 67 additions & 0 deletions script/verification/ProtocolVersionsBump.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;

import {console2 as console} from "forge-std/console2.sol";
import {VerificationBase, SuperchainRegistry} from "script/verification/Verification.s.sol";
import {ProtocolVersions, ProtocolVersion} from "@eth-optimism-bedrock/src/L1/ProtocolVersions.sol";
import {LibString} from "solady/utils/LibString.sol";

abstract contract ProtocolVersionsBump is VerificationBase, SuperchainRegistry {
struct ProtoVer {
uint32 major;
uint32 minor;
uint32 patch;
uint32 preRelease;
}

uint256 immutable reccomended;
uint256 immutable required;

address owner;

constructor(address _owner, ProtoVer memory _recommended, ProtoVer memory _required) {
owner = _owner;
console.log("Current owner is:", owner);
reccomended = encodeProtocolVersion(_recommended);
required = encodeProtocolVersion(_required);
console.log(
"Will validate ProtocolVersions bump to (reccommended,required): ",
stringifyProtoVer(_recommended),
stringifyProtoVer(_required)
);
console.log(
"Encoded versions are (reccommended,required): ",
LibString.toHexString(reccomended, 32),
LibString.toHexString(required, 32)
);
addAllowedStorageAccess(proxies.ProtocolVersions);
addAllowedStorageAccess(owner);
}

function stringifyProtoVer(ProtoVer memory pv) internal pure returns (string memory) {
return string(
abi.encodePacked(
LibString.toString(pv.major),
".",
LibString.toString(pv.minor),
".",
LibString.toString(pv.patch),
"-",
LibString.toString(pv.preRelease)
)
);
}

function encodeProtocolVersion(ProtoVer memory pv) internal pure returns (uint256) {
return
(uint256(pv.major) << 96) | (uint256(pv.minor) << 64) | (uint256(pv.patch) << 32) | (uint256(pv.preRelease));
}

function checkProtocolVersions() public view {
console.log("Checking ProtocolVersions at ", proxies.ProtocolVersions);
ProtocolVersions pv = ProtocolVersions(proxies.ProtocolVersions);
require(pv.owner() == owner, "PV.owner not expected");
require(ProtocolVersion.unwrap(pv.required()) == required, "Required PV not set correctly");
require(ProtocolVersion.unwrap(pv.recommended()) == reccomended, "Recommended PV not set correctly");
}
}
3 changes: 3 additions & 0 deletions tasks/eth/021-holocene-protocol-versions/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
ETH_RPC_URL="https://ethereum.publicnode.com"
OWNER_SAFE=0x847B5c174615B1B7fDF770882256e2D3E95b9D92
SAFE_NONCE=10
42 changes: 42 additions & 0 deletions tasks/eth/021-holocene-protocol-versions/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Mainnet Required & Recommended Protocol Version Update (9.0.0 - Holocene)
Status: READY TO SIGN

## Objective

This is the playbook to update the required and recommended protocol versions of the `ProtocolVersions` contract on Ethereum mainnet to 9.0.0 (Holocene). It is currently set to 8.0.0 (Granite).

This transaction should be sent on **Jan 7th, 2025**, so 2 days before the [Holocene mainnet activation](https://github.com/ethereum-optimism/superchain-registry/blob/17f539928389cdd88bcae48e6e24c07337ce3f4f/superchain/configs/mainnet/superchain.toml#L11).

The Holocene proposal was:

- [x] Posted on the governance forum [here](https://gov.optimism.io/t/upgrade-proposal-11-holocene-network-upgrade/9313).
- [x] Approved by Token House voting [here](https://vote.optimism.io/proposals/20127877429053636874064552098716749508236019236440427814457915785398876262515).
- [ ] Not vetoed by the Citizens' house
- [ ] Executed on OP Mainnet.

The [governance proposal](https://gov.optimism.io/t/upgrade-proposal-11-holocene-network-upgrade/9313) should be treated as the source of truth and used to verify the correctness of the onchain operations.

## Deployments

* Mainnet: [`0x8062AbC286f5e7D9428a0Ccb9AbD71e50d93b935`](https://github.com/ethereum-optimism/superchain-registry/blob/17f539928389cdd88bcae48e6e24c07337ce3f4f/superchain/configs/mainnet/superchain.toml#L2)

## 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/eth/021-holocene-protocol-versions/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.

Do NOT yet proceed to the "Execution" section.

## 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 [SINGLE.md](../../../SINGLE.md).

When executing, ensure the logs say `Using script /your/path/to/superchain-ops/tasks/eth/021-holocene-protocol-versions/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.
38 changes: 38 additions & 0 deletions tasks/eth/021-holocene-protocol-versions/SignFromJson.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;

import {SignFromJson as OriginalSignFromJson} from "script/SignFromJson.s.sol";
import {ProtocolVersionsBump} from "script/verification/ProtocolVersionsBump.s.sol";
import {SuperchainRegistry} from "script/verification/Verification.s.sol";
import {console2 as console} from "forge-std/console2.sol";
import {Vm} from "forge-std/Vm.sol";
import {Simulation} from "@base-contracts/script/universal/Simulation.sol";

contract SignFromJson is OriginalSignFromJson, ProtocolVersionsBump {
constructor()
ProtocolVersionsBump(vm.envAddress("OWNER_SAFE"), ProtoVer(9, 0, 0, 0), ProtoVer(9, 0, 0, 0))
// In the next line, "op" and ""v1.8.0-rc.4" are not relevant.
// This is because we only need to read superchain-wide information from the registry.
// We can use any valid values here.
SuperchainRegistry("mainnet", "op", "v1.8.0-rc.4")
{}

/// @notice Checks the correctness of the deployment
function _postCheck(Vm.AccountAccess[] memory accesses, Simulation.Payload memory /* simPayload */ )
internal
view
override
{
console.log("Running assertions");
checkStateDiff(accesses);
checkProtocolVersions();
console.log("All assertions passed!");
}

function getAllowedStorageAccess() internal view override returns (address[] memory) {
return allowedStorageAccess;
}

// No need to override getCodeExceptions() because we do not expect to ever trigger it.
// We are writing a value which is very unlikely to be interpreted as an address.
}
54 changes: 54 additions & 0 deletions tasks/eth/021-holocene-protocol-versions/VALIDATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Validation

This document can be used to validate the state diff resulting from the execution of setting the recommended protocol version.

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 key values match the semantic meaning provided, which can be validated using the storage layout links provided.

## State Overrides

The following state overrides should be seen:

### `0x847B5c174615B1B7fDF770882256e2D3E95b9D92` (Foundation Upgrade Safe)

The [Foundation Upgrade Safe](https://etherscan.io/address/0x847B5c174615B1B7fDF770882256e2D3E95b9D92) is attested to in the [Optimism docs](https://docs.optimism.io/chain/security/privileged-roles#system-config-owner) as the current owner of the `SystemConfig`.
The `ProtocolVersions` owner is not mentioned in the docs, but is the same.

To allow simulating the transaction bundle of setting the required versions in a single Tenderly tx, the threshold is overridden to 1.

- **Key:** `0x0000000000000000000000000000000000000000000000000000000000000004` <br/>
**Value:** `0x0000000000000000000000000000000000000000000000000000000000000001` <br/>
**Meaning:** The threshold is set 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

More background on `ProtocolVersions` state validation can be found
[here](../../common/protocol-versions.md), including a description of expected event emissions.

### `0x8062AbC286f5e7D9428a0Ccb9AbD71e50d93b935` (`ProtocolVersions`)

- **Key:** `0x4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace0` <br/>
**Before:** `0x0000000000000000000000000000000000000008000000000000000000000000` <br/>
**After:** `0x0000000000000000000000000000000000000009000000000000000000000000` <br/>
**Meaning:** This bumps the major version of the *required protocol version* from 8.0.0 to 9.0.0.
The key is derived from `keccak256('protocolversion.required')-1`. See [../../common/protocol-versions.md](../../common/protocol-versions.md) for more information.

- **Key:** `0xe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1a` <br/>
**Before:** `0x0000000000000000000000000000000000000008000000000000000000000000` <br/>
**After:** `0x0000000000000000000000000000000000000009000000000000000000000000` <br/>
**Meaning:** This bumps the major version of the *recommended protocol version* from 8.0.0 to 9.0.0.
The key is derived from `keccak256('protocolversion.recommended')-1`. See [../../common/protocol-versions.md](../../common/protocol-versions.md) for more information.


### Nonce increments

The only other state changes are two nonce increments:

**Key**: 0x0000000000000000000000000000000000000000000000000000000000000005
**Before**: 0x000000000000000000000000000000000000000000000000000000000000000a
**After**: 0x000000000000000000000000000000000000000000000000000000000000000b
**Meaning**: Increment the nonce of the Foundation Upgrade Safe from 10 (0xa) to 11 (0xb).
- One on the owner on the account that sent the transaction.

27 changes: 27 additions & 0 deletions tasks/eth/021-holocene-protocol-versions/input.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"chainId": 1,
"metadata": {
"name": "Set ProtocolVersions to 9.0.0 (Holocene)",
"description": ""
},
"transactions": [
{
"metadata": {
"name": "Update the recommended ProtocolVersions to 9.0.0 (Holocene)",
"description": "calls setRecommended"
},
"to": "0x8062AbC286f5e7D9428a0Ccb9AbD71e50d93b935",
"value": "0x0",
"data": "0x5fd579af0000000000000000000000000000000000000009000000000000000000000000"
},
{
"metadata": {
"name": "Update the required ProtocolVersions to 9.0.0 (Holocene)",
"description": "calls setRequired"
},
"to": "0x8062AbC286f5e7D9428a0Ccb9AbD71e50d93b935",
"value": "0x0",
"data": "0x0457d6f20000000000000000000000000000000000000009000000000000000000000000"
}
]
}
10 changes: 10 additions & 0 deletions tasks/eth/022-holocene-fp-upgrade/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
ETH_RPC_URL="https://ethereum.publicnode.com"
OWNER_SAFE=0x5a0Aae59D09fccBdDb6C6CcEB07B7279367C3d2A
COUNCIL_SAFE=0xc2819DC788505Aac350142A7A707BF9D03E3Bd03
FOUNDATION_SAFE=0x847B5c174615B1B7fDF770882256e2D3E95b9D92

SAFE_NONCE=6 # noop
SAFE_NONCE_0XC2819DC788505AAC350142A7A707BF9D03E3BD03=8 # noop
SAFE_NONCE_0X847B5C174615B1B7FDF770882256E2D3E95B9D92=11 # +1, task 021

SIMULATE_WITHOUT_LEDGER=0 # 1
57 changes: 57 additions & 0 deletions tasks/eth/022-holocene-fp-upgrade/NestedSignFromJson.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;

import {console2 as console} from "forge-std/console2.sol";
import {Vm} from "forge-std/Vm.sol";
import {stdJson} from "forge-std/StdJson.sol";
import {Simulation} from "@base-contracts/script/universal/Simulation.sol";
import {NestedSignFromJson as OriginalNestedSignFromJson} from "script/NestedSignFromJson.s.sol";
import {DisputeGameUpgrade} from "script/verification/DisputeGameUpgrade.s.sol";
import {CouncilFoundationNestedSign} from "script/verification/CouncilFoundationNestedSign.s.sol";
import {SuperchainRegistry} from "script/verification/Verification.s.sol";

contract NestedSignFromJson is OriginalNestedSignFromJson, CouncilFoundationNestedSign, DisputeGameUpgrade {
constructor()
SuperchainRegistry("mainnet", "op", "v1.8.0-rc.4")
DisputeGameUpgrade(
0x03f89406817db1ed7fd8b31e13300444652cdb0b9c509a674de43483b2f83568, // absolutePrestate
0x27B81db41F586016694632193b99E45b1a27B8f8, // faultDisputeGame
0x91a661891248d8C4916FB4a1508492a5e2CBcb87 // permissionedDisputeGame
)
{}

function setUp() public view {
checkInput();
}

function checkInput() public view {
string memory inputJson;
string memory path = "/tasks/eth/022-holocene-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));
}

address inputPermissionedDisputeGame =
stdJson.readAddress(inputJson, "$.transactions[0].contractInputsValues._impl");
address inputFaultDisputeGame = stdJson.readAddress(inputJson, "$.transactions[1].contractInputsValues._impl");
require(expPermissionedDisputeGame == inputPermissionedDisputeGame, "input-pdg");
require(expFaultDisputeGame == inputFaultDisputeGame, "input-fdg");
}

function _postCheck(Vm.AccountAccess[] memory accesses, Simulation.Payload memory) internal view override {
console.log("Running post-deploy assertions");
checkStateDiff(accesses);
checkDisputeGameUpgrade();
console.log("All assertions passed!");
}

function getAllowedStorageAccess() internal view override returns (address[] memory) {
return allowedStorageAccess;
}

function getCodeExceptions() internal view override returns (address[] memory) {
return codeExceptions;
}
}
Loading

0 comments on commit e11035d

Please sign in to comment.