From 90b974ff034f7f72959862dd1c53b3aa92da15c3 Mon Sep 17 00:00:00 2001 From: Thanh Trinh Date: Wed, 5 Aug 2026 02:28:32 -0500 Subject: [PATCH 1/9] docs: align README with task-local workflows Co-authored-by: Codex --- README.md | 267 ++++++++---------------------------------------------- 1 file changed, 40 insertions(+), 227 deletions(-) diff --git a/README.md b/README.md index 75b9814b..b5f4f12f 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ This repo contains execution code and artifacts related to Base contract deployments, upgrades, and calls. For actual contract implementations, see [base/contracts](https://github.com/base/contracts). -This repo is structured with each network having a high-level directory which contains subdirectories of any "tasks" (contract deployments/calls) that have happened for that network. +Active EVM tasks live under `active/evm/tasks/`. Shared network configuration lives under `config/`, and completed historical tasks live under `archive/`. @@ -72,84 +72,48 @@ This is purely a convenience for task authors — `make` targets work correctly ### Running a task -To execute a new task, run one of the following commands (depending on the type of change you're making): +Each active task has its own `Makefile`, signer-facing `README.md`, facilitator +guide, task configuration, and validation files. Run task commands from that +task's directory: -- For gas increase tasks: `make setup-gas-increase network=` -- For combined gas, elasticity, and DA footprint gas scalar tasks: `make setup-gas-and-elasticity-increase 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=` -- For pausing SuperchainConfig: `make setup-superchain-config-pause network=` - -Each `setup-*` command also creates a matching `/signatures//` directory for [task origin signing](#task-origin-signing). The parent `signatures/` directory is created automatically via `mkdir -p` for networks that do not yet have one. - -Next, `cd` into the directory that was created for you and follow the steps listed below for the relevant template. +```bash +cd active/evm/tasks/ +make deps +make +``` -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. +Signers start the UI from the repository root with `make sign-task`, select the +network and task, then follow the task README. ## Network configuration -Each network directory (`mainnet/`, `sepolia/`, `sepolia-alpha/`, `zeronet/`) contains a `.env` file that defines all contract addresses and network metadata for that chain. These variables are automatically available to every task via the `include ../.env` directive in each task's Makefile, so there is no need to manually load addresses in individual tasks or templates. - -The network `.env` files contain: - -- **Network metadata** — `NETWORK`, `L1_RPC_URL`, `L2_RPC_URL`, `L1_CHAIN_ID`, `L2_CHAIN_ID`, `LEDGER_ACCOUNT` -- **Admin addresses** — multisig addresses, proposer, challenger, batch sender, etc. -- **L1 contract addresses** — proxy admin, bridges, dispute game factories, system config, etc. -- **L2 contract addresses** — fee vaults, cross-domain messenger, standard bridge, etc. - -All address variables are prefixed with `export` so they are available to child shell processes (Forge scripts, shell commands, etc.). Foundry scripts can access them via `vm.envAddress("VARIABLE_NAME")`. - -> **Note:** If you need to add or update a contract address, edit the corresponding `{network}/.env` file directly. Do not create per-task address definitions unless they are truly task-specific. +Shared network values live in `config/mainnet.env`, `config/sepolia.env`, and +`config/zeronet.env`. Task Makefiles include the appropriate shared file, while +`config//.env` inside the task contains only task-specific values such +as `BASE_CONTRACTS_COMMIT`. ## Directory structure -Active EVM tasks live under `active/evm/`, which is a single shared Foundry -project rather than a standalone project per task. A single `active/evm/Makefile` -selects the active task via `TASK_ID` / `TASK_NETWORK`, reusable operation -scripts are shared across tasks under `script/common//`, and each task -directory holds only its own config, docs, and (per-network) validations and -signatures: +`active/evm` is one shared Foundry project. Common Solidity lives under +`script/common/`, dependencies are installed into `active/evm/lib`, and each +task owns its operational files: ```text active/evm/ -├── Makefile # shared; selects the task via TASK_ID / TASK_NETWORK -├── foundry.toml # shared Foundry config (base-contracts v8.2.1) -├── script/ -│ └── common/ # reusable scripts, shared across tasks -│ └── / # bridge, funding, gas, ownership, safe, superchain, verifier-update -└── tasks/ - └── / - ├── FACILITATOR.md - ├── config/ - │ └── / - │ ├── .env # task inputs + BASE_CONTRACTS_COMMIT + RECORD_STATE_DIFF - │ ├── network.env # RPC, chain ids, Safe/contract addresses - │ ├── README.md # status + description (parsed by the signer tool) - │ └── validations/ # generated per-signer validation JSON - └── signatures/ - └── / # task-origin signatures (when required) +├── foundry.toml +├── script/common/ +└── tasks// + ├── Makefile + ├── FACILITATOR.md + ├── config// + │ ├── .env + │ ├── README.md + │ └── validations/ + └── signatures// ``` -Task commands run from `active/evm`, selecting the task by `TASK_ID` / -`TASK_NETWORK` (both default to the current task in the shared `Makefile`), e.g. -`TASK_ID= TASK_NETWORK= make gen-validation-cb`. The shared -Makefile runs Forge from `active/evm` using the shared `foundry.toml` and `lib/`, -while task-specific files are read from `tasks//config//`. -Reusable scripts are documented in [`active/evm/script/common/README.md`](active/evm/script/common/README.md); -put a script under `script/common//` when it will be reused across -tasks, and keep one-off task glue out of `common/`. - -The shared `active/evm/Makefile` selects a task (via `TASK_ID` / `TASK_NETWORK`) -and sources that task's `.env` for `BASE_CONTRACTS_COMMIT`. To install -dependencies for the shared project without selecting a task (e.g. to build the -common scripts locally), invoke the root Makefile directly with a `PROJECT_DIR` -override and an explicit `BASE_CONTRACTS_COMMIT`: - -```bash -make deps PROJECT_DIR="$PWD/active/evm" BASE_CONTRACTS_COMMIT= -``` +Reusable scripts are documented in +[`active/evm/script/common/README.md`](active/evm/script/common/README.md). ### Legacy tasks @@ -185,167 +149,16 @@ A GitHub Actions workflow automatically validates the shared `active/evm` script ## Multisig macro convention -All task templates use global macros defined in [`Multisig.mk`](Multisig.mk) for multisig operations: - -| Macro | Purpose | Key arguments | -| ------------------ | --------------------------------------------------------------- | --------------------------------------------------------- | -| `MULTISIG_APPROVE` | Approve a transaction (nested safe hierarchy) | `(address_list, signatures)` | -| `MULTISIG_EXECUTE` | Execute an approved transaction on-chain | `(signatures)` | -| `GEN_VALIDATION` | Generate a validation JSON file for signers via the signer-tool | `(script_name, safe_addr, sender, output_file, env_vars)` | - -Two helper macros are also available for tasks that need nonce offset calculations or address manipulation: - -| Macro | Purpose | Key arguments | -| ------------ | ---------------------------------------------------------- | ---------------- | -| `GET_NONCE` | Fetch the current nonce of a Safe contract on-chain | `(safe_address)` | -| `ADDR_UPPER` | Convert an address to uppercase (for env var construction) | `(address)` | - -Signing is handled externally by the [task-signing-tool](https://github.com/base/task-signing-tool). - -Every template Makefile should include `Multisig.mk` and define at least two variables for the macros to work: - -```makefile -include ../../Makefile -include ../../Multisig.mk -include ../.env -include .env - -RPC_URL = $(L1_RPC_URL) # or $(L2_RPC_URL) -SCRIPT_NAME = MyScript # class name or .sol file path -``` - -Templates that generate validation files should use `GEN_VALIDATION` with the `deps-signer-tool` prerequisite (which checks out and installs the signer-tool): - -```makefile -gen-validation: validate-config deps-signer-tool - $(call GEN_VALIDATION,$(SCRIPT_NAME),,$(SENDER),base-signer.json,) -``` - -Templates should use these macros rather than inline `forge script` / `eip712sign` / `bun run` invocations. The known exceptions are the incident-response pause templates, which pre-sign 20 future nonces in a loop using inline `eip712sign`; only their `execute-*` targets use `MULTISIG_EXECUTE`. +Task Makefiles use the shared macros in [`Multisig.mk`](Multisig.mk) for +validation generation, nested-Safe approvals, and execution. Tasks running from +their own directory set `FORGE_WORKDIR` to `active/evm` so Forge uses the shared +Foundry project and common scripts. ## Task origin signing -The root Makefile provides three targets for generating cryptographic attestations (sigstore bundles) that prove who created and facilitated a task. These are inherited by all task Makefiles via `include ../../Makefile`. - -| Target | Purpose | -| ------------------------------- | ----------------------------------------------- | -| `make sign-as-task-creator` | Attest authorship of the task (run after setup) | -| `make sign-as-base-facilitator` | Attest Base team facilitation | -| `make sign-as-sc-facilitator` | Attest Security Council facilitation | - -Signatures are stored in `/signatures//`, where `` is auto-derived from the task directory name. This directory is created automatically when you run any `setup-*` target (in both the root and Solana Makefiles), so it is ready for the signing tool when you invoke one of the targets below. Two variables control this behavior and can be overridden in a task's Makefile if the defaults are not appropriate: - -| Variable | Default | Description | -| --------------- | ------------------------------------------ | ------------------------------------- | -| `TASK_NAME` | `$(notdir $(CURDIR))` (directory basename) | Name used to locate signature dir | -| `SIGNATURE_DIR` | `$(CURDIR)/../signatures/$(TASK_NAME)` | Directory where signatures are stored | - -All three targets depend on `deps-signer-tool`, which checks out and installs the [task-signing-tool](https://github.com/base/task-signing-tool) automatically. - -For `active/evm` tasks, the shared Makefile overrides `TASK_ORIGIN_DIR` and `SIGNATURE_DIR`: the signer tool signs over the `active/evm/tasks//config/` directory (`TASK_ORIGIN_DIR`), while the signatures themselves are written to `active/evm/tasks//signatures//` (`SIGNATURE_DIR`) — outside the signed directory, so generating signatures does not change the signed payload. A task may opt out of task-origin validation entirely by setting `skipTaskOriginValidation: true` at the root of each validation file (e.g. non-production networks such as zeronet). - -## Using the gas limit increase template - -This template is increasing the throughput on Base Chain. - -1. Ensure you have followed the instructions above in `setup` -1. Go to the folder that was created using the `make setup-gas-increase network=` step -1. Fill in all TODOs (search for "TODO" in the folder) in the `.env` and `README` files. Tip: you can run `make deps` followed by `make sign-upgrade` to produce a Tenderly simulation which will help fill in several of the TODOs in the README (and also `make sign-rollback`). -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, elasticity, and DA footprint gas scalar template - -This template is used to update the gas limit, elasticity, and DA footprint gas scalar, or roll back the changes (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 [Base contracts code](https://github.com/base/contracts) in the `.env` file. -1. Run `make deps`. -1. Fill in any task-specific variables in the `.env` file that have per-network comments (e.g., `OWNER_SAFE`, `SENDER`), using the value for your target network. -1. Ensure the `SENDER` variable in the `.env` file is set to a signer of `OWNER_SAFE`. -1. Set the `FROM_*` and `TO_*` values for gas limit and elasticity in the `.env` file. -1. Calculate the DA footprint gas scalar using the DA limits runbook at `go/base-da-config`. `make da-scalar TARGET_BLOB_COUNT=` is the source of truth for the standard soft-cap policy and calculates `gas_limit / (elasticity * da_soft_cap_blob_count * 32,000)`. Since BPO2, Base has used a DA soft-cap blob count of 21, passed as `TARGET_BLOB_COUNT=21`, to allow the chain to use all L1 DA before raising the L2 base fee. The command prints the `.env` value and the DA table to copy into the task README. Pass `BUILDER_HARD_CAP=` after checking the target network's `op_batcher_throttle_block_size_upper_limit` Config Service value. The task README includes links for the standard network scopes. Set the `FROM_DA_FOOTPRINT_GAS_SCALAR` and `TO_DA_FOOTPRINT_GAS_SCALAR` values in the `.env` file. -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 safe management template - -This template is used to perform ownership management on a Gnosis Safe, like the incident multisig, specifically it can be used to change the owners of the multisig. - -1. Ensure you have followed the instructions above in `setup`, including running `make setup-safe-management network=` and go to the folder that was created by this command. -1. Specify the commit of [Base contracts code](https://github.com/base/contracts) you intend to use in the `.env` file. -1. Enter the directory that was generated for the task (in the first step) and then run `make deps`. -1. Specify the `OWNER_SAFE`, which is the safe multisig where an owner will be replaced and the `SENDER` which should be the address of a current signer of the multisig. -1. Fill in the `OwnerDiff.json` inside the task's directory with the addresses to add to, and remove from, the multisig in their respective fields. -1. Ensure that the `EXISTING_OWNERS_LENGTH` constant value inside the `script/UpdateSigners.s.sol` script is set appropriately, in particular that it equals the exact number of current members of the Incident Multisig Safe (prior to running the task). -1. Build the contracts with `forge build`. -1. Generate the validation file for signers with `make gen-validation`. -1. Double check the `cmd` field at the top of the generated validation file at `validations/base-signer.json` and ensure that the value passed to the `--sender` flag matches the `SENDER` env var already defined in the `.env` file. -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 funding template - -This template is used to fund addresses from a Gnosis Safe. - -1. Ensure you have followed the instructions above in `setup`. -1. Run `make setup-funding network=` and go to the folder that was created by this command. -1. Specify the commit of [Base contracts code](https://github.com/base/contracts) you intend to use in the `.env` file. -1. Run `make deps`. -1. Specify the `SAFE`, which is the safe that will fund the addresses in the `.env` file. -1. Specify the `recipients` and `funds` arrays (in 1e18 units) in the `funding.json` file. -1. Build the contracts with `forge build`. -1. Simulate the task with `make sign` and update the generic validations in `VALIDATION.md` with the real values. -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 Base Bridge set partner threshold template - -This template is used to update the partner threshold in [Base Bridge](https://github.com/base/bridge), affecting the amount of required partner signatures to approve bridge messages. - -1. Ensure you have followed the instructions above in `setup`. -1. Run `make setup-bridge-partner-threshold network=` and go to the folder that was created by this command. -1. Specify the commit of [Base contracts code](https://github.com/base/contracts) you intend to use in the `.env` file. -1. Run `make deps`. -1. Fill in any task-specific variables in the `.env` file that have per-network comments, using the value for your target network. -1. Set the `NEW_THRESHOLD` variable in the `.env` file. -1. Ensure the `--sender` flag in the `make gen-validation` command in the `Makefile` file is set to a signer for `OWNER_SAFE` in `.env`. -1. Build the contracts with `forge build`. -1. Generate the validation file for signers with `make gen-validation`. -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 pause Base Bridge template - -This template is used to pause or un-pause [Base Bridge](https://github.com/base/bridge). - -1. Ensure you have followed the instructions above in `setup`. -1. Run `make setup-bridge-pause network=` and go to the folder that was created by this command. -1. Specify the commit of [Base contracts code](https://github.com/base/contracts) you intend to use in the `.env` file. -1. Run `make deps`. -1. Fill in any task-specific variables in the `.env` file that have per-network comments (e.g., `L2_BRIDGE`), using the value for your target network. -1. Set the `IS_PAUSED` variable to `true` or `false` in the `.env` file depending on if you intend to pause or unpause the bridge. -1. Ensure the `SENDER` variable in the Makefile is set to a signer for `OWNER_SAFE`. -1. Build the contracts with `forge build`. -1. Generate the validation file for signers with `make gen-validation`. -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 pause SuperchainConfig template - -This template is used to pause or un-pause the L1 SuperchainConfig contract. - -1. Ensure you have followed the instructions above in `setup`. -1. Run `make setup-superchain-config-pause network=` and go to the folder that was created by this command. -1. Specify the commit of [Base contracts code](https://github.com/base/contracts) you intend to use in the `.env` file. -1. Run `make deps`. -1. Fill in any task-specific variables in the `.env` file that have per-network comments, using the value for your target network. -1. Build the contracts with `forge build`. -1. Sign the pause transaction with `make sign-pause` or generate the validation file for un-pausing with `make gen-validation-unpause`. -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. +The root Makefile provides `sign-as-task-creator`, +`sign-as-base-facilitator`, and `sign-as-sc-facilitator`. Active task Makefiles +set `TASK_ORIGIN_DIR` to `config/` and store signatures separately in +`signatures/` so generating signatures does not change the signed +payload. Validation files may set `skipTaskOriginValidation: true` where task +origin validation is not required. From b2259340452f9b4f792f162bb0831735b6b63a75 Mon Sep 17 00:00:00 2001 From: Thanh Trinh Date: Wed, 5 Aug 2026 02:33:14 -0500 Subject: [PATCH 2/9] docs: preserve operational workflow details Co-authored-by: Codex --- README.md | 112 ++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 88 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index b5f4f12f..5db47a14 100644 --- a/README.md +++ b/README.md @@ -92,24 +92,41 @@ Shared network values live in `config/mainnet.env`, `config/sepolia.env`, and `config//.env` inside the task contains only task-specific values such as `BASE_CONTRACTS_COMMIT`. +The shared network files contain: + +- **Network metadata** — RPC URLs, chain IDs, and Ledger account index +- **Admin addresses** — multisigs, proposer, challenger, and batch sender +- **L1 addresses** — proxy admin, bridges, dispute games, and system config +- **L2 addresses** — predeploys, bridges, and fee vaults + +Address variables are exported so Forge scripts can read them through +`vm.envAddress`. Update `config/.env` when a known shared address +changes; keep operation-specific values in the task `.env`. + ## Directory structure -`active/evm` is one shared Foundry project. Common Solidity lives under -`script/common/`, dependencies are installed into `active/evm/lib`, and each -task owns its operational files: +`active/evm` is one shared Foundry project. Common Solidity and dependencies are +shared, while each task owns its Make targets, documentation, configuration, +signatures, and execution records: ```text active/evm/ -├── foundry.toml -├── script/common/ -└── tasks// - ├── Makefile - ├── FACILITATOR.md - ├── config// - │ ├── .env - │ ├── README.md - │ └── validations/ - └── signatures// +├── foundry.toml # shared Foundry configuration +├── lib/ # generated shared dependencies; not committed +├── script/ +│ └── common/ # reusable Solidity operations +└── tasks/ + └── / + ├── Makefile # task dependencies, validation, and execution + ├── FACILITATOR.md # facilitator runbook + ├── config/ + │ └── / + │ ├── .env # task inputs + BASE_CONTRACTS_COMMIT + │ ├── README.md # signer-facing status and instructions + │ └── validations/ # generated signer validation JSON + ├── signatures/ + │ └── / # task-origin signatures when required + └──