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

Sep 027: upgrade and re-initialize SystemConfig #418

Draft
wants to merge 19 commits into
base: main
Choose a base branch
from
Draft
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
5 changes: 0 additions & 5 deletions nested.just
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ simulate whichSafe hdPath='0':
fi
echo ""

forge build
forge script ${script} \
--rpc-url ${rpcUrl} \
--sender ${signer} \
Expand Down Expand Up @@ -85,7 +84,6 @@ sign whichSafe hdPath='0':
echo "Signing with: ${signer}"
echo ""

forge build
# Using the eip712sign within the repo folder since eip712sign was installed there in ./justfile.
$(git rev-parse --show-toplevel)/bin/eip712sign --ledger --hd-paths "m/44'/60'/{{hdPath}}'/0/0" -- \
forge script ${script} \
Expand Down Expand Up @@ -120,7 +118,6 @@ approve whichSafe hdPath='0':
fi
sender=$(cast wallet address --ledger --mnemonic-derivation-path "m/44'/60'/{{hdPath}}'/0/0")

forge build
forge script ${script} \
--fork-url ${rpcUrl} \
--ledger --hd-paths "m/44'/60'/{{hdPath}}'/0/0" \
Expand All @@ -142,7 +139,6 @@ execute hdPath='0':
echo "Using script ${script}"
sender=$(cast wallet address --ledger --mnemonic-derivation-path "m/44'/60'/{{hdPath}}'/0/0")

forge build
forge script ${script} \
--fork-url ${rpcUrl} \
--ledger --hd-paths "m/44'/60'/{{hdPath}}'/0/0" \
Expand All @@ -161,7 +157,6 @@ simulated-run hdPath='0':
fi
echo "Using script ${script}"

forge build
forge script ${script} \
--fork-url ${rpcUrl} \
--sender ${randomPersonEoa} \
Expand Down
27 changes: 27 additions & 0 deletions script/verification/IResourceMetering.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IResourceMetering {
struct ResourceParams {
uint128 prevBaseFee;
uint64 prevBoughtGas;
uint64 prevBlockNum;
}

struct ResourceConfig {
uint32 maxResourceLimit;
uint8 elasticityMultiplier;
uint8 baseFeeMaxChangeDenominator;
uint32 minimumBaseFee;
uint32 systemTxMaxGas;
uint128 maximumBaseFee;
}

error OutOfGas();

event Initialized(uint8 version);

function params() external view returns (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum); // nosemgrep

function __constructor__() external;
}
87 changes: 87 additions & 0 deletions script/verification/ISystemConfig.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {IResourceMetering} from "./IResourceMetering.sol";

/// @notice This interface corresponds to the Custom Gas Token version of the SystemConfig contract.
interface ISystemConfig {
enum UpdateType {
BATCHER,
FEE_SCALARS,
GAS_LIMIT,
UNSAFE_BLOCK_SIGNER,
EIP_1559_PARAMS
}

struct Addresses {
address l1CrossDomainMessenger;
address l1ERC721Bridge;
address l1StandardBridge;
address disputeGameFactory;
address optimismPortal;
address optimismMintableERC20Factory;
address gasPayingToken;
}

event ConfigUpdate(uint256 indexed version, UpdateType indexed updateType, bytes data);
event Initialized(uint8 version);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

function BATCH_INBOX_SLOT() external view returns (bytes32);
function DISPUTE_GAME_FACTORY_SLOT() external view returns (bytes32);
function L1_CROSS_DOMAIN_MESSENGER_SLOT() external view returns (bytes32);
function L1_ERC_721_BRIDGE_SLOT() external view returns (bytes32);
function L1_STANDARD_BRIDGE_SLOT() external view returns (bytes32);
function OPTIMISM_MINTABLE_ERC20_FACTORY_SLOT() external view returns (bytes32);
function OPTIMISM_PORTAL_SLOT() external view returns (bytes32);
function START_BLOCK_SLOT() external view returns (bytes32);
function UNSAFE_BLOCK_SIGNER_SLOT() external view returns (bytes32);
function VERSION() external view returns (uint256);
function basefeeScalar() external view returns (uint32);
function batchInbox() external view returns (address addr_);
function batcherHash() external view returns (bytes32);
function blobbasefeeScalar() external view returns (uint32);
function disputeGameFactory() external view returns (address addr_);
function gasLimit() external view returns (uint64);
function eip1559Denominator() external view returns (uint32);
function eip1559Elasticity() external view returns (uint32);
function gasPayingToken() external view returns (address addr_, uint8 decimals_);
function gasPayingTokenName() external view returns (string memory name_);
function gasPayingTokenSymbol() external view returns (string memory symbol_);
function initialize(
address _owner,
uint32 _basefeeScalar,
uint32 _blobbasefeeScalar,
bytes32 _batcherHash,
uint64 _gasLimit,
address _unsafeBlockSigner,
IResourceMetering.ResourceConfig memory _config,
address _batchInbox,
Addresses memory _addresses
) external;
function isCustomGasToken() external view returns (bool);
function l1CrossDomainMessenger() external view returns (address addr_);
function l1ERC721Bridge() external view returns (address addr_);
function l1StandardBridge() external view returns (address addr_);
function maximumGasLimit() external pure returns (uint64);
function minimumGasLimit() external view returns (uint64);
function optimismMintableERC20Factory() external view returns (address addr_);
function optimismPortal() external view returns (address addr_);
function overhead() external view returns (uint256);
function owner() external view returns (address);
function renounceOwnership() external;
function resourceConfig() external view returns (IResourceMetering.ResourceConfig memory);
function scalar() external view returns (uint256);
function setBatcherHash(bytes32 _batcherHash) external;
function setGasConfig(uint256 _overhead, uint256 _scalar) external;
function setGasConfigEcotone(uint32 _basefeeScalar, uint32 _blobbasefeeScalar) external;
function setGasLimit(uint64 _gasLimit) external;
function setUnsafeBlockSigner(address _unsafeBlockSigner) external;
function setEIP1559Params(uint32 _denominator, uint32 _elasticity) external;
function startBlock() external view returns (uint256 startBlock_);
function transferOwnership(address newOwner) external; // nosemgrep
function unsafeBlockSigner() external view returns (address addr_);
function version() external pure returns (string memory);

function __constructor__() external;
}
82 changes: 82 additions & 0 deletions script/verification/SystemConfigUpgrade.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// 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 {LibString} from "solady/utils/LibString.sol";
import {SuperchainRegistry} from "script/verification/Verification.s.sol";
import "@eth-optimism-bedrock/src/dispute/lib/Types.sol";
import {ISystemConfig} from "./ISystemConfig.sol";
import {IResourceMetering} from "./IResourceMetering.sol";
import {MIPS} from "@eth-optimism-bedrock/src/cannon/MIPS.sol";
import {Simulation} from "@base-contracts/script/universal/Simulation.sol";
import {NestedMultisigBuilder} from "@base-contracts/script/universal/NestedMultisigBuilder.sol";

