Commit 9300db95 authored by Mark Tyneway's avatar Mark Tyneway Committed by GitHub

contracts-bedrock: ecotone gas config support (#10226)

* contracts-bedrock: ecotone gas config support

Updates the gas config on the `SystemConfig` to be ecotone first.
This resolves chain operator ux issues with setting the gas config,
rendering the additional tooling for calculating the encoded
scalar version obsolete. This version of the system config
is technically backwards compatible with pre-ecotone, but it
requires a follow up tx to call the old `setGasConfig` method.
The old gas config method was updated such that it cannot
be used to set ecotone style config to prevent footguns.
A new method `setGasConfigEcotone` should be used instead.

* tests: fix build

* config: fixup

* deploy-config: fixup

* chain-assertions: improve

* lint: fix

* scripts: remove overhead and scalar config

Reduces tech debt

* contracts-bedrock: fix build

* snapshots: update

* gas-snapshot: update

* contracts-bedrock: fix tests

* semver-lock: regenerate

* build: fix

* build: fix

* e2e: fix build

* config: fix test

* op-e2e: cleanup

Still support pre-ecotone tests

* test: fix

* kontrol: fixup

* op-e2e: turn on ecotone

* ecotone: fix test

* op-e2e: fix test

* op-e2e: fix failing test

* op-e2e: update tests

* deps: update

* kontrol: update

* semver-lock: update

* snapshots: update after version change

* typo: fix
Co-authored-by: default avatarMatt Solomon <matt@mattsolomon.dev>

---------
Co-authored-by: default avatarMatt Solomon <matt@mattsolomon.dev>
parent d2787077
...@@ -383,12 +383,6 @@ func (d *DeployConfig) Check() error { ...@@ -383,12 +383,6 @@ func (d *DeployConfig) Check() error {
if !d.SequencerFeeVaultWithdrawalNetwork.Valid() { if !d.SequencerFeeVaultWithdrawalNetwork.Valid() {
return fmt.Errorf("%w: SequencerFeeVaultWithdrawalNetwork can only be 0 (L1) or 1 (L2)", ErrInvalidDeployConfig) return fmt.Errorf("%w: SequencerFeeVaultWithdrawalNetwork can only be 0 (L1) or 1 (L2)", ErrInvalidDeployConfig)
} }
if d.GasPriceOracleOverhead == 0 {
log.Warn("GasPriceOracleOverhead is 0")
}
if d.GasPriceOracleScalar == 0 {
log.Warn("GasPriceOracleScalar is 0")
}
if d.GasPriceOracleBaseFeeScalar == 0 { if d.GasPriceOracleBaseFeeScalar == 0 {
log.Warn("GasPriceOracleBaseFeeScalar is 0") log.Warn("GasPriceOracleBaseFeeScalar is 0")
} }
...@@ -606,7 +600,8 @@ func (d *DeployConfig) InteropTime(genesisTime uint64) *uint64 { ...@@ -606,7 +600,8 @@ func (d *DeployConfig) InteropTime(genesisTime uint64) *uint64 {
return &v return &v
} }
// RollupConfig converts a DeployConfig to a rollup.Config // RollupConfig converts a DeployConfig to a rollup.Config. If Ecotone is active at genesis, the
// Overhead value is considered a noop.
func (d *DeployConfig) RollupConfig(l1StartBlock *types.Block, l2GenesisBlockHash common.Hash, l2GenesisBlockNumber uint64) (*rollup.Config, error) { func (d *DeployConfig) RollupConfig(l1StartBlock *types.Block, l2GenesisBlockHash common.Hash, l2GenesisBlockNumber uint64) (*rollup.Config, error) {
if d.OptimismPortalProxy == (common.Address{}) { if d.OptimismPortalProxy == (common.Address{}) {
return nil, errors.New("OptimismPortalProxy cannot be address(0)") return nil, errors.New("OptimismPortalProxy cannot be address(0)")
......
...@@ -700,12 +700,6 @@ func SystemConfig(batch *safe.Batch, implementations superchain.ImplementationLi ...@@ -700,12 +700,6 @@ func SystemConfig(batch *safe.Batch, implementations superchain.ImplementationLi
} }
if config != nil { if config != nil {
if gasPriceOracleOverhead.Uint64() != config.GasPriceOracleOverhead {
return fmt.Errorf("GasPriceOracleOverhead address doesn't match config")
}
if gasPriceOracleScalar.Uint64() != config.GasPriceOracleScalar {
return fmt.Errorf("GasPriceOracleScalar address doesn't match config")
}
if batcherHash != common.BytesToHash(config.BatchSenderAddress.Bytes()) { if batcherHash != common.BytesToHash(config.BatchSenderAddress.Bytes()) {
return fmt.Errorf("BatchSenderAddress address doesn't match config") return fmt.Errorf("BatchSenderAddress address doesn't match config")
} }
......
...@@ -74,7 +74,8 @@ func TestEcotoneNetworkUpgradeTransactions(gt *testing.T) { ...@@ -74,7 +74,8 @@ func TestEcotoneNetworkUpgradeTransactions(gt *testing.T) {
scalar, err := gasPriceOracle.Scalar(nil) scalar, err := gasPriceOracle.Scalar(nil)
require.NoError(t, err) require.NoError(t, err)
require.True(t, scalar.Cmp(big.NewInt(0)) > 0, "scalar must start non-zero") require.True(t, scalar.Cmp(big.NewInt(0)) > 0, "scalar must start non-zero")
require.True(t, scalar.Cmp(new(big.Int).SetUint64(dp.DeployConfig.GasPriceOracleScalar)) == 0, "must match deploy config") feeScalar := dp.DeployConfig.FeeScalar()
require.Equal(t, scalar, new(big.Int).SetBytes(feeScalar[:]), "must match deploy config")
// Get current implementations addresses (by slot) for L1Block + GasPriceOracle // Get current implementations addresses (by slot) for L1Block + GasPriceOracle
initialGasPriceOracleAddress, err := ethCl.StorageAt(context.Background(), predeploys.GasPriceOracleAddr, genesis.ImplementationSlot, nil) initialGasPriceOracleAddress, err := ethCl.StorageAt(context.Background(), predeploys.GasPriceOracleAddr, genesis.ImplementationSlot, nil)
...@@ -193,7 +194,7 @@ func TestEcotoneNetworkUpgradeTransactions(gt *testing.T) { ...@@ -193,7 +194,7 @@ func TestEcotoneNetworkUpgradeTransactions(gt *testing.T) {
// test if the migrated scalar matches the deploy config // test if the migrated scalar matches the deploy config
basefeeScalar, err := gasPriceOracle.BaseFeeScalar(nil) basefeeScalar, err := gasPriceOracle.BaseFeeScalar(nil)
require.NoError(t, err) require.NoError(t, err)
require.True(t, uint64(basefeeScalar) == dp.DeployConfig.GasPriceOracleScalar, "must match deploy config") require.Equal(t, uint64(basefeeScalar), dp.DeployConfig.GasPriceOracleScalar, "must match deploy config")
cost, err = gasPriceOracle.GetL1Fee(nil, []byte{0, 1, 2, 3, 4}) cost, err = gasPriceOracle.GetL1Fee(nil, []byte{0, 1, 2, 3, 4})
require.NoError(t, err) require.NoError(t, err)
......
This diff is collapsed.
...@@ -14,6 +14,7 @@ import ( ...@@ -14,6 +14,7 @@ import (
"github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum-optimism/optimism/op-service/predeploys"
"github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/ethclient"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
...@@ -23,6 +24,12 @@ func TestCustomGasToken(t *testing.T) { ...@@ -23,6 +24,12 @@ func TestCustomGasToken(t *testing.T) {
InitParallel(t, SkipOnFPAC) // Custom Gas Token feature is not yet compatible with FPAC InitParallel(t, SkipOnFPAC) // Custom Gas Token feature is not yet compatible with FPAC
cfg := DefaultSystemConfig(t) cfg := DefaultSystemConfig(t)
offset := hexutil.Uint64(0)
cfg.DeployConfig.L2GenesisRegolithTimeOffset = &offset
cfg.DeployConfig.L1CancunTimeOffset = &offset
cfg.DeployConfig.L2GenesisCanyonTimeOffset = &offset
cfg.DeployConfig.L2GenesisDeltaTimeOffset = &offset
cfg.DeployConfig.L2GenesisEcotoneTimeOffset = &offset
sys, err := cfg.Start(t) sys, err := cfg.Start(t)
require.NoError(t, err, "Error starting up system") require.NoError(t, err, "Error starting up system")
...@@ -324,9 +331,9 @@ func setCustomGasToken(t *testing.T, cfg SystemConfig, sys *System, cgtAddress c ...@@ -324,9 +331,9 @@ func setCustomGasToken(t *testing.T, cfg SystemConfig, sys *System, cgtAddress c
// Get existing parameters from SystemConfigProxy contract // Get existing parameters from SystemConfigProxy contract
owner, err := systemConfig.Owner(&bind.CallOpts{}) owner, err := systemConfig.Owner(&bind.CallOpts{})
require.NoError(t, err) require.NoError(t, err)
overhead, err := systemConfig.Overhead(&bind.CallOpts{}) basefeeScalar, err := systemConfig.BasefeeScalar(&bind.CallOpts{})
require.NoError(t, err) require.NoError(t, err)
scalar, err := systemConfig.Scalar(&bind.CallOpts{}) blobbasefeeScalar, err := systemConfig.BlobbasefeeScalar(&bind.CallOpts{})
require.NoError(t, err) require.NoError(t, err)
batcherHash, err := systemConfig.BatcherHash(&bind.CallOpts{}) batcherHash, err := systemConfig.BatcherHash(&bind.CallOpts{})
require.NoError(t, err) require.NoError(t, err)
...@@ -406,8 +413,8 @@ func setCustomGasToken(t *testing.T, cfg SystemConfig, sys *System, cgtAddress c ...@@ -406,8 +413,8 @@ func setCustomGasToken(t *testing.T, cfg SystemConfig, sys *System, cgtAddress c
// Reinitialise with existing initializer values but with custom gas token set // Reinitialise with existing initializer values but with custom gas token set
tx, err = systemConfig.Initialize(deployerOpts, owner, tx, err = systemConfig.Initialize(deployerOpts, owner,
overhead, basefeeScalar,
scalar, blobbasefeeScalar,
batcherHash, batcherHash,
gasLimit, gasLimit,
unsafeBlockSigner, unsafeBlockSigner,
......
...@@ -1266,7 +1266,8 @@ func testFees(t *testing.T, cfg SystemConfig) { ...@@ -1266,7 +1266,8 @@ func testFees(t *testing.T, cfg SystemConfig) {
scalar, err := gpoContract.Scalar(&bind.CallOpts{}) scalar, err := gpoContract.Scalar(&bind.CallOpts{})
require.Nil(t, err, "reading gpo scalar") require.Nil(t, err, "reading gpo scalar")
require.Equal(t, scalar.Uint64(), cfg.DeployConfig.GasPriceOracleScalar, "wrong gpo scalar") feeScalar := cfg.DeployConfig.FeeScalar()
require.Equal(t, scalar, new(big.Int).SetBytes(feeScalar[:]), "wrong gpo scalar")
} else { } else {
_, err := gpoContract.Overhead(&bind.CallOpts{}) _, err := gpoContract.Overhead(&bind.CallOpts{})
require.ErrorContains(t, err, "deprecated") require.ErrorContains(t, err, "deprecated")
......
...@@ -43,8 +43,9 @@ func TestGasPriceOracleFeeUpdates(t *testing.T) { ...@@ -43,8 +43,9 @@ func TestGasPriceOracleFeeUpdates(t *testing.T) {
InitParallel(t) InitParallel(t)
// Define our values to set in the GasPriceOracle (we set them high to see if it can lock L2 or stop bindings // Define our values to set in the GasPriceOracle (we set them high to see if it can lock L2 or stop bindings
// from updating the prices once again. // from updating the prices once again.
overheadValue := abi.MaxUint256 overheadValue := new(big.Int).Set(abi.MaxUint256)
scalarValue := abi.MaxUint256 // Ensure the most significant byte is 0x00
scalarValue := new(big.Int).Rsh(new(big.Int).Set(abi.MaxUint256), 8)
var cancel context.CancelFunc var cancel context.CancelFunc
// Create our system configuration for L1/L2 and start it // Create our system configuration for L1/L2 and start it
......
...@@ -25,7 +25,6 @@ var ( ...@@ -25,7 +25,6 @@ var (
ErrGenesisHashesSame = errors.New("achievement get! rollup inception: L1 and L2 genesis cannot be the same") ErrGenesisHashesSame = errors.New("achievement get! rollup inception: L1 and L2 genesis cannot be the same")
ErrMissingGenesisL2Time = errors.New("missing L2 genesis time") ErrMissingGenesisL2Time = errors.New("missing L2 genesis time")
ErrMissingBatcherAddr = errors.New("missing genesis system config batcher address") ErrMissingBatcherAddr = errors.New("missing genesis system config batcher address")
ErrMissingOverhead = errors.New("missing genesis system config overhead")
ErrMissingScalar = errors.New("missing genesis system config scalar") ErrMissingScalar = errors.New("missing genesis system config scalar")
ErrMissingGasLimit = errors.New("missing genesis system config gas limit") ErrMissingGasLimit = errors.New("missing genesis system config gas limit")
ErrMissingBatchInboxAddress = errors.New("missing batch inbox address") ErrMissingBatchInboxAddress = errors.New("missing batch inbox address")
...@@ -278,9 +277,6 @@ func (cfg *Config) Check() error { ...@@ -278,9 +277,6 @@ func (cfg *Config) Check() error {
if cfg.Genesis.SystemConfig.BatcherAddr == (common.Address{}) { if cfg.Genesis.SystemConfig.BatcherAddr == (common.Address{}) {
return ErrMissingBatcherAddr return ErrMissingBatcherAddr
} }
if cfg.Genesis.SystemConfig.Overhead == (eth.Bytes32{}) {
return ErrMissingOverhead
}
if cfg.Genesis.SystemConfig.Scalar == (eth.Bytes32{}) { if cfg.Genesis.SystemConfig.Scalar == (eth.Bytes32{}) {
return ErrMissingScalar return ErrMissingScalar
} }
......
...@@ -405,11 +405,6 @@ func TestConfig_Check(t *testing.T) { ...@@ -405,11 +405,6 @@ func TestConfig_Check(t *testing.T) {
modifier: func(cfg *Config) { cfg.Genesis.SystemConfig.BatcherAddr = common.Address{} }, modifier: func(cfg *Config) { cfg.Genesis.SystemConfig.BatcherAddr = common.Address{} },
expectedErr: ErrMissingBatcherAddr, expectedErr: ErrMissingBatcherAddr,
}, },
{
name: "NoOverhead",
modifier: func(cfg *Config) { cfg.Genesis.SystemConfig.Overhead = eth.Bytes32{} },
expectedErr: ErrMissingOverhead,
},
{ {
name: "NoScalar", name: "NoScalar",
modifier: func(cfg *Config) { cfg.Genesis.SystemConfig.Scalar = eth.Bytes32{} }, modifier: func(cfg *Config) { cfg.Genesis.SystemConfig.Scalar = eth.Bytes32{} },
......
GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_0() (gas: 369357) GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_0() (gas: 369380)
GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_1() (gas: 2967497) GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_1() (gas: 2967520)
GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_0() (gas: 561969) GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_0() (gas: 561992)
GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_1() (gas: 4074012) GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_1() (gas: 4074035)
GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_0() (gas: 466924) GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_0() (gas: 466947)
GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_1() (gas: 3512606) GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_1() (gas: 3512629)
GasBenchMark_L1StandardBridge_Finalize:test_finalizeETHWithdrawal_benchmark() (gas: 72629) GasBenchMark_L1StandardBridge_Finalize:test_finalizeETHWithdrawal_benchmark() (gas: 72629)
GasBenchMark_L2OutputOracle:test_proposeL2Output_benchmark() (gas: 92973) GasBenchMark_L2OutputOracle:test_proposeL2Output_benchmark() (gas: 92973)
GasBenchMark_OptimismPortal:test_depositTransaction_benchmark() (gas: 68410) GasBenchMark_OptimismPortal:test_depositTransaction_benchmark() (gas: 68433)
GasBenchMark_OptimismPortal:test_depositTransaction_benchmark_1() (gas: 68880) GasBenchMark_OptimismPortal:test_depositTransaction_benchmark_1() (gas: 68903)
GasBenchMark_OptimismPortal:test_proveWithdrawalTransaction_benchmark() (gas: 155618) GasBenchMark_OptimismPortal:test_proveWithdrawalTransaction_benchmark() (gas: 155618)
\ No newline at end of file
...@@ -35,6 +35,8 @@ ...@@ -35,6 +35,8 @@
"l2GenesisBlockBaseFeePerGas": "0x1", "l2GenesisBlockBaseFeePerGas": "0x1",
"gasPriceOracleOverhead": 2100, "gasPriceOracleOverhead": 2100,
"gasPriceOracleScalar": 1000000, "gasPriceOracleScalar": 1000000,
"gasPriceOracleBaseFeeScalar": 1368,
"gasPriceOracleBlobBaseFeeScalar": 810949,
"enableGovernance": true, "enableGovernance": true,
"governanceTokenSymbol": "OP", "governanceTokenSymbol": "OP",
"governanceTokenName": "Optimism", "governanceTokenName": "Optimism",
......
...@@ -16,8 +16,6 @@ ...@@ -16,8 +16,6 @@
"l2OutputOracleSubmissionInterval": 6, "l2OutputOracleSubmissionInterval": 6,
"l2OutputOracleStartingTimestamp": 1, "l2OutputOracleStartingTimestamp": 1,
"l2OutputOracleStartingBlockNumber": 1, "l2OutputOracleStartingBlockNumber": 1,
"gasPriceOracleOverhead": 2100,
"gasPriceOracleScalar": 1000000,
"gasPriceOracleBaseFeeScalar": 1368, "gasPriceOracleBaseFeeScalar": 1368,
"gasPriceOracleBlobBaseFeeScalar": 810949, "gasPriceOracleBlobBaseFeeScalar": 810949,
"l2OutputOracleProposer": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", "l2OutputOracleProposer": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8",
......
...@@ -34,8 +34,6 @@ ...@@ -34,8 +34,6 @@
"governanceTokenOwner": "0x858F0751ef8B4067f0d2668C076BDB50a8549fbF", "governanceTokenOwner": "0x858F0751ef8B4067f0d2668C076BDB50a8549fbF",
"l2GenesisBlockGasLimit": "0x17D7840", "l2GenesisBlockGasLimit": "0x17D7840",
"l2GenesisBlockBaseFeePerGas": "0x3b9aca00", "l2GenesisBlockBaseFeePerGas": "0x3b9aca00",
"gasPriceOracleOverhead": 2100,
"gasPriceOracleScalar": 1000000,
"eip1559Denominator": 50, "eip1559Denominator": 50,
"eip1559Elasticity": 10, "eip1559Elasticity": 10,
"systemConfigStartBlock": 8364212, "systemConfigStartBlock": 8364212,
......
...@@ -34,8 +34,6 @@ ...@@ -34,8 +34,6 @@
"governanceTokenOwner": "0x5C4e7Ba1E219E47948e6e3F55019A647bA501005", "governanceTokenOwner": "0x5C4e7Ba1E219E47948e6e3F55019A647bA501005",
"l2GenesisBlockGasLimit": "0x1c9c380", "l2GenesisBlockGasLimit": "0x1c9c380",
"l2GenesisBlockBaseFeePerGas": "0x3b9aca00", "l2GenesisBlockBaseFeePerGas": "0x3b9aca00",
"gasPriceOracleOverhead": 0,
"gasPriceOracleScalar": 0,
"gasPriceOracleBaseFeeScalar": 1368, "gasPriceOracleBaseFeeScalar": 1368,
"gasPriceOracleBlobBaseFeeScalar": 810949, "gasPriceOracleBlobBaseFeeScalar": 810949,
"eip1559Denominator": 50, "eip1559Denominator": 50,
......
...@@ -57,8 +57,6 @@ ...@@ -57,8 +57,6 @@
"l1ERC721BridgeProxy": "0x0000000000000000000000000000000000000000", "l1ERC721BridgeProxy": "0x0000000000000000000000000000000000000000",
"systemConfigProxy": "0x0000000000000000000000000000000000000000", "systemConfigProxy": "0x0000000000000000000000000000000000000000",
"optimismPortalProxy": "0x0000000000000000000000000000000000000000", "optimismPortalProxy": "0x0000000000000000000000000000000000000000",
"gasPriceOracleOverhead": 188,
"gasPriceOracleScalar": 684000,
"enableGovernance": true, "enableGovernance": true,
"governanceTokenSymbol": "OP", "governanceTokenSymbol": "OP",
"governanceTokenName": "Optimism", "governanceTokenName": "Optimism",
......
...@@ -28,8 +28,6 @@ ...@@ -28,8 +28,6 @@
"baseFeeVaultWithdrawalNetwork": 0, "baseFeeVaultWithdrawalNetwork": 0,
"l1FeeVaultWithdrawalNetwork": 0, "l1FeeVaultWithdrawalNetwork": 0,
"sequencerFeeVaultWithdrawalNetwork": 0, "sequencerFeeVaultWithdrawalNetwork": 0,
"gasPriceOracleOverhead": 188,
"gasPriceOracleScalar": 684000,
"enableGovernance": true, "enableGovernance": true,
"governanceTokenSymbol": "OP", "governanceTokenSymbol": "OP",
"governanceTokenName": "Optimism", "governanceTokenName": "Optimism",
......
...@@ -71,11 +71,12 @@ library ChainAssertions { ...@@ -71,11 +71,12 @@ library ChainAssertions {
if (_isProxy) { if (_isProxy) {
require(config.owner() == _cfg.finalSystemOwner()); require(config.owner() == _cfg.finalSystemOwner());
require(config.overhead() == _cfg.gasPriceOracleOverhead()); require(config.basefeeScalar() == _cfg.basefeeScalar());
require(config.scalar() == _cfg.gasPriceOracleScalar()); require(config.blobbasefeeScalar() == _cfg.blobbasefeeScalar());
require(config.batcherHash() == bytes32(uint256(uint160(_cfg.batchSenderAddress())))); require(config.batcherHash() == bytes32(uint256(uint160(_cfg.batchSenderAddress()))));
require(config.gasLimit() == uint64(_cfg.l2GenesisBlockGasLimit())); require(config.gasLimit() == uint64(_cfg.l2GenesisBlockGasLimit()));
require(config.unsafeBlockSigner() == _cfg.p2pSequencerAddress()); require(config.unsafeBlockSigner() == _cfg.p2pSequencerAddress());
require(config.scalar() >> 248 == 1);
// Check _config // Check _config
ResourceMetering.ResourceConfig memory rconfig = Constants.DEFAULT_RESOURCE_CONFIG(); ResourceMetering.ResourceConfig memory rconfig = Constants.DEFAULT_RESOURCE_CONFIG();
require(resourceConfig.maxResourceLimit == rconfig.maxResourceLimit); require(resourceConfig.maxResourceLimit == rconfig.maxResourceLimit);
...@@ -98,7 +99,9 @@ library ChainAssertions { ...@@ -98,7 +99,9 @@ library ChainAssertions {
} else { } else {
require(config.owner() == address(0xdead)); require(config.owner() == address(0xdead));
require(config.overhead() == 0); require(config.overhead() == 0);
require(config.scalar() == 0); require(config.scalar() == uint256(0x01) << 248); // version 1
require(config.basefeeScalar() == 0);
require(config.blobbasefeeScalar() == 0);
require(config.batcherHash() == bytes32(0)); require(config.batcherHash() == bytes32(0));
require(config.gasLimit() == 1); require(config.gasLimit() == 1);
require(config.unsafeBlockSigner() == address(0)); require(config.unsafeBlockSigner() == address(0));
......
...@@ -985,8 +985,8 @@ contract Deploy is Deployer { ...@@ -985,8 +985,8 @@ contract Deploy is Deployer {
SystemConfig.initialize, SystemConfig.initialize,
( (
cfg.finalSystemOwner(), cfg.finalSystemOwner(),
cfg.gasPriceOracleOverhead(), cfg.basefeeScalar(),
cfg.gasPriceOracleScalar(), cfg.blobbasefeeScalar(),
batcherHash, batcherHash,
uint64(cfg.l2GenesisBlockGasLimit()), uint64(cfg.l2GenesisBlockGasLimit()),
cfg.p2pSequencerAddress(), cfg.p2pSequencerAddress(),
......
...@@ -46,8 +46,8 @@ contract DeployConfig is Script { ...@@ -46,8 +46,8 @@ contract DeployConfig is Script {
string public governanceTokenSymbol; string public governanceTokenSymbol;
address public governanceTokenOwner; address public governanceTokenOwner;
uint256 public l2GenesisBlockGasLimit; uint256 public l2GenesisBlockGasLimit;
uint256 public gasPriceOracleOverhead; uint32 public basefeeScalar;
uint256 public gasPriceOracleScalar; uint32 public blobbasefeeScalar;
bool public enableGovernance; bool public enableGovernance;
uint256 public eip1559Denominator; uint256 public eip1559Denominator;
uint256 public eip1559Elasticity; uint256 public eip1559Elasticity;
...@@ -119,8 +119,9 @@ contract DeployConfig is Script { ...@@ -119,8 +119,9 @@ contract DeployConfig is Script {
governanceTokenSymbol = stdJson.readString(_json, "$.governanceTokenSymbol"); governanceTokenSymbol = stdJson.readString(_json, "$.governanceTokenSymbol");
governanceTokenOwner = stdJson.readAddress(_json, "$.governanceTokenOwner"); governanceTokenOwner = stdJson.readAddress(_json, "$.governanceTokenOwner");
l2GenesisBlockGasLimit = stdJson.readUint(_json, "$.l2GenesisBlockGasLimit"); l2GenesisBlockGasLimit = stdJson.readUint(_json, "$.l2GenesisBlockGasLimit");
gasPriceOracleOverhead = stdJson.readUint(_json, "$.gasPriceOracleOverhead"); basefeeScalar = uint32(_readOr(_json, "$.gasPriceOracleBaseFeeScalar", 1368));
gasPriceOracleScalar = stdJson.readUint(_json, "$.gasPriceOracleScalar"); blobbasefeeScalar = uint32(_readOr(_json, "$.gasPriceOracleBlobBaseFeeScalar", 810949));
enableGovernance = stdJson.readBool(_json, "$.enableGovernance"); enableGovernance = stdJson.readBool(_json, "$.enableGovernance");
eip1559Denominator = stdJson.readUint(_json, "$.eip1559Denominator"); eip1559Denominator = stdJson.readUint(_json, "$.eip1559Denominator");
eip1559Elasticity = stdJson.readUint(_json, "$.eip1559Elasticity"); eip1559Elasticity = stdJson.readUint(_json, "$.eip1559Elasticity");
......
...@@ -9,6 +9,7 @@ import ( ...@@ -9,6 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/cannon/mipsevm" "github.com/ethereum-optimism/optimism/cannon/mipsevm"
"github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain" "github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum-optimism/optimism/op-service/predeploys"
"github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
...@@ -35,6 +36,8 @@ var ( ...@@ -35,6 +36,8 @@ var (
{Type: fixedBytes}, {Type: fixedBytes},
} }
uint32Type, _ = abi.NewType("uint32", "", nil)
// Decoded nonce tuple (nonce, version) // Decoded nonce tuple (nonce, version)
decodedNonce, _ = abi.NewType("tuple", "DecodedNonce", []abi.ArgumentMarshaling{ decodedNonce, _ = abi.NewType("tuple", "DecodedNonce", []abi.ArgumentMarshaling{
{Name: "nonce", Type: "uint256"}, {Name: "nonce", Type: "uint256"},
...@@ -44,6 +47,12 @@ var ( ...@@ -44,6 +47,12 @@ var (
{Name: "encodedNonce", Type: decodedNonce}, {Name: "encodedNonce", Type: decodedNonce},
} }
// Decoded ecotone scalars (uint32, uint32)
decodedScalars = abi.Arguments{
{Name: "basefeeScalar", Type: uint32Type},
{Name: "blobbasefeeScalar", Type: uint32Type},
}
// WithdrawalHash slot tuple (bytes32, bytes32) // WithdrawalHash slot tuple (bytes32, bytes32)
withdrawalSlot, _ = abi.NewType("tuple", "SlotHash", []abi.ArgumentMarshaling{ withdrawalSlot, _ = abi.NewType("tuple", "SlotHash", []abi.ArgumentMarshaling{
{Name: "withdrawalHash", Type: "bytes32"}, {Name: "withdrawalHash", Type: "bytes32"},
...@@ -361,6 +370,25 @@ func DiffTestUtils() { ...@@ -361,6 +370,25 @@ func DiffTestUtils() {
packed, err := cannonMemoryProofArgs.Pack(&output) packed, err := cannonMemoryProofArgs.Pack(&output)
checkErr(err, "Error encoding output") checkErr(err, "Error encoding output")
fmt.Print(hexutil.Encode(packed[32:])) fmt.Print(hexutil.Encode(packed[32:]))
case "encodeScalarEcotone":
basefeeScalar, err := strconv.ParseUint(args[1], 10, 32)
checkErr(err, "Error decocding basefeeScalar")
blobbasefeeScalar, err := strconv.ParseUint(args[2], 10, 32)
checkErr(err, "Error decocding blobbasefeeScalar")
encoded := eth.EncodeScalar(eth.EcotoneScalars{
BaseFeeScalar: uint32(basefeeScalar),
BlobBaseFeeScalar: uint32(blobbasefeeScalar),
})
fmt.Print(hexutil.Encode(encoded[:]))
case "decodeScalarEcotone":
scalar := common.HexToHash(args[1])
scalars, err := eth.DecodeScalar([32]byte(scalar[:]))
checkErr(err, "Error decoding scalar")
packed, err := decodedScalars.Pack(scalars.BaseFeeScalar, scalars.BlobBaseFeeScalar)
checkErr(err, "Error encoding output")
fmt.Print(hexutil.Encode(packed))
default: default:
panic(fmt.Errorf("Unknown command: %s", args[0])) panic(fmt.Errorf("Unknown command: %s", args[0]))
} }
......
...@@ -48,8 +48,8 @@ ...@@ -48,8 +48,8 @@
"sourceCodeHash": "0xd6a894e371c2c7182b5960c507491f81c3775dda0efedd29475f7c30ca07b004" "sourceCodeHash": "0xd6a894e371c2c7182b5960c507491f81c3775dda0efedd29475f7c30ca07b004"
}, },
"src/L1/SystemConfig.sol": { "src/L1/SystemConfig.sol": {
"initCodeHash": "0xe937c5747e42d6701ff3fbb10471302288fa765fb40cbd9822e22547a42dfa25", "initCodeHash": "0x6160c9c96d0972e0761ab3b9d4f6d1b8543288c4c3aea9e132008a40e4c5d202",
"sourceCodeHash": "0x9fb21393eb206f94bdf7e034c667535c415b7de93a1355058626d1c9e8abbff5" "sourceCodeHash": "0xd27df6e227cc4728471641aec25a1fe6f79a12ce96d3ce6c1774d9411a54133e"
}, },
"src/L2/BaseFeeVault.sol": { "src/L2/BaseFeeVault.sol": {
"initCodeHash": "0x2744d34573be83206d1b75d049d18a7bb37f9058e68c0803e5008c46b0dc2474", "initCodeHash": "0x2744d34573be83206d1b75d049d18a7bb37f9058e68c0803e5008c46b0dc2474",
......
...@@ -134,6 +134,19 @@ ...@@ -134,6 +134,19 @@
"stateMutability": "view", "stateMutability": "view",
"type": "function" "type": "function"
}, },
{
"inputs": [],
"name": "basefeeScalar",
"outputs": [
{
"internalType": "uint32",
"name": "",
"type": "uint32"
}
],
"stateMutability": "view",
"type": "function"
},
{ {
"inputs": [], "inputs": [],
"name": "batchInbox", "name": "batchInbox",
...@@ -160,6 +173,19 @@ ...@@ -160,6 +173,19 @@
"stateMutability": "view", "stateMutability": "view",
"type": "function" "type": "function"
}, },
{
"inputs": [],
"name": "blobbasefeeScalar",
"outputs": [
{
"internalType": "uint32",
"name": "",
"type": "uint32"
}
],
"stateMutability": "view",
"type": "function"
},
{ {
"inputs": [], "inputs": [],
"name": "disputeGameFactory", "name": "disputeGameFactory",
...@@ -238,14 +264,14 @@ ...@@ -238,14 +264,14 @@
"type": "address" "type": "address"
}, },
{ {
"internalType": "uint256", "internalType": "uint32",
"name": "_overhead", "name": "_basefeeScalar",
"type": "uint256" "type": "uint32"
}, },
{ {
"internalType": "uint256", "internalType": "uint32",
"name": "_scalar", "name": "_blobbasefeeScalar",
"type": "uint256" "type": "uint32"
}, },
{ {
"internalType": "bytes32", "internalType": "bytes32",
...@@ -578,6 +604,24 @@ ...@@ -578,6 +604,24 @@
"stateMutability": "nonpayable", "stateMutability": "nonpayable",
"type": "function" "type": "function"
}, },
{
"inputs": [
{
"internalType": "uint32",
"name": "_basefeeScalar",
"type": "uint32"
},
{
"internalType": "uint32",
"name": "_blobbasefeeScalar",
"type": "uint32"
}
],
"name": "setGasConfigEcotone",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{ {
"inputs": [ "inputs": [
{ {
......
...@@ -62,6 +62,20 @@ ...@@ -62,6 +62,20 @@
"slot": "104", "slot": "104",
"type": "uint64" "type": "uint64"
}, },
{
"bytes": "4",
"label": "basefeeScalar",
"offset": 8,
"slot": "104",
"type": "uint32"
},
{
"bytes": "4",
"label": "blobbasefeeScalar",
"offset": 12,
"slot": "104",
"type": "uint32"
},
{ {
"bytes": "32", "bytes": "32",
"label": "_resourceConfig", "label": "_resourceConfig",
......
...@@ -90,9 +90,12 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken { ...@@ -90,9 +90,12 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken {
uint64 internal constant MAX_GAS_LIMIT = 200_000_000; uint64 internal constant MAX_GAS_LIMIT = 200_000_000;
/// @notice Fixed L2 gas overhead. Used as part of the L2 fee calculation. /// @notice Fixed L2 gas overhead. Used as part of the L2 fee calculation.
/// Deprecated since the Ecotone network upgrade
uint256 public overhead; uint256 public overhead;
/// @notice Dynamic L2 gas overhead. Used as part of the L2 fee calculation. /// @notice Dynamic L2 gas overhead. Used as part of the L2 fee calculation.
/// The most significant byte is used to determine the version since the
/// Ecotone network upgrade.
uint256 public scalar; uint256 public scalar;
/// @notice Identifier for the batcher. /// @notice Identifier for the batcher.
...@@ -103,6 +106,12 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken { ...@@ -103,6 +106,12 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken {
/// @notice L2 block gas limit. /// @notice L2 block gas limit.
uint64 public gasLimit; uint64 public gasLimit;
/// @notice Basefee scalar value. Part of the L2 fee calculation since the Ecotone network upgrade.
uint32 public basefeeScalar;
/// @notice Blobbasefee scalar value. Part of the L2 fee calculation since the Ecotone network upgrade.
uint32 public blobbasefeeScalar;
/// @notice The configuration for the deposit fee market. /// @notice The configuration for the deposit fee market.
/// Used by the OptimismPortal to meter the cost of buying L2 gas on L1. /// Used by the OptimismPortal to meter the cost of buying L2 gas on L1.
/// Set as internal with a getter so that the struct is returned instead of a tuple. /// Set as internal with a getter so that the struct is returned instead of a tuple.
...@@ -115,8 +124,8 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken { ...@@ -115,8 +124,8 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken {
event ConfigUpdate(uint256 indexed version, UpdateType indexed updateType, bytes data); event ConfigUpdate(uint256 indexed version, UpdateType indexed updateType, bytes data);
/// @notice Semantic version. /// @notice Semantic version.
/// @custom:semver 2.2.0 /// @custom:semver 2.3.0-beta.1
string public constant version = "2.2.0"; string public constant version = "2.3.0-beta.1";
/// @notice Constructs the SystemConfig contract. Cannot set /// @notice Constructs the SystemConfig contract. Cannot set
/// the owner to `address(0)` due to the Ownable contract's /// the owner to `address(0)` due to the Ownable contract's
...@@ -127,8 +136,8 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken { ...@@ -127,8 +136,8 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken {
Storage.setUint(START_BLOCK_SLOT, type(uint256).max); Storage.setUint(START_BLOCK_SLOT, type(uint256).max);
initialize({ initialize({
_owner: address(0xdEaD), _owner: address(0xdEaD),
_overhead: 0, _basefeeScalar: 0,
_scalar: 0, _blobbasefeeScalar: 0,
_batcherHash: bytes32(0), _batcherHash: bytes32(0),
_gasLimit: 1, _gasLimit: 1,
_unsafeBlockSigner: address(0), _unsafeBlockSigner: address(0),
...@@ -156,8 +165,8 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken { ...@@ -156,8 +165,8 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken {
/// @notice Initializer. /// @notice Initializer.
/// The resource config must be set before the require check. /// The resource config must be set before the require check.
/// @param _owner Initial owner of the contract. /// @param _owner Initial owner of the contract.
/// @param _overhead Initial overhead value. /// @param _basefeeScalar Initial basefee scalar value.
/// @param _scalar Initial scalar value. /// @param _blobbasefeeScalar Initial blobbasefee scalar value.
/// @param _batcherHash Initial batcher hash. /// @param _batcherHash Initial batcher hash.
/// @param _gasLimit Initial gas limit. /// @param _gasLimit Initial gas limit.
/// @param _unsafeBlockSigner Initial unsafe block signer address. /// @param _unsafeBlockSigner Initial unsafe block signer address.
...@@ -167,8 +176,8 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken { ...@@ -167,8 +176,8 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken {
/// @param _addresses Set of L1 contract addresses. These should be the proxies. /// @param _addresses Set of L1 contract addresses. These should be the proxies.
function initialize( function initialize(
address _owner, address _owner,
uint256 _overhead, uint32 _basefeeScalar,
uint256 _scalar, uint32 _blobbasefeeScalar,
bytes32 _batcherHash, bytes32 _batcherHash,
uint64 _gasLimit, uint64 _gasLimit,
address _unsafeBlockSigner, address _unsafeBlockSigner,
...@@ -184,7 +193,7 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken { ...@@ -184,7 +193,7 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken {
// These are set in ascending order of their UpdateTypes. // These are set in ascending order of their UpdateTypes.
_setBatcherHash(_batcherHash); _setBatcherHash(_batcherHash);
_setGasConfig({ _overhead: _overhead, _scalar: _scalar }); _setGasConfigEcotone({ _basefeeScalar: _basefeeScalar, _blobbasefeeScalar: _blobbasefeeScalar });
_setGasLimit(_gasLimit); _setGasLimit(_gasLimit);
Storage.setAddress(UNSAFE_BLOCK_SIGNER_SLOT, _unsafeBlockSigner); Storage.setAddress(UNSAFE_BLOCK_SIGNER_SLOT, _unsafeBlockSigner);
...@@ -346,6 +355,7 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken { ...@@ -346,6 +355,7 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken {
} }
/// @notice Updates gas config. Can only be called by the owner. /// @notice Updates gas config. Can only be called by the owner.
/// Deprecated in favor of setGasConfigEcotone since the Ecotone upgrade.
/// @param _overhead New overhead value. /// @param _overhead New overhead value.
/// @param _scalar New scalar value. /// @param _scalar New scalar value.
function setGasConfig(uint256 _overhead, uint256 _scalar) external onlyOwner { function setGasConfig(uint256 _overhead, uint256 _scalar) external onlyOwner {
...@@ -356,6 +366,8 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken { ...@@ -356,6 +366,8 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken {
/// @param _overhead New overhead value. /// @param _overhead New overhead value.
/// @param _scalar New scalar value. /// @param _scalar New scalar value.
function _setGasConfig(uint256 _overhead, uint256 _scalar) internal { function _setGasConfig(uint256 _overhead, uint256 _scalar) internal {
require((uint256(0xff) << 248) & _scalar == 0, "SystemConfig: scalar exceeds max.");
overhead = _overhead; overhead = _overhead;
scalar = _scalar; scalar = _scalar;
...@@ -363,6 +375,26 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken { ...@@ -363,6 +375,26 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken {
emit ConfigUpdate(VERSION, UpdateType.GAS_CONFIG, data); emit ConfigUpdate(VERSION, UpdateType.GAS_CONFIG, data);
} }
/// @notice Updates gas config as of the Ecotone upgrade. Can only be called by the owner.
/// @param _basefeeScalar New basefeeScalar value.
/// @param _blobbasefeeScalar New blobbasefeeScalar value.
function setGasConfigEcotone(uint32 _basefeeScalar, uint32 _blobbasefeeScalar) external onlyOwner {
_setGasConfigEcotone(_basefeeScalar, _blobbasefeeScalar);
}
/// @notice Internal function for updating the fee scalars as of the Ecotone upgrade.
/// @param _basefeeScalar New basefeeScalar value.
/// @param _blobbasefeeScalar New blobbasefeeScalar value.
function _setGasConfigEcotone(uint32 _basefeeScalar, uint32 _blobbasefeeScalar) internal {
basefeeScalar = _basefeeScalar;
blobbasefeeScalar = _blobbasefeeScalar;
scalar = (uint256(0x01) << 248) | (uint256(_blobbasefeeScalar) << 32) | _basefeeScalar;
bytes memory data = abi.encode(overhead, scalar);
emit ConfigUpdate(VERSION, UpdateType.GAS_CONFIG, data);
}
/// @notice Updates the L2 gas limit. Can only be called by the owner. /// @notice Updates the L2 gas limit. Can only be called by the owner.
/// @param _gasLimit New gas limit. /// @param _gasLimit New gas limit.
function setGasLimit(uint64 _gasLimit) external onlyOwner { function setGasLimit(uint64 _gasLimit) external onlyOwner {
......
...@@ -26,20 +26,20 @@ contract SystemConfig_Init is CommonTest { ...@@ -26,20 +26,20 @@ contract SystemConfig_Init is CommonTest {
contract SystemConfig_Initialize_Test is SystemConfig_Init { contract SystemConfig_Initialize_Test is SystemConfig_Init {
address batchInbox; address batchInbox;
address owner; address owner;
uint256 overhead;
uint256 scalar;
bytes32 batcherHash; bytes32 batcherHash;
uint64 gasLimit; uint64 gasLimit;
address unsafeBlockSigner; address unsafeBlockSigner;
address systemConfigImpl; address systemConfigImpl;
address optimismMintableERC20Factory; address optimismMintableERC20Factory;
uint32 basefeeScalar;
uint32 blobbasefeeScalar;
function setUp() public virtual override { function setUp() public virtual override {
super.setUp(); super.setUp();
batchInbox = deploy.cfg().batchInboxAddress(); batchInbox = deploy.cfg().batchInboxAddress();
owner = deploy.cfg().finalSystemOwner(); owner = deploy.cfg().finalSystemOwner();
overhead = deploy.cfg().gasPriceOracleOverhead(); basefeeScalar = deploy.cfg().basefeeScalar();
scalar = deploy.cfg().gasPriceOracleScalar(); blobbasefeeScalar = deploy.cfg().blobbasefeeScalar();
batcherHash = bytes32(uint256(uint160(deploy.cfg().batchSenderAddress()))); batcherHash = bytes32(uint256(uint160(deploy.cfg().batchSenderAddress())));
gasLimit = uint64(deploy.cfg().l2GenesisBlockGasLimit()); gasLimit = uint64(deploy.cfg().l2GenesisBlockGasLimit());
unsafeBlockSigner = deploy.cfg().p2pSequencerAddress(); unsafeBlockSigner = deploy.cfg().p2pSequencerAddress();
...@@ -52,10 +52,12 @@ contract SystemConfig_Initialize_Test is SystemConfig_Init { ...@@ -52,10 +52,12 @@ contract SystemConfig_Initialize_Test is SystemConfig_Init {
SystemConfig impl = SystemConfig(systemConfigImpl); SystemConfig impl = SystemConfig(systemConfigImpl);
assertEq(impl.owner(), address(0xdEaD)); assertEq(impl.owner(), address(0xdEaD));
assertEq(impl.overhead(), 0); assertEq(impl.overhead(), 0);
assertEq(impl.scalar(), 0); assertEq(impl.scalar(), uint256(0x01) << 248);
assertEq(impl.batcherHash(), bytes32(0)); assertEq(impl.batcherHash(), bytes32(0));
assertEq(impl.gasLimit(), 1); assertEq(impl.gasLimit(), 1);
assertEq(impl.unsafeBlockSigner(), address(0)); assertEq(impl.unsafeBlockSigner(), address(0));
assertEq(impl.basefeeScalar(), 0);
assertEq(impl.blobbasefeeScalar(), 0);
ResourceMetering.ResourceConfig memory actual = impl.resourceConfig(); ResourceMetering.ResourceConfig memory actual = impl.resourceConfig();
assertEq(actual.maxResourceLimit, 1); assertEq(actual.maxResourceLimit, 1);
assertEq(actual.elasticityMultiplier, 1); assertEq(actual.elasticityMultiplier, 1);
...@@ -78,14 +80,16 @@ contract SystemConfig_Initialize_Test is SystemConfig_Init { ...@@ -78,14 +80,16 @@ contract SystemConfig_Initialize_Test is SystemConfig_Init {
assertEq(decimals, 18); assertEq(decimals, 18);
} }
/// @dev Tests that initailization sets the correct values. /// @dev Tests that initialization sets the correct values.
function test_initialize_succeeds() external view { function test_initialize_succeeds() external view {
assertEq(systemConfig.owner(), owner); assertEq(systemConfig.owner(), owner);
assertEq(systemConfig.overhead(), overhead); assertEq(systemConfig.overhead(), 0);
assertEq(systemConfig.scalar(), scalar); assertEq(systemConfig.scalar() >> 248, 1);
assertEq(systemConfig.batcherHash(), batcherHash); assertEq(systemConfig.batcherHash(), batcherHash);
assertEq(systemConfig.gasLimit(), gasLimit); assertEq(systemConfig.gasLimit(), gasLimit);
assertEq(systemConfig.unsafeBlockSigner(), unsafeBlockSigner); assertEq(systemConfig.unsafeBlockSigner(), unsafeBlockSigner);
assertEq(systemConfig.basefeeScalar(), basefeeScalar);
assertEq(systemConfig.blobbasefeeScalar(), blobbasefeeScalar);
// Depends on `initialize` being called with defaults // Depends on `initialize` being called with defaults
ResourceMetering.ResourceConfig memory rcfg = Constants.DEFAULT_RESOURCE_CONFIG(); ResourceMetering.ResourceConfig memory rcfg = Constants.DEFAULT_RESOURCE_CONFIG();
ResourceMetering.ResourceConfig memory actual = systemConfig.resourceConfig(); ResourceMetering.ResourceConfig memory actual = systemConfig.resourceConfig();
...@@ -127,8 +131,8 @@ contract SystemConfig_Initialize_TestFail is SystemConfig_Initialize_Test { ...@@ -127,8 +131,8 @@ contract SystemConfig_Initialize_TestFail is SystemConfig_Initialize_Test {
vm.expectRevert("SystemConfig: gas limit too low"); vm.expectRevert("SystemConfig: gas limit too low");
systemConfig.initialize({ systemConfig.initialize({
_owner: alice, _owner: alice,
_overhead: 2100, _basefeeScalar: basefeeScalar,
_scalar: 1000000, _blobbasefeeScalar: blobbasefeeScalar,
_batcherHash: bytes32(hex"abcd"), _batcherHash: bytes32(hex"abcd"),
_gasLimit: minimumGasLimit - 1, _gasLimit: minimumGasLimit - 1,
_unsafeBlockSigner: address(1), _unsafeBlockSigner: address(1),
...@@ -157,8 +161,8 @@ contract SystemConfig_Initialize_TestFail is SystemConfig_Initialize_Test { ...@@ -157,8 +161,8 @@ contract SystemConfig_Initialize_TestFail is SystemConfig_Initialize_Test {
vm.prank(systemConfig.owner()); vm.prank(systemConfig.owner());
systemConfig.initialize({ systemConfig.initialize({
_owner: alice, _owner: alice,
_overhead: 2100, _basefeeScalar: basefeeScalar,
_scalar: 1000000, _blobbasefeeScalar: blobbasefeeScalar,
_batcherHash: bytes32(hex"abcd"), _batcherHash: bytes32(hex"abcd"),
_gasLimit: gasLimit, _gasLimit: gasLimit,
_unsafeBlockSigner: address(1), _unsafeBlockSigner: address(1),
...@@ -188,8 +192,8 @@ contract SystemConfig_Initialize_TestFail is SystemConfig_Initialize_Test { ...@@ -188,8 +192,8 @@ contract SystemConfig_Initialize_TestFail is SystemConfig_Initialize_Test {
vm.prank(systemConfig.owner()); vm.prank(systemConfig.owner());
systemConfig.initialize({ systemConfig.initialize({
_owner: alice, _owner: alice,
_overhead: 2100, _basefeeScalar: basefeeScalar,
_scalar: 1000000, _blobbasefeeScalar: blobbasefeeScalar,
_batcherHash: bytes32(hex"abcd"), _batcherHash: bytes32(hex"abcd"),
_gasLimit: gasLimit, _gasLimit: gasLimit,
_unsafeBlockSigner: address(1), _unsafeBlockSigner: address(1),
...@@ -283,8 +287,8 @@ contract SystemConfig_Init_ResourceConfig is SystemConfig_Init { ...@@ -283,8 +287,8 @@ contract SystemConfig_Init_ResourceConfig is SystemConfig_Init {
vm.expectRevert(bytes(revertMessage)); vm.expectRevert(bytes(revertMessage));
systemConfig.initialize({ systemConfig.initialize({
_owner: address(0xdEaD), _owner: address(0xdEaD),
_overhead: 0, _basefeeScalar: 0,
_scalar: 0, _blobbasefeeScalar: 0,
_batcherHash: bytes32(0), _batcherHash: bytes32(0),
_gasLimit: gasLimit, _gasLimit: gasLimit,
_unsafeBlockSigner: address(0), _unsafeBlockSigner: address(0),
...@@ -321,8 +325,8 @@ contract SystemConfig_Init_CustomGasToken is SystemConfig_Init { ...@@ -321,8 +325,8 @@ contract SystemConfig_Init_CustomGasToken is SystemConfig_Init {
systemConfig.initialize({ systemConfig.initialize({
_owner: alice, _owner: alice,
_overhead: 2100, _basefeeScalar: 2100,
_scalar: 1000000, _blobbasefeeScalar: 1000000,
_batcherHash: bytes32(hex"abcd"), _batcherHash: bytes32(hex"abcd"),
_gasLimit: 30_000_000, _gasLimit: 30_000_000,
_unsafeBlockSigner: address(1), _unsafeBlockSigner: address(1),
...@@ -474,6 +478,18 @@ contract SystemConfig_Setters_TestFail is SystemConfig_Init { ...@@ -474,6 +478,18 @@ contract SystemConfig_Setters_TestFail is SystemConfig_Init {
systemConfig.setGasConfig(0, 0); systemConfig.setGasConfig(0, 0);
} }
/// @notice Ensures that `setGasConfig` reverts if version byte is set.
function test_setGasConfig_badValues_reverts() external {
vm.prank(systemConfig.owner());
vm.expectRevert("SystemConfig: scalar exceeds max.");
systemConfig.setGasConfig({ _overhead: 0, _scalar: type(uint256).max });
}
function test_setGasConfigEcotone_notOwner_reverts() external {
vm.expectRevert("Ownable: caller is not the owner");
systemConfig.setGasConfigEcotone({ _basefeeScalar: 0, _blobbasefeeScalar: 0 });
}
/// @dev Tests that `setGasLimit` reverts if the caller is not the owner. /// @dev Tests that `setGasLimit` reverts if the caller is not the owner.
function test_setGasLimit_notOwner_reverts() external { function test_setGasLimit_notOwner_reverts() external {
vm.expectRevert("Ownable: caller is not the owner"); vm.expectRevert("Ownable: caller is not the owner");
...@@ -516,6 +532,8 @@ contract SystemConfig_Setters_Test is SystemConfig_Init { ...@@ -516,6 +532,8 @@ contract SystemConfig_Setters_Test is SystemConfig_Init {
/// @dev Tests that `setGasConfig` updates the overhead and scalar successfully. /// @dev Tests that `setGasConfig` updates the overhead and scalar successfully.
function testFuzz_setGasConfig_succeeds(uint256 newOverhead, uint256 newScalar) external { function testFuzz_setGasConfig_succeeds(uint256 newOverhead, uint256 newScalar) external {
// always zero out most significant byte
newScalar = (newScalar << 16) >> 16;
vm.expectEmit(address(systemConfig)); vm.expectEmit(address(systemConfig));
emit ConfigUpdate(0, SystemConfig.UpdateType.GAS_CONFIG, abi.encode(newOverhead, newScalar)); emit ConfigUpdate(0, SystemConfig.UpdateType.GAS_CONFIG, abi.encode(newOverhead, newScalar));
...@@ -525,6 +543,24 @@ contract SystemConfig_Setters_Test is SystemConfig_Init { ...@@ -525,6 +543,24 @@ contract SystemConfig_Setters_Test is SystemConfig_Init {
assertEq(systemConfig.scalar(), newScalar); assertEq(systemConfig.scalar(), newScalar);
} }
function testFuzz_setGasConfigEcotone_succeeds(uint32 _basefeeScalar, uint32 _blobbasefeeScalar) external {
bytes32 encoded =
ffi.encodeScalarEcotone({ _basefeeScalar: _basefeeScalar, _blobbasefeeScalar: _blobbasefeeScalar });
vm.expectEmit(address(systemConfig));
emit ConfigUpdate(0, SystemConfig.UpdateType.GAS_CONFIG, abi.encode(systemConfig.overhead(), encoded));
vm.prank(systemConfig.owner());
systemConfig.setGasConfigEcotone({ _basefeeScalar: _basefeeScalar, _blobbasefeeScalar: _blobbasefeeScalar });
assertEq(systemConfig.basefeeScalar(), _basefeeScalar);
assertEq(systemConfig.blobbasefeeScalar(), _blobbasefeeScalar);
assertEq(systemConfig.scalar(), uint256(encoded));
(uint32 basefeeScalar, uint32 blobbbasefeeScalar) = ffi.decodeScalarEcotone(encoded);
assertEq(uint256(basefeeScalar), uint256(_basefeeScalar));
assertEq(uint256(blobbbasefeeScalar), uint256(_blobbasefeeScalar));
}
/// @dev Tests that `setGasLimit` updates the gas limit successfully. /// @dev Tests that `setGasLimit` updates the gas limit successfully.
function testFuzz_setGasLimit_succeeds(uint64 newGasLimit) external { function testFuzz_setGasLimit_succeeds(uint64 newGasLimit) external {
uint64 minimumGasLimit = systemConfig.minimumGasLimit(); uint64 minimumGasLimit = systemConfig.minimumGasLimit();
......
...@@ -30,7 +30,7 @@ contract DeploymentSummary is DeploymentSummaryCode { ...@@ -30,7 +30,7 @@ contract DeploymentSummary is DeploymentSummaryCode {
address internal constant safeSingletonAddress = 0x90193C961A926261B756D1E5bb255e67ff9498A1; address internal constant safeSingletonAddress = 0x90193C961A926261B756D1E5bb255e67ff9498A1;
address internal constant superchainConfigAddress = 0x068E44eB31e111028c41598E4535be7468674D0A; address internal constant superchainConfigAddress = 0x068E44eB31e111028c41598E4535be7468674D0A;
address internal constant superchainConfigProxyAddress = 0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809; address internal constant superchainConfigProxyAddress = 0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809;
address internal constant systemConfigAddress = 0x19E90dC1Fb905f20BB3A7eC537B5B812d5FFA682; address internal constant systemConfigAddress = 0x1182f45ae539e18534cbCC222c1C3D972B5Ba24D;
address internal constant systemConfigProxyAddress = 0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4; address internal constant systemConfigProxyAddress = 0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4;
address internal constant systemOwnerSafeAddress = 0x7d039be7F9b5190147621b02e82B250e1D748e02; address internal constant systemOwnerSafeAddress = 0x7d039be7F9b5190147621b02e82B250e1D748e02;
...@@ -242,6 +242,9 @@ contract DeploymentSummary is DeploymentSummaryCode { ...@@ -242,6 +242,9 @@ contract DeploymentSummary is DeploymentSummaryCode {
slot = hex"0000000000000000000000000000000000000000000000000000000000000033"; slot = hex"0000000000000000000000000000000000000000000000000000000000000033";
value = hex"000000000000000000000000000000000000000000000000000000000000dead"; value = hex"000000000000000000000000000000000000000000000000000000000000dead";
vm.store(systemConfigAddress, slot, value); vm.store(systemConfigAddress, slot, value);
slot = hex"0000000000000000000000000000000000000000000000000000000000000066";
value = hex"0100000000000000000000000000000000000000000000000000000000000000";
vm.store(systemConfigAddress, slot, value);
slot = hex"0000000000000000000000000000000000000000000000000000000000000068"; slot = hex"0000000000000000000000000000000000000000000000000000000000000068";
value = hex"0000000000000000000000000000000000000000000000000000000000000001"; value = hex"0000000000000000000000000000000000000000000000000000000000000001";
vm.store(systemConfigAddress, slot, value); vm.store(systemConfigAddress, slot, value);
...@@ -281,7 +284,7 @@ contract DeploymentSummary is DeploymentSummaryCode { ...@@ -281,7 +284,7 @@ contract DeploymentSummary is DeploymentSummaryCode {
value = hex"0000000000000000000000000000000000000000000000000000000000000003"; value = hex"0000000000000000000000000000000000000000000000000000000000000003";
vm.store(systemOwnerSafeAddress, slot, value); vm.store(systemOwnerSafeAddress, slot, value);
slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc";
value = hex"00000000000000000000000019e90dc1fb905f20bb3a7ec537b5b812d5ffa682"; value = hex"0000000000000000000000001182f45ae539e18534cbcc222c1c3d972b5ba24d";
vm.store(systemConfigProxyAddress, slot, value); vm.store(systemConfigProxyAddress, slot, value);
slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; slot = hex"0000000000000000000000000000000000000000000000000000000000000000";
value = hex"0000000000000000000000000000000000000000000000000000000000000001"; value = hex"0000000000000000000000000000000000000000000000000000000000000001";
...@@ -298,14 +301,14 @@ contract DeploymentSummary is DeploymentSummaryCode { ...@@ -298,14 +301,14 @@ contract DeploymentSummary is DeploymentSummaryCode {
slot = hex"0000000000000000000000000000000000000000000000000000000000000067"; slot = hex"0000000000000000000000000000000000000000000000000000000000000067";
value = hex"0000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc"; value = hex"0000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc";
vm.store(systemConfigProxyAddress, slot, value); vm.store(systemConfigProxyAddress, slot, value);
slot = hex"0000000000000000000000000000000000000000000000000000000000000065"; slot = hex"0000000000000000000000000000000000000000000000000000000000000068";
value = hex"0000000000000000000000000000000000000000000000000000000000000834"; value = hex"00000000000000000000000000000000000c5fc5000005580000000000000000";
vm.store(systemConfigProxyAddress, slot, value); vm.store(systemConfigProxyAddress, slot, value);
slot = hex"0000000000000000000000000000000000000000000000000000000000000066"; slot = hex"0000000000000000000000000000000000000000000000000000000000000066";
value = hex"00000000000000000000000000000000000000000000000000000000000f4240"; value = hex"010000000000000000000000000000000000000000000000000c5fc500000558";
vm.store(systemConfigProxyAddress, slot, value); vm.store(systemConfigProxyAddress, slot, value);
slot = hex"0000000000000000000000000000000000000000000000000000000000000068"; slot = hex"0000000000000000000000000000000000000000000000000000000000000068";
value = hex"00000000000000000000000000000000000000000000000000000000017d7840"; value = hex"00000000000000000000000000000000000c5fc50000055800000000017d7840";
vm.store(systemConfigProxyAddress, slot, value); vm.store(systemConfigProxyAddress, slot, value);
slot = hex"65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08"; slot = hex"65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08";
value = hex"0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc"; value = hex"0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc";
......
...@@ -36,7 +36,7 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode { ...@@ -36,7 +36,7 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode {
address internal constant safeSingletonAddress = 0x90193C961A926261B756D1E5bb255e67ff9498A1; address internal constant safeSingletonAddress = 0x90193C961A926261B756D1E5bb255e67ff9498A1;
address internal constant superchainConfigAddress = 0x068E44eB31e111028c41598E4535be7468674D0A; address internal constant superchainConfigAddress = 0x068E44eB31e111028c41598E4535be7468674D0A;
address internal constant superchainConfigProxyAddress = 0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809; address internal constant superchainConfigProxyAddress = 0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809;
address internal constant systemConfigAddress = 0x19E90dC1Fb905f20BB3A7eC537B5B812d5FFA682; address internal constant systemConfigAddress = 0x1182f45ae539e18534cbCC222c1C3D972B5Ba24D;
address internal constant systemConfigProxyAddress = 0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D; address internal constant systemConfigProxyAddress = 0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D;
address internal constant systemOwnerSafeAddress = 0x7d039be7F9b5190147621b02e82B250e1D748e02; address internal constant systemOwnerSafeAddress = 0x7d039be7F9b5190147621b02e82B250e1D748e02;
address internal constant acc27Address = 0x12e721c390F5728200a26BBEf206A5F4F7E991f3; address internal constant acc27Address = 0x12e721c390F5728200a26BBEf206A5F4F7E991f3;
...@@ -245,6 +245,9 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode { ...@@ -245,6 +245,9 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode {
slot = hex"0000000000000000000000000000000000000000000000000000000000000033"; slot = hex"0000000000000000000000000000000000000000000000000000000000000033";
value = hex"000000000000000000000000000000000000000000000000000000000000dead"; value = hex"000000000000000000000000000000000000000000000000000000000000dead";
vm.store(systemConfigAddress, slot, value); vm.store(systemConfigAddress, slot, value);
slot = hex"0000000000000000000000000000000000000000000000000000000000000066";
value = hex"0100000000000000000000000000000000000000000000000000000000000000";
vm.store(systemConfigAddress, slot, value);
slot = hex"0000000000000000000000000000000000000000000000000000000000000068"; slot = hex"0000000000000000000000000000000000000000000000000000000000000068";
value = hex"0000000000000000000000000000000000000000000000000000000000000001"; value = hex"0000000000000000000000000000000000000000000000000000000000000001";
vm.store(systemConfigAddress, slot, value); vm.store(systemConfigAddress, slot, value);
...@@ -373,7 +376,7 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode { ...@@ -373,7 +376,7 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode {
value = hex"0000000000000000000000000000000000000000000000000000000000000003"; value = hex"0000000000000000000000000000000000000000000000000000000000000003";
vm.store(systemOwnerSafeAddress, slot, value); vm.store(systemOwnerSafeAddress, slot, value);
slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc";
value = hex"00000000000000000000000019e90dc1fb905f20bb3a7ec537b5b812d5ffa682"; value = hex"0000000000000000000000001182f45ae539e18534cbcc222c1c3d972b5ba24d";
vm.store(systemConfigProxyAddress, slot, value); vm.store(systemConfigProxyAddress, slot, value);
slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; slot = hex"0000000000000000000000000000000000000000000000000000000000000000";
value = hex"0000000000000000000000000000000000000000000000000000000000000001"; value = hex"0000000000000000000000000000000000000000000000000000000000000001";
...@@ -390,14 +393,14 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode { ...@@ -390,14 +393,14 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode {
slot = hex"0000000000000000000000000000000000000000000000000000000000000067"; slot = hex"0000000000000000000000000000000000000000000000000000000000000067";
value = hex"0000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc"; value = hex"0000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc";
vm.store(systemConfigProxyAddress, slot, value); vm.store(systemConfigProxyAddress, slot, value);
slot = hex"0000000000000000000000000000000000000000000000000000000000000065"; slot = hex"0000000000000000000000000000000000000000000000000000000000000068";
value = hex"0000000000000000000000000000000000000000000000000000000000000834"; value = hex"00000000000000000000000000000000000c5fc5000005580000000000000000";
vm.store(systemConfigProxyAddress, slot, value); vm.store(systemConfigProxyAddress, slot, value);
slot = hex"0000000000000000000000000000000000000000000000000000000000000066"; slot = hex"0000000000000000000000000000000000000000000000000000000000000066";
value = hex"00000000000000000000000000000000000000000000000000000000000f4240"; value = hex"010000000000000000000000000000000000000000000000000c5fc500000558";
vm.store(systemConfigProxyAddress, slot, value); vm.store(systemConfigProxyAddress, slot, value);
slot = hex"0000000000000000000000000000000000000000000000000000000000000068"; slot = hex"0000000000000000000000000000000000000000000000000000000000000068";
value = hex"00000000000000000000000000000000000000000000000000000000017d7840"; value = hex"00000000000000000000000000000000000c5fc50000055800000000017d7840";
vm.store(systemConfigProxyAddress, slot, value); vm.store(systemConfigProxyAddress, slot, value);
slot = hex"65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08"; slot = hex"65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08";
value = hex"0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc"; value = hex"0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc";
......
...@@ -243,4 +243,25 @@ contract FFIInterface { ...@@ -243,4 +243,25 @@ contract FFIInterface {
(bytes32 memRoot, bytes memory proof) = abi.decode(result, (bytes32, bytes)); (bytes32 memRoot, bytes memory proof) = abi.decode(result, (bytes32, bytes));
return (memRoot, proof); return (memRoot, proof);
} }
function encodeScalarEcotone(uint32 _basefeeScalar, uint32 _blobbasefeeScalar) external returns (bytes32) {
string[] memory cmds = new string[](5);
cmds[0] = "scripts/go-ffi/go-ffi";
cmds[1] = "diff";
cmds[2] = "encodeScalarEcotone";
cmds[3] = vm.toString(_basefeeScalar);
cmds[4] = vm.toString(_blobbasefeeScalar);
bytes memory result = vm.ffi(cmds);
return abi.decode(result, (bytes32));
}
function decodeScalarEcotone(bytes32 _scalar) external returns (uint32, uint32) {
string[] memory cmds = new string[](4);
cmds[0] = "scripts/go-ffi/go-ffi";
cmds[1] = "diff";
cmds[2] = "decodeScalarEcotone";
cmds[3] = vm.toString(_scalar);
bytes memory result = vm.ffi(cmds);
return abi.decode(result, (uint32, uint32));
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment