Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mainnet-014: Fjord gas config update #246

Merged
merged 8 commits into from
Jun 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,23 @@ jobs:
--justfile ../../../nested.just \
simulate foundation

just_simulate_eth-014-fjord-gas-config:
docker:
- image: <<pipeline.parameters.ci_builder_image>>
steps:
- checkout
- run:
name: just simulate eth/014-fjord-gas-config
command: |
go install github.com/mikefarah/yq/v4@latest
just install
cd tasks/eth/014-fjord-gas-config
export SIMULATE_WITHOUT_LEDGER=1
just \
--dotenv-path $(pwd)/.env \
--justfile ../../../single.just \
simulate

forge_fmt:
docker:
- image: <<pipeline.parameters.ci_builder_image>>
Expand Down Expand Up @@ -276,3 +293,4 @@ workflows:
- just_simulate_eth-011-1-proto-ver_ownership-transfers
- just_simulate_eth-012-proto-ver-required
- just_simulate_eth-013-fp-upgrade-fjord
- just_simulate_eth-014-fjord-gas-config
3 changes: 3 additions & 0 deletions tasks/eth/014-fjord-gas-config/.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 # Foundation Upgrades Safe
SAFE_NONCE=6
42 changes: 42 additions & 0 deletions tasks/eth/014-fjord-gas-config/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Mainnet Gas Config Update for Fjord

Status: DRAFT, NOT READY TO SIGN

## Objective

This is the playbook to update the gas scalar configuration on the `SystemConfig` contract for OP Mainnet.
Fjord uses the same configuration parameters as Ecotone, that is, the _base fee_ and _blob base fee scalars_.
Because [Fjord updates the L1 cost function to be based on a compression estimation using FastLZ](https://github.com/ethereum-optimism/specs/blob/main/specs/fjord/exec-engine.md#fees),
these scalars have to be adjusted.
Details on the transaction input can be found in the validation file, see below.

This transaction should be sent within five minutes of the successful Fjord mainnet activation on **Jul 10, 16:00:01 UTC**.

The Fjord proposal was:

- [x] Posted on the governance forum [here](https://gov.optimism.io/t/upgrade-proposal-9-fjord-network-upgrade/8236).
- [x] Approved by Token House voting [here](https://vote.optimism.io/proposals/19894803675554157870919000647998468859257602050917884642551010462863037711179).
- [ ] Not vetoed by the Citizens' house [here](https://snapshot.org/#/citizenshouse.eth/proposal/0x14336dfcb086279e47ef8fffbd6282984d392f1b9eaf22f76547210df6451c43).

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

## 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/014-fjord-gas-config/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/014-fjord-gas-config/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.
89 changes: 89 additions & 0 deletions tasks/eth/014-fjord-gas-config/SignFromJson.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;

import {SignFromJson as OriginalSignFromJson} from "script/SignFromJson.s.sol";
import {Proxy} from "@eth-optimism-bedrock/src/universal/Proxy.sol";
import {SystemConfig} from "@eth-optimism-bedrock/src/L1/SystemConfig.sol";
import {ProtocolVersions, ProtocolVersion} from "@eth-optimism-bedrock/src/L1/ProtocolVersions.sol";
import {Types} from "@eth-optimism-bedrock/scripts/Types.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 {LibString} from "solady/utils/LibString.sol";

contract SignFromJson is OriginalSignFromJson {
using LibString for string;

// Chains for this task.
string constant l1ChainName = "mainnet";
string constant l2ChainName = "op";

uint256 constant scalarFjord = 0x010000000000000000000000000000000000000000000000000f79c50000146b;

// Safe contract for this task.
address foundationUpgradesSafe = vm.envAddress("OWNER_SAFE");

// All L1 proxy addresses.
Types.ContractSet proxies;

function setUp() public {
proxies = _getContractSet();
}

function getAllowedStorageAccess() internal view override returns (address[] memory allowed) {
allowed = new address[](2);
allowed[0] = foundationUpgradesSafe;
allowed[1] = proxies.SystemConfig;
}

/// @notice Checks the correctness of the deployment
function _postCheck(Vm.AccountAccess[] memory accesses, SimulationPayload memory /* simPayload */ )
internal
view
override
{
console.log("Running assertions");

checkStateDiff(accesses);
checkSystemConfig();

console.log("All assertions passed!");
}

function getCodeExceptions() internal view override returns (address[] memory exceptions) {
// No exceptions are expected in this task, but it must be implemented.
}

function checkSystemConfig() internal view {
console.log("Checking SystemConfig at ", proxies.SystemConfig);
SystemConfig sc = SystemConfig(proxies.SystemConfig);
require(sc.owner() == address(foundationUpgradesSafe), "SC owner must be Foundation Upgrade Safe");
require(sc.overhead() == 0, "SC overhead should still be 0");
require(sc.scalar() == scalarFjord, "SC wrong encoded scalar value");
}

/// @notice Reads the contract addresses from the superchain registry.
function _getContractSet() internal view returns (Types.ContractSet memory _proxies) {
string memory addressesJson;

addressesJson = vm.readFile(
string.concat("lib/superchain-registry/superchain/extra/addresses/", l1ChainName, "/", l2ChainName, ".json")
);
_proxies.SystemConfig = stdJson.readAddress(addressesJson, "$.SystemConfigProxy");
}

function _addMultipleGenericOverrides()
internal
view
override
returns (SimulationStateOverride[] memory overrides_)
{
// set owner of SystemConfig to FUS (#011)
bytes32 ownerSlot = 0x0000000000000000000000000000000000000000000000000000000000000033;
overrides_ = new SimulationStateOverride[](1);
overrides_[0].contractAddress = proxies.SystemConfig;
overrides_[0].overrides = new SimulationStorageOverride[](1);
overrides_[0].overrides[0] =
SimulationStorageOverride({key: ownerSlot, value: bytes32(uint256(uint160(foundationUpgradesSafe)))});
}
}
103 changes: 103 additions & 0 deletions tasks/eth/014-fjord-gas-config/VALIDATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# Validation

This document can be used to validate the state diff resulting from the execution of setting the recommended protocol version and the two ownership transfers from the Foundation Operations to the Upgrade Safe (TODO).

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:

### `0x229047fed2591dbec1eF1118d64F7aF3dB9EB290` (`SystemConfig`)

We override the ownership of the `SystemConfig` contract (task#011).

- **Key:** `0x0000000000000000000000000000000000000000000000000000000000000033` <br/>
**Value:** `0x000000000000000000000000847b5c174615b1b7fdf770882256e2d3e95b9d92` <br/>
**Meaning:** Overrides ownership of `SystemConfig` to the Foundation Upgrades Safe, as if task#011 had been exectued.
It can also be validated in that tasks's validation description that this change occurs.

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

To allow simulating the transaction bundle of setting the required versions in a single Tenderly tx, the threshold is overridden to 1.
Additionally, the nonce is set to 6 to account for tasks `012` and `013`.

- **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).

- **Key:** `0x0000000000000000000000000000000000000000000000000000000000000005` <br/>
**Value:** `0x0000000000000000000000000000000000000000000000000000000000000006`
**Meaning:** Sets the Safe nonce to the hardcoded value of 6. This is the expected value of the Safe nonce at the time of execution. The key can be validated by the location of the `nonce` variable in the [Safe's Storage Layout](https://github.com/safe-global/safe-smart-account/blob/v1.3.0/contracts/examples/libraries/GnosisSafeStorage.sol#L17).

## State Changes

### `0x229047fed2591dbec1eF1118d64F7aF3dB9EB290` (`SystemConfig`)

- **Key:** `0x0000000000000000000000000000000000000000000000000000000000000066` <br/>
**Before:** `0x010000000000000000000000000000000000000000000000000c5fc500000558` <br/>
**After:** `0x010000000000000000000000000000000000000000000000000f79c50000146b` <br/>
**Meaning:** This updates the encoded `scalar` value to hold the new base fee and blob base fee scalars. See next section "Gas Config Update Details" for details.
The correct slot can be verified with the [storage layout](https://github.com/ethereum-optimism/optimism/blob/31653e5e51c22a239dad1a682b931e696e1539c9/packages/contracts-bedrock/snapshots/storageLayout/SystemConfig.json#L48) (`0x66 = 102`).

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

The `SystemConfig` also emits a `ConfigUpdate` event, with `updateType` set to `1` and data containing the packed `overhead` and `scalar` values.
The `updateType = 1` value can be verified in the contract source's [enum definition](https://github.com/ethereum-optimism/optimism/blob/31653e5e51c22a239dad1a682b931e696e1539c9/packages/contracts-bedrock/src/L1/SystemConfig.sol#L26).

### Nonce increments

The only other state changes are two nonce increments:

- One on the Foundation Upgrade Safe (`0x847B5c174615B1B7fDF770882256e2D3E95b9D92`). If this is not decoded, it corresponds to key `0x05` on a `GnosisSafeProxy`.
- One on the owner on the account that sent the transaction.

## Gas Config Update Details

The basefee and blob basefee scalars are updated to
* `L1BaseFeeScalar: 5227`
* `BlobBaseFeeScalar: 1014213`
maurelian marked this conversation as resolved.
Show resolved Hide resolved

These values are optimized for sending 5 blobs per transactions on OP Mainnet
and are the result of running [this Fjord chain scalar calculator](https://docs.google.com/spreadsheets/d/1V3CWpeUzXv5Iopw8lBSS8tWoSzyR4PDDwV9cu2kKOrs/edit#gid=186414307)
with the following parameters, which are the default:
* Transactions per day: 500,000
* Comparable Transaction Type : OP Mainnet
* Data Availability Type: Ethereum
* Fault Proofs Enabled: yes
* Max # of Blobs per L1 Transaction: 5
* Target Data Margin: 5%
* Include Output Root Costs in User Fees?: yes

## Transaction creation

Fjord uses the same fee scalar encoding format as Ecotone.

The [`ecotone-scalar`](https://github.com/ethereum-optimism/optimism/tree/develop/op-chain-ops/cmd/ecotone-scalar)
encoding tool was used to determine the correct transaction input (execute in monorepo):
```
go run ./op-chain-ops/cmd/ecotone-scalar --scalar=5227 --blob-scalar=1014213
# base fee scalar : 5227
# blob base fee scalar: 1014213
# v1 hex encoding : 0x010000000000000000000000000000000000000000000000000f79c50000146b
# uint value for the 'scalar' parameter in SystemConfigProxy.setGasConfig():
452312848583266388373324160190187140051835877600158453279135543542576845931```
Note the *hex encoding* `0x010000000000000000000000000000000000000000000000000f79c50000146b`.

This encoding follows the [spec change for Ecotone fee scalars](https://github.com/ethereum-optimism/specs/blob/11099e9908bb7bfa640d73b2a3a2349bef9ab7a1/specs/protocol/system_config.md#scalars).
Notably, in version 1 of the scalar encoding format, the `overhead` is set to 0 and the old `scalar` field
now encodes the _base fee scalar_ as well as the _blob base fee scalar_ in a packed format.
The first byte of the `scalar` field denotes the version `0x01`.

The transaction was created in the root directory with

```
just add-transaction tasks/eth/014-fjord-gas-config/input.json 0x229047fed2591dbec1eF1118d64F7aF3dB9EB290 'setGasConfig(uint256,uint256)' 0 0x010000000000000000000000000000000000000000000000000f79c50000146b
```

8 changes: 8 additions & 0 deletions tasks/eth/014-fjord-gas-config/input.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"transactions": [
{
"to": "0x229047fed2591dbec1eF1118d64F7aF3dB9EB290",
"data": "0x935f029e0000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000f79c50000146b"
}
]
}