contract SystemConfigUpgrade is SuperchainRegistry {
using LibString for string;

struct SysCfgVars {
address owner;
uint256 scalar;
bytes32 batcherHash;
uint256 gasLimit;
address unsafeBlockSigner;
IResourceMetering.ResourceConfig resourceConfig;
address batchInbox;
address gasPayingToken;
address l1CrossDomainMessenger;
address l1StandardBridge;
address l1ERC721Bridge;
address disputeGameFactory;
address optimismPortal;
address optimismMintableERC20Factory;
}

address public systemConfigAddress;
SysCfgVars previous;

constructor(string memory l1ChainName, string memory l2ChainName, string memory release)
SuperchainRegistry(l1ChainName, l2ChainName, release)
{
systemConfigAddress = proxies.SystemConfig;
previous = getSysCfgVars(); // Set this before the tx is executed.
}

function getSysCfgVars() internal view returns (SysCfgVars memory) {
ISystemConfig sysCfg = ISystemConfig(proxies.SystemConfig);

(address gasPayingToken,) = sysCfg.gasPayingToken();

return SysCfgVars({
owner: sysCfg.owner(),
scalar: sysCfg.scalar(),
batcherHash: sysCfg.batcherHash(),
gasLimit: sysCfg.gasLimit(),
unsafeBlockSigner: sysCfg.unsafeBlockSigner(),
resourceConfig: sysCfg.resourceConfig(),
batchInbox: sysCfg.batchInbox(),
gasPayingToken: gasPayingToken,
l1CrossDomainMessenger: sysCfg.l1CrossDomainMessenger(),
l1StandardBridge: sysCfg.l1StandardBridge(),
l1ERC721Bridge: sysCfg.l1ERC721Bridge(),
disputeGameFactory: sysCfg.disputeGameFactory(),
optimismPortal: sysCfg.optimismPortal(),
optimismMintableERC20Factory: sysCfg.optimismMintableERC20Factory()
});
}

/// @notice Public function that must be called by the verification script.
function checkSystemConfigUpgrade() public view virtual {
SysCfgVars memory got = getSysCfgVars();
require(keccak256(abi.encode(got)) == keccak256(abi.encode(previous)), "system-config-100");
}

function getCodeExceptions() public view returns (address[] memory) {
address[] memory exceptions = new address[](4);
exceptions[0] = previous.owner; // NOTE this can be removed for mainnet
exceptions[1] = address(uint160(uint256((previous.batcherHash))));
exceptions[2] = previous.unsafeBlockSigner;
exceptions[3] = previous.batchInbox;
return exceptions;
}
}
48 changes: 48 additions & 0 deletions script/verification/SystemConfigUpgradeEcotoneScalars.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// 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 {LibString} from "solady/utils/LibString.sol";
import {SuperchainRegistry} from "script/verification/Verification.s.sol";
import "@eth-optimism-bedrock/src/dispute/lib/Types.sol";
import {ISystemConfig} from "./ISystemConfig.sol";
import {IResourceMetering} from "./IResourceMetering.sol";
import {MIPS} from "@eth-optimism-bedrock/src/cannon/MIPS.sol";
import {Simulation} from "@base-contracts/script/universal/Simulation.sol";
import {NestedMultisigBuilder} from "@base-contracts/script/universal/NestedMultisigBuilder.sol";
import {SystemConfigUpgrade} from "script/verification/SystemConfigUpgrade.s.sol";

