diff --git a/Makefile b/Makefile index daf4637d..25e99de5 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,7 @@ FOUNDRY_COMMIT ?= 3b1129b5bc43ba22a9bcf4e4323c5a9df0023140 PROJECT_DIR = $(network)/$(shell date +'%Y-%m-%d')-$(task) GAS_INCREASE_DIR = $(network)/$(shell date +'%Y-%m-%d')-increase-gas-limit +GAS_AND_ELASTICITY_INCREASE_DIR = $(network)/$(shell date +'%Y-%m-%d')-increase-gas-and-elasticity-limit FAULT_PROOF_UPGRADE_DIR = $(network)/$(shell date +'%Y-%m-%d')-upgrade-fault-proofs SAFE_MANAGEMENT_DIR = $(network)/$(shell date +'%Y-%m-%d')-safe-swap-owner FUNDING_DIR = $(network)/$(shell date +'%Y-%m-%d')-funding @@ -10,6 +11,7 @@ PAUSE_BRIDGE_BASE_DIR = $(network)/$(shell date +'%Y-%m-%d')-pause-bridge-base TEMPLATE_GENERIC = setup-templates/template-generic TEMPLATE_GAS_INCREASE = setup-templates/template-gas-increase +TEMPLATE_GAS_AND_ELASTICITY_INCREASE = setup-templates/template-gas-and-elasticity-increase TEMPLATE_UPGRADE_FAULT_PROOFS = setup-templates/template-upgrade-fault-proofs TEMPLATE_SAFE_MANAGEMENT = setup-templates/template-safe-management TEMPLATE_FUNDING = setup-templates/template-funding @@ -39,6 +41,11 @@ setup-gas-increase: rm -rf $(TEMPLATE_GAS_INCREASE)/cache $(TEMPLATE_GAS_INCREASE)/lib $(TEMPLATE_GAS_INCREASE)/out cp -r $(TEMPLATE_GAS_INCREASE) $(GAS_INCREASE_DIR) +# Run `make setup-gas-increase network=` +setup-gas-and-elasticity-increase: + rm -rf $(TEMPLATE_GAS_AND_ELASTICITY_INCREASE)/cache $(TEMPLATE_GAS_AND_ELASTICITY_INCREASE)/lib $(TEMPLATE_GAS_AND_ELASTICITY_INCREASE)/out + cp -r $(TEMPLATE_GAS_AND_ELASTICITY_INCREASE) $(GAS_AND_ELASTICITY_INCREASE_DIR) + # Run `make setup-upgrade-fault-proofs network=` setup-upgrade-fault-proofs: cp -r $(TEMPLATE_UPGRADE_FAULT_PROOFS) $(FAULT_PROOF_UPGRADE_DIR) @@ -112,7 +119,7 @@ checkout-base-contracts-commit: ## # Task Signer Tool ## -SIGNER_TOOL_COMMIT=92a4b600252cd7ffe255a876a880c2540802b99c +SIGNER_TOOL_COMMIT=63df22556bb41f6a1fd14f90da2809a7c4e5fe8a SIGNER_TOOL_PATH=signer-tool .PHONY: checkout-signer-tool diff --git a/README.md b/README.md index 5b6a76f2..1df636c8 100644 --- a/README.md +++ b/README.md @@ -37,10 +37,10 @@ To execute a new task, run one of the following commands (depending on the type - For a generic task: `make setup-task network= task=` - For gas increase tasks: `make setup-gas-increase network=` +- For combined gas and elasticity increase tasks: `make setup-gas-and-elasticity-increase network=` - For funding: `make setup-funding network=` - For fault proof upgrade: `make setup-upgrade-fault-proofs network=` - For safe management tasks: `make setup-safe-management network=` -- For funding tasks: `make setup-funding network=` - For updating the partner threshold in Base Bridge: `make setup-bridge-partner-threshold network=` - For pausing / un-pausing Base Bridge: `make setup-bridge-pause network=` @@ -48,7 +48,7 @@ Next, `cd` into the directory that was created for you and follow the steps list > **👥 For Signers:** Please read the [Signer Guide](SIGNER.md) for step-by-step instructions on using the validation UI. -Please note, you will need to manually create validation file(s) for your task as they are bespoke to each task and therefore not created automatically as a part of the templates. We use one validation Markdown file per multisig involved in the task, so if there's only one multisig involved in your task, then you can simply create a `VALIDATION.md` file at the root of your task containing the validation instructions, while if there are multiple multisigs involved in the task, then create a `validations/` sub-directory at the root of your task containing the corresponding validation Markdown files. If you need examples to work from, you can browse through similar past tasks in this repo and adapt them to your specific task. Also, please note that we have tooling to generate these files (like the `task-signer-tool`) which removes the manual aspect of creating these validation files, we will soon update these instructions to reflect how this process can be automated. +Please note, for some older tasks (that have not yet been adapted to use the signer tool) you will need to manually create validation file(s) for your task as they are bespoke to each task and therefore not created automatically as a part of the templates. We use one validation Markdown file per multisig involved in the task, so if there's only one multisig involved in your task, then you can simply create a `VALIDATION.md` file at the root of your task containing the validation instructions, while if there are multiple multisigs involved in the task, then create a `validations/` sub-directory at the root of your task containing the corresponding validation Markdown files. If you need examples to work from, you can browse through similar past tasks in this repo and adapt them to your specific task. Also, please note that we have tooling to generate these files (like the `task-signer-tool`) which removes the manual aspect of creating these validation files, we will soon update these instructions to reflect how this process can be automated. ## Directory structure @@ -96,6 +96,23 @@ This template is increasing the throughput on Base Chain. 1. Check in the task when it's ready to sign and collect signatures from signers 1. Once executed, check in the records files and mark the task `EXECUTED` in the README. +## Using the combined gas limit and elasticity increase template + +This template is used to increase the gas limit and elasticity or roll back the upgrade (if needed). + +1. Ensure you have followed the instructions above in `setup`, including running `make setup-gas-and-elasticity-increase network=` and then go to the folder that was created by this command. +1. Specify the commit of [Optimism code](https://github.com/ethereum-optimism/optimism) and [Base contracts code](https://github.com/base/contracts), and the new / old gas limit and elasticity, as well the other env vars marked with a TODO, in the `.env` file. +1. Run `make deps`. +1. Ensure only the Sepolia or Mainnet variables are in the `.env` file depending on what network this task is for. +1. Ensure the `SENDER` variable in the `.env` file is set to a signer of `OWNER_SAFE`. +1. Build the contracts with `forge build`. +1. Generate the validation file for signers with `make gen-validation`. +1. Generate the rollback validation file for signers with `make gen-validation-rollback`. +1. Double check the `cmd` field at the top of both of the generated validation files and ensure that the value passed to the `--sender` flag matches the `SENDER` env var already defined in the `.env` file. +1. Ensure that all of the fields marked as `TODO` in the tasks's `README.md` have been properly filled out. +1. Check in the task when it's ready to sign and request the facilitators to collect signatures from signers. +1. Once executed, check in the records files and mark the task `EXECUTED` in the README. + ## Using the fault proof upgrade template This template is used to upgrade the fault proof contracts. This is commonly done in conjunction with a hard fork. diff --git a/setup-templates/template-gas-and-elasticity-increase/.env b/setup-templates/template-gas-and-elasticity-increase/.env new file mode 100644 index 00000000..6c4ac5d9 --- /dev/null +++ b/setup-templates/template-gas-and-elasticity-increase/.env @@ -0,0 +1,25 @@ +OP_COMMIT=TODO # Recommend using the version of https://github.com/ethereum-optimism/optimism that the current SystemConfig contract is on +BASE_CONTRACTS_COMMIT=TODO # Recommend using the latest version of https://github.com/base-org/contracts + +# TODO: ensure that the `SYSTEM_CONFIG` / `OWNER_SAFE` below are set for the correct network + +# Mainnet +SYSTEM_CONFIG=0x73a79Fab69143498Ed3712e519A88a918e1f4072 +OWNER_SAFE=0x14536667Cd30e52C0b458BaACcB9faDA7046E056 + +# Sepolia +# SYSTEM_CONFIG=0xf272670eb55e895584501d564AfEB048bEd26194 +# OWNER_SAFE=0x0fe884546476dDd290eC46318785046ef68a0BA9 + +# TODO: ensure the current and future gas limits are set properly +FROM_GAS_LIMIT=TODO +TO_GAS_LIMIT=TODO + +# TODO: ensure the current and future elasticities are set properly +FROM_ELASTICITY=TODO +TO_ELASTICITY=TODO + +# TODO: ensure `SENDER` is a signer for `OWNER_SAFE` on the given network +SENDER=0x1841CB3C2ce6870D0417844C817849da64E6e937 + +RECORD_STATE_DIFF=true diff --git a/setup-templates/template-gas-and-elasticity-increase/FACILITATOR.md b/setup-templates/template-gas-and-elasticity-increase/FACILITATOR.md new file mode 100644 index 00000000..7b8c393c --- /dev/null +++ b/setup-templates/template-gas-and-elasticity-increase/FACILITATOR.md @@ -0,0 +1,28 @@ +# Facilitator Guide + +Guide for facilitators after collecting signatures from signers. + +### 1. Update repo: + +```bash +cd contract-deployments +git pull +cd mainnet/TODO +make deps +``` + +### 2. Execute upgrade + +```bash +SIGNATURES=AAABBBCCC make execute +``` + +### 3. (**ONLY** if needed) Execute upgrade rollback + +> [!IMPORTANT] +> +> THIS SHOULD ONLY BE PERFORMED IN THE EVENT THAT WE NEED TO ROLLBACK + +```bash +SIGNATURES=AAABBBCCC make execute-rollback +``` diff --git a/setup-templates/template-gas-and-elasticity-increase/Makefile b/setup-templates/template-gas-and-elasticity-increase/Makefile new file mode 100644 index 00000000..11194d96 --- /dev/null +++ b/setup-templates/template-gas-and-elasticity-increase/Makefile @@ -0,0 +1,61 @@ +include ../../Makefile +include ../../Multisig.mk +include ../.env +include .env + +ifndef LEDGER_ACCOUNT +override LEDGER_ACCOUNT = 0 +endif + +ifndef ROLLBACK_NONCE_OFFSET +override ROLLBACK_NONCE_OFFSET = 1 +endif + +RPC_URL = $(L1_RPC_URL) +SCRIPT_NAME = IncreaseEip1559ElasticityAndIncreaseGasLimitScript + +.PHONY: gen-validation +gen-validation: checkout-signer-tool run-script + +.PHONY: run-script +run-script: + mkdir validations; \ + cd $(SIGNER_TOOL_PATH); \ + npm ci; \ + bun run scripts/genValidationFile.ts --rpc-url $(RPC_URL) \ + --workdir .. --forge-cmd 'NEW_GAS_LIMIT=$(TO_GAS_LIMIT) \ + OLD_GAS_LIMIT=$(FROM_GAS_LIMIT) NEW_ELASTICITY=$(TO_ELASTICITY) OLD_ELASTICITY=$(FROM_ELASTICITY) \ + forge script --rpc-url $(RPC_URL) \ + $(SCRIPT_NAME) --sig "sign(address[])" [] --sender $(SENDER)' --out ../validations/base-signer.json; + +.PHONY: execute +execute: + NEW_GAS_LIMIT=$(TO_GAS_LIMIT) \ + OLD_GAS_LIMIT=$(FROM_GAS_LIMIT) \ + NEW_ELASTICITY=$(TO_ELASTICITY) \ + OLD_ELASTICITY=$(FROM_ELASTICITY) \ + $(call MULTISIG_EXECUTE,$(SIGNATURES)) + +.PHONY: gen-validation-rollback +gen-validation-rollback: checkout-signer-tool run-script-rollback + +.PHONY: run-script-rollback +run-script-rollback: + cd $(SIGNER_TOOL_PATH); \ + npm ci; \ + bun run scripts/genValidationFile.ts --rpc-url $(RPC_URL) \ + --workdir .. --forge-cmd 'OLD_GAS_LIMIT=$(TO_GAS_LIMIT) \ + NEW_GAS_LIMIT=$(FROM_GAS_LIMIT) OLD_ELASTICITY=$(TO_ELASTICITY) NEW_ELASTICITY=$(FROM_ELASTICITY) \ + SAFE_NONCE=$(shell expr $$(cast call $(OWNER_SAFE) "nonce()" --rpc-url $(RPC_URL) | cast to-dec) + $(ROLLBACK_NONCE_OFFSET)) \ + forge script --rpc-url $(RPC_URL) \ + $(SCRIPT_NAME) --sig "sign(address[])" [] --sender $(SENDER)' --out ../validations/base-signer-rollback.json; + +.PHONY: execute-rollback +execute-rollback: + OLD_GAS_LIMIT=$(TO_GAS_LIMIT) \ + NEW_GAS_LIMIT=$(FROM_GAS_LIMIT) \ + OLD_ELASTICITY=$(TO_ELASTICITY) \ + NEW_ELASTICITY=$(FROM_ELASTICITY) \ + SAFE_NONCE=$(shell expr $$(cast call $(OWNER_SAFE) "nonce()" --rpc-url $(RPC_URL) | cast to-dec) + $(ROLLBACK_NONCE_OFFSET)) \ + forge script --rpc-url $(RPC_URL) $(SCRIPT_NAME) \ + --sig "run(bytes)" $(SIGNATURES) --ledger --hd-paths "m/44'/60'/$(LEDGER_ACCOUNT)'/0/0" --broadcast diff --git a/setup-templates/template-gas-and-elasticity-increase/README.md b/setup-templates/template-gas-and-elasticity-increase/README.md new file mode 100644 index 00000000..14e02fa2 --- /dev/null +++ b/setup-templates/template-gas-and-elasticity-increase/README.md @@ -0,0 +1,69 @@ +# Update Gas Limit & Elasticity in L1 `SystemConfig` + +Status: TODO[READY TO SIGN|DONE] + +## Description + +We are updating the gas limit and elasticity to improve TPS and reduce gas fees. + +This runbook invokes the following script which allows our signers to sign the same call with two different sets of parameters for our Incident Multisig, defined in the [base-org/contracts](https://github.com/base/contracts) repository: + +`IncreaseEip1559ElasticityAndIncreaseGasLimitScript` -- This script will update the gas limit to our new limit of TODO gas and TODO elasticity if invoked as part of the "upgrade" process, or revert to the old limit of TODO gas and TODO elasticity if invoked as part of the "rollback" process. + +The values we are sending are statically defined in the `.env` file. + +> [!IMPORTANT] We have two transactions to sign. Please follow +> the flow for both "Approving the Update transaction" and +> "Approving the Rollback transaction". Hopefully we only need +> the former, but will have the latter available if needed. + +## Install dependencies + +### 1. Update foundry + +```bash +foundryup +``` + +### 2. Install Node.js if needed + +First, check if you have node installed + +```bash +node --version +``` + +If you see a version output from the above command, you can move on. Otherwise, install node + +```bash +brew install node +``` + +## Approving the Update transaction + +### 1. Update repo: + +```bash +cd contract-deployments +git pull +``` + +### 2. Run the signing tool (NOTE: do not enter the task directory. Run this command from the project's root). + +```bash +make sign-task +``` + +### 3. Open the UI at [http://localhost:3000](http://localhost:3000) + +Be sure to select the correct task from the list of available tasks to sign (**not** the "Base Signer Rollback" task). Copy the resulting signature and save it. + +### 4. Rollback signing + +Now, click on the "Base Signer" selection and switch over to the rollback task (called "Base Signer Rollback"). Copy the resulting signature and save it. + +### 5. Send signature to facilitator + +Send the two signatures to the facilitator and make sure to clearly note which one is the primary one and which one is the rollback. + +You may now kill the Signer Tool process in your terminal window by running `Ctrl + C`. diff --git a/setup-templates/template-gas-and-elasticity-increase/foundry.toml b/setup-templates/template-gas-and-elasticity-increase/foundry.toml new file mode 100644 index 00000000..1f932186 --- /dev/null +++ b/setup-templates/template-gas-and-elasticity-increase/foundry.toml @@ -0,0 +1,20 @@ +[profile.default] +src = 'src' +out = 'out' +libs = ['lib'] +broadcast = 'records' +fs_permissions = [ {access = "read-write", path = "./"} ] +optimizer = true +optimizer_runs = 999999 +solc_version = "0.8.15" +via-ir = false +remappings = [ + '@eth-optimism-bedrock/=lib/optimism/packages/contracts-bedrock/', + '@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts', + '@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts', + '@rari-capital/solmate/=lib/solmate/', + '@base-contracts/=lib/base-contracts', + '@solady/=lib/solady/src/' +] + +# See more config options https://github.com/foundry-rs/foundry/tree/master/config \ No newline at end of file diff --git a/setup-templates/template-gas-and-elasticity-increase/script/IncreaseEip1559ElasticityAndIncreaseGasLimit.s.sol b/setup-templates/template-gas-and-elasticity-increase/script/IncreaseEip1559ElasticityAndIncreaseGasLimit.s.sol new file mode 100644 index 00000000..506ebc48 --- /dev/null +++ b/setup-templates/template-gas-and-elasticity-increase/script/IncreaseEip1559ElasticityAndIncreaseGasLimit.s.sol @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import {Vm} from "forge-std/Vm.sol"; +import {Simulation} from "@base-contracts/script/universal/Simulation.sol"; +import {IMulticall3} from "forge-std/interfaces/IMulticall3.sol"; + +import {MultisigScript} from "@base-contracts/script/universal/MultisigScript.sol"; + +interface ISystemConfig { + function eip1559Elasticity() external view returns (uint32); + function eip1559Denominator() external view returns (uint32); + function setEIP1559Params(uint32 _denominator, uint32 _elasticity) external; + function gasLimit() external view returns (uint64); + function setGasLimit(uint64 _gasLimit) external; +} + +contract IncreaseEip1559ElasticityAndIncreaseGasLimitScript is MultisigScript { + address internal immutable OWNER_SAFE; + address internal immutable SYSTEM_CONFIG; + + uint32 internal immutable ELASTICITY; + uint32 internal immutable NEW_ELASTICITY; + uint64 internal immutable GAS_LIMIT; + uint64 internal immutable NEW_GAS_LIMIT; + uint32 internal immutable DENOMINATOR; + + constructor() { + OWNER_SAFE = vm.envAddress("OWNER_SAFE"); + SYSTEM_CONFIG = vm.envAddress("SYSTEM_CONFIG"); + + GAS_LIMIT = uint64(vm.envUint("OLD_GAS_LIMIT")); + NEW_GAS_LIMIT = uint64(vm.envUint("NEW_GAS_LIMIT")); + + ELASTICITY = uint32(vm.envUint("OLD_ELASTICITY")); + NEW_ELASTICITY = uint32(vm.envUint("NEW_ELASTICITY")); + + DENOMINATOR = ISystemConfig(SYSTEM_CONFIG).eip1559Denominator(); + } + + function _postCheck(Vm.AccountAccess[] memory, Simulation.Payload memory) internal view override { + vm.assertEq(ISystemConfig(SYSTEM_CONFIG).eip1559Denominator(), DENOMINATOR, "Denominator mismatch"); + vm.assertEq(ISystemConfig(SYSTEM_CONFIG).eip1559Elasticity(), NEW_ELASTICITY, "Elasticity mismatch"); + vm.assertEq(ISystemConfig(SYSTEM_CONFIG).gasLimit(), NEW_GAS_LIMIT, "Gas Limit mismatch"); + } + + function _simulationOverrides() internal view override returns (Simulation.StateOverride[] memory _stateOverrides) { + if ( + GAS_LIMIT != ISystemConfig(SYSTEM_CONFIG).gasLimit() + || ELASTICITY != ISystemConfig(SYSTEM_CONFIG).eip1559Elasticity() + ) { + // Override SystemConfig state to the expected "from" values so simulations succeeds even + // when the chain already reflects the post-change values (during rollback simulation). + + // Prepare two storage overrides for SystemConfig + Simulation.StateOverride[] memory stateOverrides = new Simulation.StateOverride[](1); + Simulation.StorageOverride[] memory storageOverrides = new Simulation.StorageOverride[](2); + + // Load current packed gas config (slot 0x68) and replace only the lower 64 bits with GAS_LIMIT + bytes32 gasConfigSlotKey = bytes32(uint256(0x68)); + uint256 gasConfigWord = uint256(vm.load(SYSTEM_CONFIG, gasConfigSlotKey)); + uint256 updatedGasConfigWord = (gasConfigWord & ~uint256(0xffffffffffffffff)) | uint256(GAS_LIMIT); + storageOverrides[0] = + Simulation.StorageOverride({key: gasConfigSlotKey, value: bytes32(updatedGasConfigWord)}); + + // Deterministically set EIP-1559 params (slot 0x6a) to [ ... | elasticity (uint32) | denominator (uint32) ] + // Compose the full 256-bit word with only these two fields set to avoid unused high bits which can + // cause mismatches during validation. + bytes32 eip1559SlotKey = bytes32(uint256(0x6a)); + uint256 composedEip1559Word = (uint256(ELASTICITY) << 32) | uint256(DENOMINATOR); + storageOverrides[1] = Simulation.StorageOverride({key: eip1559SlotKey, value: bytes32(composedEip1559Word)}); + + stateOverrides[0] = Simulation.StateOverride({contractAddress: SYSTEM_CONFIG, overrides: storageOverrides}); + return stateOverrides; + } + } + + function _buildCalls() internal view override returns (IMulticall3.Call3Value[] memory) { + IMulticall3.Call3Value[] memory calls = new IMulticall3.Call3Value[](2); + + calls[0] = IMulticall3.Call3Value({ + target: SYSTEM_CONFIG, + allowFailure: false, + callData: abi.encodeCall(ISystemConfig.setEIP1559Params, (DENOMINATOR, NEW_ELASTICITY)), + value: 0 + }); + + calls[1] = IMulticall3.Call3Value({ + target: SYSTEM_CONFIG, + allowFailure: false, + callData: abi.encodeCall(ISystemConfig.setGasLimit, (NEW_GAS_LIMIT)), + value: 0 + }); + + return calls; + } + + function _ownerSafe() internal view override returns (address) { + return OWNER_SAFE; + } +}