Skip to content
Merged
66 changes: 66 additions & 0 deletions active/evm/tasks/2026-10-08-denim-system-config/FACILITATOR.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Denim SystemConfig Gas Parameters — Facilitator Guide

This task writes the post-Denim gas limit and EIP-1559 denominator to `SystemConfig`, signed by the
Base multisig alone (the `SystemConfig` owner).

At the first Denim block the node divides the gas limit by 10 and multiplies the EIP-1559
denominator by 10 (`DENIM_GAS_PARAMETER_SCALING_FACTOR` in base/base
`crates/consensus/derive/src/attributes/stateful.rs`). This task records the same values on L1 so
that a later `SystemConfig` update does not restore the 2s-block ones.

The validation file can be generated and signed before Denim activates. **Execute only after Denim
activates**, in an L1 block with a timestamp strictly after `DENIM_ACTIVATION_TIMESTAMP` from
`config/<network>/.env`: a transaction included in or before the L1 block the first Denim block
derives from would have its new values scaled a second time by the node. `make execute` refuses to
run until the latest L1 block timestamp is past the activation.

Replace `<network>` with the rollout network. Every command requires `TASK_NETWORK` explicitly. Run everything from this directory (`active/evm/tasks/2026-10-08-denim-system-config/`).

## 1. Install dependencies

```bash
make TASK_NETWORK=<network> deps
```

## 2. Review the network config

Open `config/<network>/.env` and confirm:

- `OLD_GAS_LIMIT` and `OLD_EIP1559_DENOMINATOR` are the live `SystemConfig` values. The script asserts
them before building the calls.
- `NEW_GAS_LIMIT` is `OLD_GAS_LIMIT / 10` and `NEW_EIP1559_DENOMINATOR` is
`OLD_EIP1559_DENOMINATOR * 10`. The script asserts both ratios.
- `DENIM_ACTIVATION_TIMESTAMP` matches the Denim activation registered in `ProtocolVersions`.

The EIP-1559 elasticity and the DA footprint gas scalar are read from the live config and must stay
unchanged.

## 3. Generate the validation file

```bash
make TASK_NETWORK=<network> gen-validation-cb
```

This writes `config/<network>/validations/base-signer.json`. Replace any generated
`<<ContractName>>` or `<<Summary>>` placeholders with reviewed contract names and state-change
descriptions. For any non-mainnet rollout, remove the generated `taskOriginConfig` and add this root
field:

```json
"skipTaskOriginValidation": true
```

Commit it and share `config/<network>/README.md` with signers.

## 4. Collect signatures and execute

`SystemConfig` is owned by the Base multisig directly, so the collected signatures execute the
transaction without a separate approval step. `execute` first checks that the latest L1 block
timestamp is past `DENIM_ACTIVATION_TIMESTAMP` and stops otherwise.

```bash
SIGNATURES=<concatenated base signatures> make TASK_NETWORK=<network> execute
```

After execution the script checks the new gas limit and denominator, and that elasticity and the DA
footprint gas scalar are unchanged. Set the README status to the execution transaction link.
60 changes: 60 additions & 0 deletions active/evm/tasks/2026-10-08-denim-system-config/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
include ../../../../Makefile
include $(REPO_ROOT)/Multisig.mk

# Denim rolls out across several networks from this one task directory, so the network is never
# defaulted. Select it on every command line:
# make TASK_NETWORK=zeronet gen-validation-cb
ifndef TASK_NETWORK
$(error TASK_NETWORK is required, e.g. make TASK_NETWORK=zeronet $(MAKECMDGOALS))
endif

PROJECT_DIR := $(abspath ../..)

include $(REPO_ROOT)/config/$(TASK_NETWORK).env
include config/$(TASK_NETWORK)/.env