contract SystemConfigUpgradeEcotoneScalars is SystemConfigUpgrade {
using LibString for string;

constructor(string memory l1ChainName, string memory l2ChainName, string memory release)
SystemConfigUpgrade(l1ChainName, l2ChainName, release)
{}

/// @notice Public function that must be called by the verification script.
function checkSystemConfigUpgrade() public view override {
ISystemConfig sysCfg = ISystemConfig(proxies.SystemConfig);
uint256 reencodedScalar =
(uint256(0x01) << 248) | (uint256(sysCfg.blobbasefeeScalar()) << 32) | sysCfg.basefeeScalar();
console.log(
"checking baseFeeScalar and blobbaseFeeScalar ",
LibString.toString(sysCfg.basefeeScalar()),
LibString.toString(sysCfg.blobbasefeeScalar())
);
if (
uint8(previous.scalar >> 248) == 1 // most significant bit
) {
console.log(
"reencode to previous scalar: ",
LibString.toString(reencodedScalar),
LibString.toString(previous.scalar)
);
require(reencodedScalar == previous.scalar, "scalar-100 (reencoding produced incorrect result)");
// We do this check last because it would fail if the scalar is wrong, and we get less debug info from it.
// It checks all of the other fields which should not have changed (via a hash).
super.checkSystemConfigUpgrade();
}
require(sysCfg.scalar() == reencodedScalar, "scalar-101");
}
}
8 changes: 5 additions & 3 deletions script/verification/Verification.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -100,12 +100,14 @@ contract SuperchainRegistry is CommonBase {
proxies.L1CrossDomainMessenger = stdToml.readAddress(toml, "$.addresses.L1CrossDomainMessengerProxy");
proxies.L1StandardBridge = stdToml.readAddress(toml, "$.addresses.L1StandardBridgeProxy");
proxies.SystemConfig = stdToml.readAddress(toml, "$.addresses.SystemConfigProxy");
proxies.AnchorStateRegistry = stdToml.readAddress(toml, "$.addresses.AnchorStateRegistryProxy");
proxies.DisputeGameFactory = stdToml.readAddress(toml, "$.addresses.DisputeGameFactoryProxy");

// TODO handle chains which are missing these values:
// proxies.AnchorStateRegistry = stdToml.readAddress(toml, "$.addresses.AnchorStateRegistryProxy");
// proxies.DisputeGameFactory = stdToml.readAddress(toml, "$.addresses.DisputeGameFactoryProxy");
// chainConfig.unsafeBlockSigner = stdToml.readAddress(toml, "$.addresses.UnsafeBlockSigner");

chainConfig.chainId = stdToml.readUint(toml, "$.chain_id");
chainConfig.systemConfigOwner = stdToml.readAddress(toml, "$.addresses.SystemConfigOwner");
chainConfig.unsafeBlockSigner = stdToml.readAddress(toml, "$.addresses.UnsafeBlockSigner");
chainConfig.batchSubmitter = stdToml.readAddress(toml, "$.addresses.BatchSubmitter");
chainConfig.batchInbox = stdToml.readAddress(toml, "$.batch_inbox_addr");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

Status: [EXECUTED](https://sepolia.etherscan.io/tx/0x88bd1d85740af3741e2ed96d6fd07f2abb4541afc667625480bf6a28451c4d6d)

> ⚠️ **Warning:** This task is incorrect and is superceded by [Task 027](../027-holocene-system-config-upgrade-and-init-multi-chain/)

## Objective

Upgrades the `SystemConfig` for the Holocene hardfork for Sepolia/{OP,Mode,Metal,Zora,Base}.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
ETH_RPC_URL="https://ethereum-sepolia.publicnode.com"
COUNCIL_SAFE=0xf64bc17485f0B4Ea5F06A96514182FC4cB561977
FOUNDATION_SAFE=0xDEe57160aAfCF04c34C887B5962D0a69676d3C8B
OWNER_SAFE=0x1Eb2fFc903729a0F03966B917003800b145F56E2
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// 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 {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 {VerificationBase, SuperchainRegistry} from "script/verification/Verification.s.sol";
import {SystemConfigUpgradeEcotoneScalars as SystemConfigUpgrade} from
"script/verification/SystemConfigUpgradeEcotoneScalars.s.sol";

contract NestedSignFromJson is OriginalNestedSignFromJson, CouncilFoundationNestedSign {
string constant l1ChainName = "sepolia";
string constant release = "v1.8.0-rc.4";
string[4] l2ChainNames = ["op", "metal", "mode", "zora"];

SystemConfigUpgrade[] sysCfgUpgrades;

constructor() {
for (uint256 i = 0; i < l2ChainNames.length; i++) {
console.log("Setting up verification data for chain", l2ChainNames[i], "-", l1ChainName);
sysCfgUpgrades.push(new SystemConfigUpgrade(l1ChainName, l2ChainNames[i], release));
addAllowedStorageAccess(sysCfgUpgrades[i].systemConfigAddress());
address[] memory exceptions = sysCfgUpgrades[i].getCodeExceptions();
for (uint256 j = 0; j < exceptions.length; j++) {
addCodeException(exceptions[j]);
}
}
}

function _postCheck(Vm.AccountAccess[] memory accesses, Simulation.Payload memory) internal view override {
console.log("Running post-deploy assertions");
checkStateDiff(accesses);
for (uint256 i = 0; i < l2ChainNames.length; i++) {
console.log("Running post-deploy assertions for chain", l2ChainNames[i], "-", l1ChainName);
sysCfgUpgrades[i].checkSystemConfigUpgrade();
}
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