Skip to content
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
21 changes: 21 additions & 0 deletions mainnet/2026-02-03-eip1559-denominator-increase/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Required: Git commit hash for https://github.com/ethereum-optimism/optimism
OP_COMMIT=d09c836f818c73ae139f60b717654c4e53712743

# Required: Git commit hash for https://github.com/base/contracts
BASE_CONTRACTS_COMMIT=9526d38b63be2ee10fc905dee60f0b2a0a17e89e

# Required: L1 SystemConfig proxy contract address
SYSTEM_CONFIG=0x73a79Fab69143498Ed3712e519A88a918e1f4072

# Required: Address of the Gnosis Safe that owns SystemConfig
OWNER_SAFE=0x14536667Cd30e52C0b458BaACcB9faDA7046E056

# Required: Address of a signer on OWNER_SAFE (used for simulation)
SENDER=0x1841CB3C2ce6870D0417844C817849da64E6e937

# Enable state diff recording for validation
RECORD_STATE_DIFF=true

# EIP-1559 Denominator: 50 -> 125 (2.5x increase)
FROM_DENOMINATOR=50
TO_DENOMINATOR=125
28 changes: 28 additions & 0 deletions mainnet/2026-02-03-eip1559-denominator-increase/FACILITATORS.md
Original file line number Diff line number Diff line change
@@ -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/2026-02-03-eip1559-denominator-increase
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
```
69 changes: 69 additions & 0 deletions mainnet/2026-02-03-eip1559-denominator-increase/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
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 = IncreaseEip1559DenominatorScript

# Validate required configuration before execution
.PHONY: validate-config
validate-config:
@test -n "$(OP_COMMIT)" -a "$(OP_COMMIT)" != "TODO" || (echo "OP_COMMIT required" && exit 1)
@test -n "$(BASE_CONTRACTS_COMMIT)" -a "$(BASE_CONTRACTS_COMMIT)" != "TODO" || (echo "BASE_CONTRACTS_COMMIT required" && exit 1)
@test -n "$(OWNER_SAFE)" || (echo "OWNER_SAFE required" && exit 1)
@test -n "$(SYSTEM_CONFIG)" || (echo "SYSTEM_CONFIG required" && exit 1)
@test -n "$(SENDER)" || (echo "SENDER required" && exit 1)
@test -n "$(FROM_DENOMINATOR)" -a "$(FROM_DENOMINATOR)" != "TODO" || (echo "FROM_DENOMINATOR required" && exit 1)
@test -n "$(TO_DENOMINATOR)" -a "$(TO_DENOMINATOR)" != "TODO" || (echo "TO_DENOMINATOR required" && exit 1)
@echo "Configuration validated successfully"

.PHONY: gen-validation
gen-validation: validate-config checkout-signer-tool run-script

.PHONY: run-script
run-script:
mkdir -p validations; \
cd $(SIGNER_TOOL_PATH); \
npm ci; \
bun run scripts/genValidationFile.ts --rpc-url $(RPC_URL) \
--workdir .. --forge-cmd 'NEW_DENOMINATOR=$(TO_DENOMINATOR) \
OLD_DENOMINATOR=$(FROM_DENOMINATOR) \
forge script --rpc-url $(RPC_URL) \
$(SCRIPT_NAME) --sig "sign(address[])" [] --sender $(SENDER)' --out ../validations/base-signer.json;

.PHONY: execute
execute: validate-config
NEW_DENOMINATOR=$(TO_DENOMINATOR) \
OLD_DENOMINATOR=$(FROM_DENOMINATOR) \
$(call MULTISIG_EXECUTE,$(SIGNATURES))

.PHONY: gen-validation-rollback
gen-validation-rollback: validate-config 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_DENOMINATOR=$(TO_DENOMINATOR) \
NEW_DENOMINATOR=$(FROM_DENOMINATOR) \
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: validate-config
OLD_DENOMINATOR=$(TO_DENOMINATOR) \
NEW_DENOMINATOR=$(FROM_DENOMINATOR) \
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
75 changes: 75 additions & 0 deletions mainnet/2026-02-03-eip1559-denominator-increase/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Increase EIP-1559 Denominator in L1 `SystemConfig`

Status: READY TO SIGN

## Executed Transactions

PENDING

## Description

We are increaseing the EIP-1559 Denominator to reduce the maximum rate of change for the base fee, and thus limit overall fee volatility.

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:

`IncreaseEip1559Denominator` -- This script will update the EIP-1559 denominator to 125 if invoked as part of the "upgrade" process, or revert to the old denominator of 50 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

```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 signatures 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`.
20 changes: 20 additions & 0 deletions mainnet/2026-02-03-eip1559-denominator-increase/foundry.toml
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// 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;
}

contract IncreaseEip1559DenominatorScript is MultisigScript {
address internal immutable OWNER_SAFE;
address internal immutable SYSTEM_CONFIG;

uint32 internal immutable DENOMINATOR;
uint32 internal immutable NEW_DENOMINATOR;
uint32 internal immutable ELASTICITY;

constructor() {
OWNER_SAFE = vm.envAddress("OWNER_SAFE");
SYSTEM_CONFIG = vm.envAddress("SYSTEM_CONFIG");

DENOMINATOR = uint32(vm.envUint("OLD_DENOMINATOR"));
NEW_DENOMINATOR = uint32(vm.envUint("NEW_DENOMINATOR"));

ELASTICITY = ISystemConfig(SYSTEM_CONFIG).eip1559Elasticity();
}

function _postCheck(Vm.AccountAccess[] memory, Simulation.Payload memory) internal view override {
vm.assertEq(ISystemConfig(SYSTEM_CONFIG).eip1559Denominator(), NEW_DENOMINATOR, "Denominator mismatch");
vm.assertEq(ISystemConfig(SYSTEM_CONFIG).eip1559Elasticity(), ELASTICITY, "Elasticity mismatch");
}

function _simulationOverrides() internal view override returns (Simulation.StateOverride[] memory _stateOverrides) {
if (DENOMINATOR != ISystemConfig(SYSTEM_CONFIG).eip1559Denominator()) {
// 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 one storage override for SystemConfig
Simulation.StateOverride[] memory stateOverrides = new Simulation.StateOverride[](1);
Simulation.StorageOverride[] memory storageOverrides = new Simulation.StorageOverride[](1);

// Load current packed EIP-1559 params (slot 0x6a) and replace only the lower 32 bits with DENOMINATOR
bytes32 eip1559SlotKey = bytes32(uint256(0x6a));
uint256 existingEip1559Word = uint256(vm.load(SYSTEM_CONFIG, eip1559SlotKey));
uint256 updatedEip1559Word = (existingEip1559Word & ~uint256(0xffffffff)) | uint256(DENOMINATOR);
storageOverrides[0] = Simulation.StorageOverride({key: eip1559SlotKey, value: bytes32(updatedEip1559Word)});

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[](1);

calls[0] = IMulticall3.Call3Value({
target: SYSTEM_CONFIG,
allowFailure: false,
callData: abi.encodeCall(ISystemConfig.setEIP1559Params, (NEW_DENOMINATOR, ELASTICITY)),
value: 0
});

return calls;
}

function _ownerSafe() internal view override returns (address) {
return OWNER_SAFE;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
{
"cmd": "OLD_DENOMINATOR=125 NEW_DENOMINATOR=50 SAFE_NONCE=103 forge script --rpc-url https://eth-mainnet.public.blastapi.io IncreaseEip1559DenominatorScript --sig sign(address[]) [] --sender 0x1841CB3C2ce6870D0417844C817849da64E6e937",
"ledgerId": 0,
"rpcUrl": "https://eth-mainnet.public.blastapi.io",
"expectedDomainAndMessageHashes": {
"address": "0x14536667Cd30e52C0b458BaACcB9faDA7046E056",
"domainHash": "0xf3474c66ee08325b410c3f442c878d01ec97dd55a415a307e9d7d2ea24336289",
"messageHash": "0x96f9aabc336c8752c76a513c4de4f28886f7d8757f132fc375edb6005a3a0876"
},
"stateOverrides": [
{
"name": "Incident Safe - Mainnet",
"address": "0x14536667cd30e52c0b458baaccb9fada7046e056",
"overrides": [
{
"key": "0x0000000000000000000000000000000000000000000000000000000000000004",
"value": "0x0000000000000000000000000000000000000000000000000000000000000001",
"description": "Override the threshold to 1 so the transaction simulation can occur.",
"allowDifference": false
},
{
"key": "0x0000000000000000000000000000000000000000000000000000000000000005",
"value": "0x0000000000000000000000000000000000000000000000000000000000000067",
"description": "Override the nonce to be our expected value after initial execution.",
"allowDifference": false
},
{
"key": "0x46a08474ac712a822d2c6035d1899c5d8c6e0032d6fb14e842f146f6083e44a9",
"value": "0x0000000000000000000000000000000000000000000000000000000000000001",
"description": "Simulates an approval from msg.sender in order for the task simulation to succeed.",
"allowDifference": false
}
]
},
{
"name": "System Config - Mainnet",
"address": "0x73a79fab69143498ed3712e519a88a918e1f4072",
"overrides": [
{
"key": "0x000000000000000000000000000000000000000000000000000000000000006a",
"value": "0x00000000000000000000008b000000000000000000000000000000060000007d",
"description": "Override EIP-1559 denominator to 125 (post-upgrade value) for rollback simulation",
"allowDifference": false
}
]
}
],
"stateChanges": [
{
"name": "Incident Safe - Mainnet",
"address": "0x14536667cd30e52c0b458baaccb9fada7046e056",
"changes": [
{
"key": "0x0000000000000000000000000000000000000000000000000000000000000005",
"before": "0x0000000000000000000000000000000000000000000000000000000000000067",
"after": "0x0000000000000000000000000000000000000000000000000000000000000068",
"description": "Increments the nonce",
"allowDifference": false
}
]
},
{
"name": "System Config - Mainnet",
"address": "0x73a79fab69143498ed3712e519a88a918e1f4072",
"changes": [
{
"key": "0x000000000000000000000000000000000000000000000000000000000000006a",
"before": "0x00000000000000000000008b000000000000000000000000000000060000007d",
"after": "0x00000000000000000000008b0000000000000000000000000000000600000032",
"description": "Updates EIP-1559 denominator from 125 to 50 (rollback)",
"allowDifference": false
}
]
}
],
"balanceChanges": []
}
Loading