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
17 changes: 15 additions & 2 deletions hardhat-test/EnforcedTxGateway.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ import { expect } from "chai";
import { BigNumberish, BytesLike, MaxUint256, ZeroAddress, getBytes } from "ethers";
import { ethers } from "hardhat";

import { EnforcedTxGateway, L1MessageQueueV2, L2GasPriceOracle, MockCaller } from "../typechain";
import { EnforcedTxGateway, L1MessageQueueV2, L2GasPriceOracle, MockCaller, SystemConfig } from "../typechain";

describe("EnforcedTxGateway.spec", async () => {
let deployer: HardhatEthersSigner;
let feeVault: HardhatEthersSigner;
let signer: HardhatEthersSigner;

let caller: MockCaller;
let system: SystemConfig;
let gateway: EnforcedTxGateway;
let oracle: L2GasPriceOracle;
let queue: L1MessageQueueV2;
Expand All @@ -37,6 +38,12 @@ describe("EnforcedTxGateway.spec", async () => {
deployer
);

system = await ethers.getContractAt(
"SystemConfig",
await deployProxy("SystemConfig", await admin.getAddress(), []),
deployer
);

const queueV1 = await ethers.getContractAt(
"L1MessageQueueV1",
await deployProxy("L1MessageQueueV1", await admin.getAddress(), [
Expand All @@ -54,6 +61,7 @@ describe("EnforcedTxGateway.spec", async () => {
deployer.address,
await gateway.getAddress(),
await queueV1.getAddress(),
await system.getAddress(),
]),
deployer
);
Expand All @@ -67,7 +75,12 @@ describe("EnforcedTxGateway.spec", async () => {
const MockCaller = await ethers.getContractFactory("MockCaller", deployer);
caller = await MockCaller.deploy();

await queue.initialize(1000000, { overhead: 123, scalar: 10n ** 18n });
await system.initialize(deployer.address, deployer.address, {
maxGasLimit: 1000000,
baseFeeOverhead: 10n ** 9n,
baseFeeScalar: 10n ** 18n,
});
await queue.initialize();
await gateway.initialize(queue.getAddress(), feeVault.address);
await oracle.initialize(21000, 51000, 8, 16);

Expand Down
22 changes: 22 additions & 0 deletions scripts/foundry/DeployL1SystemConfig.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity =0.8.24;

import {Script} from "forge-std/Script.sol";
import {SystemConfig} from "../../src/L1/system-contract/SystemConfig.sol"; // adjust the relative path as necessary
import {console} from "forge-std/console.sol";

contract DeployL1SystemConfig is Script {
function run() external {
// Retrieve the deployer private key from environment variables
uint256 deployerKey = vm.envUint("L1_DEPLOYER_PRIVATE_KEY");

vm.startBroadcast(deployerKey);

// Deploy the SystemConfig contract with the specified owner.
SystemConfig sysConfig = new SystemConfig();

console.log("Deployed SystemConfig Implementation at address:", address(sysConfig));

vm.stopBroadcast();
}
}
8 changes: 6 additions & 2 deletions scripts/foundry/InitializeL1ScrollOwner.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {ScrollChain} from "../../src/L1/rollup/ScrollChain.sol";
import {ScrollOwner} from "../../src/misc/ScrollOwner.sol";
import {Whitelist} from "../../src/L2/predeploys/Whitelist.sol";


// solhint-disable max-states-count
// solhint-disable state-visibility
// solhint-disable var-name-mixedcase
Expand Down Expand Up @@ -63,6 +64,9 @@ contract InitializeL1ScrollOwner is Script {
address L1_ENFORCED_TX_GATEWAY_PROXY_ADDR = vm.envAddress("L1_ENFORCED_TX_GATEWAY_PROXY_ADDR");
address L1_WHITELIST_ADDR = vm.envAddress("L1_WHITELIST_ADDR");

address SYSTEM_CONTRACT_ADDR = vm.envAddress("SYSTEM_CONTRACT_ADDR");


ScrollOwner owner;

function run() external {
Expand All @@ -81,8 +85,8 @@ contract InitializeL1ScrollOwner is Script {
configL1GatewayRouter();
configL1CustomERC20Gateway();
configL1ERC721Gateway();
configL1ERC1155Gateway();

configL1ERC1155Gateway();
configL1USDCGateway();
configEnforcedTxGateway();

Expand Down
47 changes: 47 additions & 0 deletions scripts/foundry/InitializeL1SystemConfig.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity =0.8.24;

import { Script } from "forge-std/Script.sol";
import { SystemConfig } from "../../src/L1/system-contract/SystemConfig.sol";
import { ScrollOwner } from "../../src/misc/ScrollOwner.sol"; // Adjust this path as needed

/**
* @title InitializeL1SystemConfig
* @notice Configures the deployed SystemConfig contract.
* This script grants the Security Council (as defined by L1_SECURITY_COUNCIL_ADDR)
* access to call updateSigner() on the SystemConfig contract with no delay.
*/
contract InitializeL1SystemConfig is Script {
function run() external {
// Retrieve required environment variables.
uint256 deployerKey = vm.envUint("L1_DEPLOYER_PRIVATE_KEY");
address systemConfigAddr = vm.envAddress("SYSTEM_CONTRACT_ADDR");
address securityCouncilAddr = vm.envAddress("L1_SECURITY_COUNCIL_ADDR");
address scrollOwnerAddr = vm.envAddress("L1_SCROLL_OWNER_ADDR");

// Compute the role hash for the Security Council with no delay.
bytes32 SECURITY_COUNCIL_NO_DELAY_ROLE = keccak256("SECURITY_COUNCIL_NO_DELAY_ROLE");

vm.startBroadcast(deployerKey);

// Instantiate the ScrollOwner contract instance which manages access control.
ScrollOwner owner = ScrollOwner(payable(scrollOwnerAddr));
// Instantiate the already-deployed SystemConfig contract.
SystemConfig sys = SystemConfig(systemConfigAddr);

// Prepare a single-element array containing the function selector for updateSigner.
bytes4[] memory selectors = new bytes4[](1);
selectors[0] = sys.updateSigner.selector;

// Grant the SECURITY_COUNCIL_NO_DELAY_ROLE permission on SystemConfig,
// so that the Security Council address can call updateSigner() with no delay.
owner.updateAccess(
systemConfigAddr, // Address of the SystemConfig contract.
selectors, // The function selectors (only updateSigner here).
SECURITY_COUNCIL_NO_DELAY_ROLE,
true // Grant access.
);

vm.stopBroadcast();
}
}
2 changes: 1 addition & 1 deletion src/L1/L1ScrollMessenger.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// SPDX-License-Identifier: MIT

pragma solidity =0.8.24;

import {IScrollChain} from "./rollup/IScrollChain.sol";
Expand All @@ -11,6 +10,7 @@ import {IScrollMessenger} from "../libraries/IScrollMessenger.sol";
import {ScrollMessengerBase} from "../libraries/ScrollMessengerBase.sol";
import {WithdrawTrieVerifier} from "../libraries/verifier/WithdrawTrieVerifier.sol";


import {IMessageDropCallback} from "../libraries/callbacks/IMessageDropCallback.sol";

// solhint-disable avoid-low-level-calls
Expand Down
70 changes: 11 additions & 59 deletions src/L1/rollup/L1MessageQueueV2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import {AddressAliasHelper} from "../../libraries/common/AddressAliasHelper.sol"
import {IL1MessageQueueV1} from "./IL1MessageQueueV1.sol";
import {IL1MessageQueueV2} from "./IL1MessageQueueV2.sol";

import {SystemConfig} from "../system-contract/SystemConfig.sol";

// solhint-disable no-empty-blocks
// solhint-disable no-inline-assembly
// solhint-disable reason-string
Expand Down Expand Up @@ -69,14 +71,8 @@ contract L1MessageQueueV2 is OwnableUpgradeable, IL1MessageQueueV2 {
/// @notice The address of L1MessageQueueV1 contract.
address public immutable messageQueueV1;

/***********
* Structs *
***********/

struct L2BaseFeeParameters {
uint128 overhead;
uint128 scalar;
}
/// @notice The address of `SystemConfig` contract.
address public immutable systemConfig;

/*********************
* Storage Variables *
Expand All @@ -103,11 +99,6 @@ contract L1MessageQueueV2 is OwnableUpgradeable, IL1MessageQueueV2 {
/// @inheritdoc IL1MessageQueueV2
uint256 public nextUnfinalizedQueueIndex;

/// @notice The max gas limit of L1 transactions.
uint256 public maxGasLimit;

L2BaseFeeParameters public l2BaseFeeParameters;

/// @dev The storage slots for future usage.
uint256[45] private __gap;

Expand All @@ -134,25 +125,22 @@ contract L1MessageQueueV2 is OwnableUpgradeable, IL1MessageQueueV2 {
address _messenger,
address _scrollChain,
address _enforcedTxGateway,
address _messageQueueV1
address _messageQueueV1,
address _systemConfig
) {
_disableInitializers();

messenger = _messenger;
scrollChain = _scrollChain;
enforcedTxGateway = _enforcedTxGateway;
messageQueueV1 = _messageQueueV1;
systemConfig = _systemConfig;
}

/// @notice Initialize the storage of L1MessageQueue.
///
/// @param _maxGasLimit The maximum gas limit allowed in single transaction.
function initialize(uint256 _maxGasLimit, L2BaseFeeParameters memory _params) external initializer {
function initialize() external initializer {
OwnableUpgradeable.__Ownable_init();

_updateL2BaseFeeParameters(_params.overhead, _params.scalar);
_updateMaxGasLimit(_maxGasLimit);

uint256 _nextCrossDomainMessageIndex = IL1MessageQueueV1(messageQueueV1).nextCrossDomainMessageIndex();
nextCrossDomainMessageIndex = _nextCrossDomainMessageIndex;
nextUnfinalizedQueueIndex = _nextCrossDomainMessageIndex;
Expand All @@ -169,10 +157,10 @@ contract L1MessageQueueV2 is OwnableUpgradeable, IL1MessageQueueV2 {

/// @inheritdoc IL1MessageQueueV2
function estimatedL2BaseFee() public view returns (uint256) {
L2BaseFeeParameters memory parameters = l2BaseFeeParameters;
(, uint256 overhead, uint256 scalar) = SystemConfig(systemConfig).messageQueueParameters();
// this is unlikely to happen, use unchecked here
unchecked {
return (block.basefee * parameters.scalar) / PRECISION + parameters.overhead;
return (block.basefee * scalar) / PRECISION + overhead;
}
}

Expand Down Expand Up @@ -372,47 +360,10 @@ contract L1MessageQueueV2 is OwnableUpgradeable, IL1MessageQueueV2 {
}
}

/************************
* Restricted Functions *
************************/

/// @notice Update the parameters for l2 base fee formula.
/// @param overhead The value of overhead in l2 base fee formula.
/// @param scalar The value of scalar in l2 base fee formula.
function updateL2BaseFeeParameters(uint128 overhead, uint128 scalar) external onlyOwner {
_updateL2BaseFeeParameters(overhead, scalar);
}

/// @notice Update the max gas limit.
/// @param _newMaxGasLimit The new max gas limit.
function updateMaxGasLimit(uint256 _newMaxGasLimit) external onlyOwner {
_updateMaxGasLimit(_newMaxGasLimit);
}

/**********************
* Internal Functions *
**********************/

/// @dev Internal function to update the parameters for l2 base fee formula.
/// @param overhead The value of overhead in l2 base fee formula.
/// @param scalar The value of scalar in l2 base fee formula.
function _updateL2BaseFeeParameters(uint128 overhead, uint128 scalar) internal {
l2BaseFeeParameters = L2BaseFeeParameters(overhead, scalar);

emit UpdateL2BaseFeeParameters(overhead, scalar);
}

/// @dev Internal function to update the max gas limit.
/// @param _newMaxGasLimit The new max gas limit.
function _updateMaxGasLimit(uint256 _newMaxGasLimit) internal {
if (_newMaxGasLimit < INTRINSIC_GAS_TX) revert ErrorGasLimitBelowIntrinsicGas();

uint256 _oldMaxGasLimit = maxGasLimit;
maxGasLimit = _newMaxGasLimit;

emit UpdateMaxGasLimit(_oldMaxGasLimit, _newMaxGasLimit);
}

/// @dev Internal function to queue a L1 transaction.
/// @param _sender The address of sender who will initiate this transaction in L2.
/// @param _target The address of target contract to call in L2.
Expand Down Expand Up @@ -444,6 +395,7 @@ contract L1MessageQueueV2 is OwnableUpgradeable, IL1MessageQueueV2 {
/// @param _gasLimit The value of given gas limit.
/// @param _calldata The calldata for this message.
function _validateGasLimit(uint256 _gasLimit, bytes calldata _calldata) internal view {
(uint256 maxGasLimit, , ) = SystemConfig(systemConfig).messageQueueParameters();
if (_gasLimit > maxGasLimit) revert ErrorGasLimitExceeded();
// check if the gas limit is above intrinsic gas
uint256 intrinsicGas = calculateIntrinsicGasFee(_calldata);
Expand Down
76 changes: 76 additions & 0 deletions src/L1/system-contract/SystemConfig.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// SPDX-License-Identifier: MIT
pragma solidity =0.8.24;

import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";

contract SystemConfig is OwnableUpgradeable {
/***********
* Structs *
***********/

/// @param maxGasLimit The maximum gas limit allowed for each L1 message.
/// @param baseFeeOverhead The overhead used to calculate l2 base fee.
/// @param baseFeeScalar The scalar used to calculate l2 base fee.
struct MessageQueueParameters {
uint32 maxGasLimit;
uint112 baseFeeOverhead;
uint112 baseFeeScalar;
}

/*********************
* Storage Variables *
*********************/

/// @notice The parameters for message queue.
MessageQueueParameters public messageQueueParameters;

/// @dev The address of current authorized signer.
address private currentSigner;

/***************
* Constructor *
***************/

constructor() {
_disableInitializers();
}

function initialize(
address _owner,
address _signer,
MessageQueueParameters memory _params
) external initializer {
__Ownable_init();
transferOwnership(_owner);

currentSigner = _signer;
messageQueueParameters = _params;
}

/*************************
* Public View Functions *
*************************/

/// @notice Return the current authorized signer.
/// @return The authorized signer address.
function getSigner() external view returns (address) {
return currentSigner;
}

/************************
* Restricted Functions *
************************/

/// @notice Update the message queue parameters.
/// @param _params The new message queue parameters.
function updateMessageQueueParameters(MessageQueueParameters memory _params) external onlyOwner {
messageQueueParameters = _params;
}

/// @notice Update the current signer.
/// @dev Only the owner can call this function.
/// @param _newSigner The address of the new authorized signer.
function updateSigner(address _newSigner) external onlyOwner {
currentSigner = _newSigner;
}
}
Loading