SIGNER_TOOL_PATH := $(REPO_ROOT)/signer-tool
VALIDATIONS_DIR := $(CURDIR)/config/$(TASK_NETWORK)/validations
RPC_URL := $(L1_RPC_URL)
TASK_ORIGIN_DIR := $(CURDIR)/config/$(TASK_NETWORK)
SIGNATURE_DIR := $(CURDIR)/signatures/$(TASK_NETWORK)

TASK_DIR := tasks/2026-10-08-denim-system-config
SCRIPT_NAME := $(TASK_DIR)/script/UpdateDenimGasParams.s.sol:UpdateDenimGasParams

CB_SENDER = $(shell $(MISE_EXEC) cast call $(CB_MULTISIG) "getOwners()(address[])" --rpc-url $(L1_RPC_URL) | tr -d '[]' | cut -d',' -f1)

GAS_ENV = CB_MULTISIG=$(CB_MULTISIG) \
SYSTEM_CONFIG=$(SYSTEM_CONFIG) \
OLD_GAS_LIMIT=$(OLD_GAS_LIMIT) \
NEW_GAS_LIMIT=$(NEW_GAS_LIMIT) \
OLD_EIP1559_DENOMINATOR=$(OLD_EIP1559_DENOMINATOR) \
NEW_EIP1559_DENOMINATOR=$(NEW_EIP1559_DENOMINATOR)

##
# Validation file
##
# SystemConfig is owned by the Base multisig alone, so it is the executing Safe and there are no
# nested Safes to approve.
.PHONY: gen-validation-cb
gen-validation-cb: deps-signer-tool
$(call GEN_VALIDATION,$(SCRIPT_NAME),,$(CB_SENDER),base-signer.json,$(GAS_ENV))

##
# Execute
##
# Signing does not depend on the activation, but execution must land after it: in or before the L1
# block the first Denim block derives from, the node would scale the new values a second time. The
# transaction lands in a block after the latest one, so the latest L1 timestamp must be past it.
.PHONY: check-denim-active
check-denim-active:
$(call require_vars,check-denim-active,DENIM_ACTIVATION_TIMESTAMP L1_RPC_URL)
@latest=$$($(MISE_EXEC) cast block latest --field timestamp --rpc-url $(L1_RPC_URL)); \
if [ "$$latest" -le "$(DENIM_ACTIVATION_TIMESTAMP)" ]; then \
echo "Denim is not active: latest L1 block timestamp $$latest <= DENIM_ACTIVATION_TIMESTAMP $(DENIM_ACTIVATION_TIMESTAMP)" >&2; \
exit 1; \
fi

.PHONY: execute
execute: check-denim-active
export $(GAS_ENV); $(call MULTISIG_EXECUTE,$(SIGNATURES))
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# https://github.com/base/contracts/commits/releases/v8.3.0/
BASE_CONTRACTS_COMMIT=385f21a41f277d287db92fffe88dca41299162ea

# Denim (upgrade id 13) activation, set by 2026-10-07-denim-upgrade: 2026-10-14 18:00:00 UTC.
# date -u -r 1792000800
DENIM_ACTIVATION_TIMESTAMP=1792000800

# Live values verified against Zeronet on 2026-10-08.
OLD_GAS_LIMIT=1200000000
OLD_EIP1559_DENOMINATOR=100

# Values the node applies from the first Denim block (gas limit / 10, denominator x 10).
NEW_GAS_LIMIT=120000000
NEW_EIP1559_DENOMINATOR=1000
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Denim SystemConfig Gas Parameters

Status: [EXECUTED](https://hoodi.etherscan.io/tx/0x2bf7928e72e17a4657a3fd24e33907574881b63878ac04d0cfeaa5e7af880a5b)

## Description

Sets Zeronet's post-Denim gas parameters on `SystemConfig`:

- gas limit from `1,200,000,000` to `120,000,000`;
- EIP-1559 denominator from `100` to `1000`.

The node already applies these values from the first Denim block; this writes them to L1. Executes
after Denim activates on October 14, 2026 at 18:00 UTC.

## Target

| Contract | Address |
| -- | -- |
| `SystemConfig` | `0x0a111C7980152bDe41D71f48e2E1d8184f5f6187` |

## Sign

From the repository root:

```bash
make sign-task
```

Select this Zeronet task, sign, and send the signature to the facilitator.
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
{
"cmd": "CB_MULTISIG=0x856611ed7e07d83243b15e93f6321f2df6865852 SYSTEM_CONFIG=0x0a111c7980152bde41d71f48e2e1d8184f5f6187 OLD_GAS_LIMIT=1200000000 NEW_GAS_LIMIT=120000000 OLD_EIP1559_DENOMINATOR=100 NEW_EIP1559_DENOMINATOR=1000 mise exec -- forge script --rpc-url https://c3-chainproxy-eth-hoodi-full-dev.cbhq.net tasks/2026-10-08-denim-system-config/script/UpdateDenimGasParams.s.sol:UpdateDenimGasParams --sig sign(address[]) [] --sender 0x2c1475476B586d66a85bC65A5aB396BBbAa4f3aD",
"ledgerId": 1,
"rpcUrl": "https://c3-chainproxy-eth-hoodi-full-dev.cbhq.net",
"expectedDomainAndMessageHashes": {
"address": "0x856611eD7E07D83243b15E93f6321f2df6865852",
"domainHash": "0xc88eae2baaa4c8513a3d87913666de9463f106158aaf8be5cd31588215ccd5c4",
"messageHash": "0x5433f20de7f056f5c7420d66e94a06be3de603f9648f34f6eea7ef4038561b16"
},
"stateOverrides": [
{
"name": "CB Signer Safe - Zeronet",
"address": "0x856611eD7E07D83243b15E93f6321f2df6865852",
"overrides": [
{
"key": "0x0000000000000000000000000000000000000000000000000000000000000004",
"value": "0x0000000000000000000000000000000000000000000000000000000000000001",
"description": "Override the threshold to 1 so the transaction simulation can occur.",
"allowDifference": false
},
{
"key": "0x2b25a1a0b52252deb68a67f882255eacc6adbfa7143cee991048bf6da0e7c174",
"value": "0x0000000000000000000000000000000000000000000000000000000000000001",
"description": "Simulates an approval from msg.sender in order for the task simulation to succeed.",
"allowDifference": false
}
]
}
],
"stateChanges": [
{
"name": "System Config - Zeronet",
"address": "0x0a111C7980152bDe41D71f48e2E1d8184f5f6187",
"changes": [
{
"key": "0x0000000000000000000000000000000000000000000000000000000000000068",
"before": "0x00000000000000000000000000000000000c3c9d000005580000000047868c00",
"after": "0x00000000000000000000000000000000000c3c9d000005580000000007270e00",
"description": "Sets gasLimit from 1,200,000,000 to 120,000,000. basefeeScalar and blobbasefeeScalar are unchanged.",
"allowDifference": false
},
{
"key": "0x000000000000000000000000000000000000000000000000000000000000006a",
"before": "0x0000000000000000000000770000000000000000000000000000000f00000064",
"after": "0x0000000000000000000000770000000000000000000000000000000f000003e8",
"description": "Sets eip1559Denominator from 100 to 1000. eip1559Elasticity (15) and daFootprintGasScalar (119) are unchanged.",
"allowDifference": false
}
]
},
{
"name": "CB Signer Safe - Zeronet",
"address": "0x856611eD7E07D83243b15E93f6321f2df6865852",
"changes": [
{
"key": "0x0000000000000000000000000000000000000000000000000000000000000005",
"before": "0x0000000000000000000000000000000000000000000000000000000000000022",
"after": "0x0000000000000000000000000000000000000000000000000000000000000023",
"description": "Increments the nonce",
"allowDifference": false
}
]
}
],
"balanceChanges": [],
"skipTaskOriginValidation": true
}
Loading
Loading