Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ctb): Enforce maximum L2 gas limit #10500

Merged
merged 2 commits into from
May 13, 2024
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
5 changes: 3 additions & 2 deletions packages/contracts-bedrock/invariant-docs/SystemConfig.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# `SystemConfig` Invariants

## The gas limit of the `SystemConfig` contract can never be lower than the hard-coded lower bound.
**Test:** [`SystemConfig.t.sol#L69`](../test/invariants/SystemConfig.t.sol#L69)
## Gas limit boundaries
clabby marked this conversation as resolved.
Show resolved Hide resolved
**Test:** [`SystemConfig.t.sol#L70`](../test/invariants/SystemConfig.t.sol#L70)

The gas limit of the `SystemConfig` contract can never be lower than the hard-coded lower bound or higher than the hard-coded upper bound. The lower bound must never be higher than the upper bound.
clabby marked this conversation as resolved.
Show resolved Hide resolved
4 changes: 2 additions & 2 deletions packages/contracts-bedrock/semver-lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@
"sourceCodeHash": "0xd6a894e371c2c7182b5960c507491f81c3775dda0efedd29475f7c30ca07b004"
},
"src/L1/SystemConfig.sol": {
"initCodeHash": "0xace1ef0e25a5416a686c7555acd20e9b0191ab2a8c8320d57606ed12092ccbb6",
"sourceCodeHash": "0x1f35f55aa230a686f6457e42bd08acc8bd94d691f89ac23a4b2efd7cc1eefdc6"
"initCodeHash": "0x68a862089f654e951850708a48025e93231c041b862d05086e1a05be9d9ac4e9",
"sourceCodeHash": "0x3a7cd5254306a01b50c9c68d9e57a57db7ad8163326eb30dff23e368c35ff166"
},
"src/L2/BaseFeeVault.sol": {
"initCodeHash": "0x2744d34573be83206d1b75d049d18a7bb37f9058e68c0803e5008c46b0dc2474",
Expand Down
13 changes: 13 additions & 0 deletions packages/contracts-bedrock/snapshots/abi/SystemConfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,19 @@
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "maximumGasLimit",
"outputs": [
{
"internalType": "uint64",
"name": "",
"type": "uint64"
}
],
"stateMutability": "pure",
"type": "function"
},
{
"inputs": [],
"name": "minimumGasLimit",
Expand Down
18 changes: 16 additions & 2 deletions packages/contracts-bedrock/src/L1/SystemConfig.sol
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,11 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken {
/// @notice The number of decimals that the gas paying token has.
uint8 internal constant GAS_PAYING_TOKEN_DECIMALS = 18;

/// @notice The maximum gas limit that can be set for L2 blocks. This limit is used to enforce that the blocks
/// on L2 are not too large to process and prove. Over time, this value can be increased as various
/// optimizations and improvements are made to the system at large.
uint64 internal constant MAX_GAS_LIMIT = 200_000_000;

/// @notice Fixed L2 gas overhead. Used as part of the L2 fee calculation.
uint256 public overhead;

Expand All @@ -110,8 +115,8 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken {
event ConfigUpdate(uint256 indexed version, UpdateType indexed updateType, bytes data);

/// @notice Semantic version.
/// @custom:semver 2.1.0
string public constant version = "2.1.0";
/// @custom:semver 2.2.0
string public constant version = "2.2.0";

/// @notice Constructs the SystemConfig contract. Cannot set
/// the owner to `address(0)` due to the Ownable contract's
Expand Down Expand Up @@ -208,6 +213,14 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken {
return uint64(_resourceConfig.maxResourceLimit) + uint64(_resourceConfig.systemTxMaxGas);
}

/// @notice Returns the maximum L2 gas limit that can be safely set for the system to
/// operate. This bound is used to prevent the gas limit from being set too high
/// and causing the system to be unable to process and/or prove L2 blocks.
/// @return uint64 Maximum gas limit.
function maximumGasLimit() public pure returns (uint64) {
return MAX_GAS_LIMIT;
}

/// @notice High level getter for the unsafe block signer address.
/// Unsafe blocks can be propagated across the p2p network if they are signed by the
/// key corresponding to this address.
Expand Down Expand Up @@ -360,6 +373,7 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken {
/// @param _gasLimit New gas limit.
function _setGasLimit(uint64 _gasLimit) internal {
require(_gasLimit >= minimumGasLimit(), "SystemConfig: gas limit too low");
require(_gasLimit <= maximumGasLimit(), "SystemConfig: gas limit too high");
gasLimit = _gasLimit;

bytes memory data = abi.encode(_gasLimit);
Expand Down
19 changes: 18 additions & 1 deletion packages/contracts-bedrock/test/L1/SystemConfig.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,22 @@ contract SystemConfig_Setters_TestFail is SystemConfig_Init {
systemConfig.setResourceConfig(config);
}

/// @dev Tests that `setGasLimit` reverts if the gas limit is too low.
function test_setGasLimit_lowGasLimit_reverts() external {
uint64 minimumGasLimit = systemConfig.minimumGasLimit();
vm.prank(systemConfig.owner());
vm.expectRevert("SystemConfig: gas limit too low");
systemConfig.setGasLimit(minimumGasLimit - 1);
}

/// @dev Tests that `setGasLimit` reverts if the gas limit is too high.
function test_setGasLimit_highGasLimit_reverts() external {
uint64 maximumGasLimit = systemConfig.maximumGasLimit();
vm.prank(systemConfig.owner());
vm.expectRevert("SystemConfig: gas limit too high");
systemConfig.setGasLimit(maximumGasLimit + 1);
}

/// @dev Tests that `setResourceConfig` reverts if the min base fee
/// is greater than the maximum allowed base fee.
function test_setResourceConfig_badMinMax_reverts() external {
Expand Down Expand Up @@ -489,7 +505,8 @@ contract SystemConfig_Setters_Test is SystemConfig_Init {
/// @dev Tests that `setGasLimit` updates the gas limit successfully.
function testFuzz_setGasLimit_succeeds(uint64 newGasLimit) external {
uint64 minimumGasLimit = systemConfig.minimumGasLimit();
newGasLimit = uint64(bound(uint256(newGasLimit), uint256(minimumGasLimit), uint256(type(uint64).max)));
uint64 maximumGasLimit = systemConfig.maximumGasLimit();
newGasLimit = uint64(bound(uint256(newGasLimit), uint256(minimumGasLimit), uint256(maximumGasLimit)));

vm.expectEmit(address(systemConfig));
emit ConfigUpdate(0, SystemConfig.UpdateType.GAS_LIMIT, abi.encode(newGasLimit));
Expand Down
12 changes: 8 additions & 4 deletions packages/contracts-bedrock/test/invariants/SystemConfig.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { SystemConfig } from "src/L1/SystemConfig.sol";
import { Proxy } from "src/universal/Proxy.sol";
import { Constants } from "src/libraries/Constants.sol";

contract SystemConfig_GasLimitLowerBound_Invariant is Test {
contract SystemConfig_GasLimitBoundaries_Invariant is Test {
SystemConfig public config;

function setUp() external {
Expand Down Expand Up @@ -63,9 +63,13 @@ contract SystemConfig_GasLimitLowerBound_Invariant is Test {
targetInterface(target);
}

/// @custom:invariant The gas limit of the `SystemConfig` contract can never be lower
/// than the hard-coded lower bound.
function invariant_gasLimitLowerBound() external view {
/// @custom:invariant Gas limit boundaries
///
/// The gas limit of the `SystemConfig` contract can never be lower than the hard-coded lower bound or higher than
/// the hard-coded upper bound. The lower bound must never be higher than the upper bound.
function invariant_gasLimitBoundaries() external view {
assertTrue(config.gasLimit() >= config.minimumGasLimit());
assertTrue(config.gasLimit() <= config.maximumGasLimit());
assertTrue(config.minimumGasLimit() <= config.maximumGasLimit());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ contract DeploymentSummary is DeploymentSummaryCode {
address internal constant safeSingletonAddress = 0x90193C961A926261B756D1E5bb255e67ff9498A1;
address internal constant superchainConfigAddress = 0x068E44eB31e111028c41598E4535be7468674D0A;
address internal constant superchainConfigProxyAddress = 0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809;
address internal constant systemConfigAddress = 0x809abd1c13738dE7a76C85839779FCaa59FA32CE;
address internal constant systemConfigAddress = 0x1Fa4ABc046c3B6e20e072df7F869D67566974301;
address internal constant systemConfigProxyAddress = 0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4;
address internal constant systemOwnerSafeAddress = 0x7d039be7F9b5190147621b02e82B250e1D748e02;

Expand Down Expand Up @@ -281,7 +281,7 @@ contract DeploymentSummary is DeploymentSummaryCode {
value = hex"0000000000000000000000000000000000000000000000000000000000000003";
vm.store(systemOwnerSafeAddress, slot, value);
slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc";
value = hex"000000000000000000000000809abd1c13738de7a76c85839779fcaa59fa32ce";
value = hex"0000000000000000000000001fa4abc046c3b6e20e072df7f869d67566974301";
vm.store(systemConfigProxyAddress, slot, value);
slot = hex"0000000000000000000000000000000000000000000000000000000000000000";
value = hex"0000000000000000000000000000000000000000000000000000000000000001";
Expand Down

Large diffs are not rendered by default.