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

draft PR for chained l1 message queue #69

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"eslint-plugin-promise": "^6.1.1",
"ethereum-waffle": "^3.0.0",
"ethers": "^6.11.1",
"hardhat": "^2.22.6",
"hardhat": "^2.22.17",
"hardhat-gas-reporter": "^1.0.4",
"husky": "^8.0.1",
"lint-staged": "^13.0.3",
Expand Down
4 changes: 2 additions & 2 deletions scripts/foundry/DeployL1BridgeContracts.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {L1ERC1155Gateway} from "../../src/L1/gateways/L1ERC1155Gateway.sol";
import {L1ERC721Gateway} from "../../src/L1/gateways/L1ERC721Gateway.sol";
import {L1ETHGateway} from "../../src/L1/gateways/L1ETHGateway.sol";
import {L1GatewayRouter} from "../../src/L1/gateways/L1GatewayRouter.sol";
import {L1MessageQueueWithGasPriceOracle} from "../../src/L1/rollup/L1MessageQueueWithGasPriceOracle.sol";
import {L1MessageQueueV1WithGasPriceOracle} from "../../src/L1/rollup/L1MessageQueueV1WithGasPriceOracle.sol";
import {L1ScrollMessenger} from "../../src/L1/L1ScrollMessenger.sol";
import {L1StandardERC20Gateway} from "../../src/L1/gateways/L1StandardERC20Gateway.sol";
import {L1WETHGateway} from "../../src/L1/gateways/L1WETHGateway.sol";
Expand Down Expand Up @@ -115,7 +115,7 @@ contract DeployL1BridgeContracts is Script {
}

function deployL1MessageQueue() internal {
L1MessageQueueWithGasPriceOracle impl = new L1MessageQueueWithGasPriceOracle(
L1MessageQueueV1WithGasPriceOracle impl = new L1MessageQueueV1WithGasPriceOracle(
L1_SCROLL_MESSENGER_PROXY_ADDR,
L1_SCROLL_CHAIN_PROXY_ADDR,
address(enforcedTxGateway)
Expand Down
10 changes: 5 additions & 5 deletions scripts/foundry/InitializeL1BridgeContracts.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ import {L1StandardERC20Gateway} from "../../src/L1/gateways/L1StandardERC20Gatew
import {L1WETHGateway} from "../../src/L1/gateways/L1WETHGateway.sol";
import {MultipleVersionRollupVerifier} from "../../src/L1/rollup/MultipleVersionRollupVerifier.sol";
import {ScrollChain} from "../../src/L1/rollup/ScrollChain.sol";
import {L1MessageQueue} from "../../src/L1/rollup/L1MessageQueue.sol";
import {L1MessageQueueWithGasPriceOracle} from "../../src/L1/rollup/L1MessageQueueWithGasPriceOracle.sol";
import {L1MessageQueueV1} from "../../src/L1/rollup/L1MessageQueueV1.sol";
import {L1MessageQueueV1WithGasPriceOracle} from "../../src/L1/rollup/L1MessageQueueV1WithGasPriceOracle.sol";
import {L2GasPriceOracle} from "../../src/L1/rollup/L2GasPriceOracle.sol";
import {EnforcedTxGateway} from "../../src/L1/gateways/EnforcedTxGateway.sol";

Expand Down Expand Up @@ -105,21 +105,21 @@ contract InitializeL1BridgeContracts is Script {
);
L2GasPriceOracle(L2_GAS_PRICE_ORACLE_PROXY_ADDR).updateWhitelist(L1_WHITELIST_ADDR);

// initialize L1MessageQueueWithGasPriceOracle
// initialize L1MessageQueueV1WithGasPriceOracle
proxyAdmin.upgrade(
ITransparentUpgradeableProxy(L1_MESSAGE_QUEUE_PROXY_ADDR),
L1_MESSAGE_QUEUE_IMPLEMENTATION_ADDR
);

L1MessageQueueWithGasPriceOracle(L1_MESSAGE_QUEUE_PROXY_ADDR).initialize(
L1MessageQueueV1WithGasPriceOracle(L1_MESSAGE_QUEUE_PROXY_ADDR).initialize(
L1_SCROLL_MESSENGER_PROXY_ADDR,
L1_SCROLL_CHAIN_PROXY_ADDR,
L1_ENFORCED_TX_GATEWAY_PROXY_ADDR,
L2_GAS_PRICE_ORACLE_PROXY_ADDR,
MAX_L1_MESSAGE_GAS_LIMIT
);

L1MessageQueueWithGasPriceOracle(L1_MESSAGE_QUEUE_PROXY_ADDR).initializeV2();
L1MessageQueueV1WithGasPriceOracle(L1_MESSAGE_QUEUE_PROXY_ADDR).initializeV2();

// initialize L1ScrollMessenger
proxyAdmin.upgrade(
Expand Down
6 changes: 3 additions & 3 deletions scripts/foundry/InitializeL1ScrollOwner.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {L1CustomERC20Gateway} from "../../src/L1/gateways/L1CustomERC20Gateway.s
import {L1ERC1155Gateway} from "../../src/L1/gateways/L1ERC1155Gateway.sol";
import {L1ERC721Gateway} from "../../src/L1/gateways/L1ERC721Gateway.sol";
import {L1GatewayRouter} from "../../src/L1/gateways/L1GatewayRouter.sol";
import {L1MessageQueue} from "../../src/L1/rollup/L1MessageQueue.sol";
import {L1MessageQueueV1} from "../../src/L1/rollup/L1MessageQueueV1.sol";
import {ScrollMessengerBase} from "../../src/libraries/ScrollMessengerBase.sol";
import {L2GasPriceOracle} from "../../src/L1/rollup/L2GasPriceOracle.sol";
import {MultipleVersionRollupVerifier} from "../../src/L1/rollup/MultipleVersionRollupVerifier.sol";
Expand Down Expand Up @@ -163,8 +163,8 @@ contract InitializeL1ScrollOwner is Script {

// delay 1 day, scroll multisig
_selectors = new bytes4[](2);
_selectors[0] = L1MessageQueue.updateGasOracle.selector;
_selectors[1] = L1MessageQueue.updateMaxGasLimit.selector;
_selectors[0] = L1MessageQueueV1.updateGasOracle.selector;
_selectors[1] = L1MessageQueueV1.updateMaxGasLimit.selector;
owner.updateAccess(L1_MESSAGE_QUEUE_PROXY_ADDR, _selectors, TIMELOCK_1DAY_DELAY_ROLE, true);
}

Expand Down
29 changes: 15 additions & 14 deletions src/L1/L1ScrollMessenger.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
pragma solidity =0.8.24;

import {IScrollChain} from "./rollup/IScrollChain.sol";
import {IL1MessageQueue} from "./rollup/IL1MessageQueue.sol";
import {IL1MessageQueueV1} from "./rollup/IL1MessageQueueV1.sol";
import {IL1MessageQueueV2} from "./rollup/IL1MessageQueueV2.sol";
Thegaram marked this conversation as resolved.
Show resolved Hide resolved
import {IL1ScrollMessenger} from "./IL1ScrollMessenger.sol";
import {ScrollConstants} from "../libraries/constants/ScrollConstants.sol";
import {IScrollMessenger} from "../libraries/IScrollMessenger.sol";
Expand Down Expand Up @@ -41,8 +42,8 @@ contract L1ScrollMessenger is ScrollMessengerBase, IL1ScrollMessenger {
/// @notice The address of Rollup contract.
address public immutable rollup;

/// @notice The address of L1MessageQueue contract.
address public immutable messageQueue;
/// @notice The address of L1MessageQueueV1 contract.
address public immutable messageQueueV1;

/***********
* Structs *
Expand Down Expand Up @@ -100,16 +101,16 @@ contract L1ScrollMessenger is ScrollMessengerBase, IL1ScrollMessenger {
constructor(
address _counterpart,
address _rollup,
address _messageQueue
address _messageQueueV1
) ScrollMessengerBase(_counterpart) {
if (_rollup == address(0) || _messageQueue == address(0)) {
if (_rollup == address(0) || _messageQueueV1 == address(0)) {
revert ErrorZeroAddress();
}

_disableInitializers();

rollup = _rollup;
messageQueue = _messageQueue;
messageQueueV1 = _messageQueueV1;
}

/// @notice Initialize the storage of L1ScrollMessenger.
Expand Down Expand Up @@ -182,7 +183,7 @@ contract L1ScrollMessenger is ScrollMessengerBase, IL1ScrollMessenger {
}

// @note check more `_to` address to avoid attack in the future when we add more gateways.
require(_to != messageQueue, "Forbid to call message queue");
require(_to != messageQueueV1, "Forbid to call message queue");
_validateTargetAddress(_to);

// @note This usually will never happen, just in case.
Expand Down Expand Up @@ -223,7 +224,7 @@ contract L1ScrollMessenger is ScrollMessengerBase, IL1ScrollMessenger {
require(!isL1MessageDropped[_xDomainCalldataHash], "Message already dropped");

// compute and deduct the messaging fee to fee vault.
uint256 _fee = IL1MessageQueue(messageQueue).estimateCrossDomainMessageFee(_newGasLimit);
uint256 _fee = IL1MessageQueueV1(messageQueueV1).estimateCrossDomainMessageFee(_newGasLimit);

// charge relayer fee
require(msg.value >= _fee, "Insufficient msg.value for fee");
Expand All @@ -233,8 +234,8 @@ contract L1ScrollMessenger is ScrollMessengerBase, IL1ScrollMessenger {
}

// enqueue the new transaction
uint256 _nextQueueIndex = IL1MessageQueue(messageQueue).nextCrossDomainMessageIndex();
IL1MessageQueue(messageQueue).appendCrossDomainMessage(counterpart, _newGasLimit, _xDomainCalldata);
uint256 _nextQueueIndex = IL1MessageQueueV1(messageQueueV1).nextCrossDomainMessageIndex();
IL1MessageQueueV1(messageQueueV1).appendCrossDomainMessage(counterpart, _newGasLimit, _xDomainCalldata);

ReplayState memory _replayState = replayStates[_xDomainCalldataHash];
// update the replayed message chain.
Expand Down Expand Up @@ -300,7 +301,7 @@ contract L1ScrollMessenger is ScrollMessengerBase, IL1ScrollMessenger {
// check message is skipped and drop it.
// @note If the list is very long, the message may never be dropped.
while (true) {
IL1MessageQueue(messageQueue).dropCrossDomainMessage(_lastIndex);
IL1MessageQueueV1(messageQueueV1).dropCrossDomainMessage(_lastIndex);
_lastIndex = prevReplayIndex[_lastIndex];
if (_lastIndex == 0) break;
unchecked {
Expand Down Expand Up @@ -343,19 +344,19 @@ contract L1ScrollMessenger is ScrollMessengerBase, IL1ScrollMessenger {
address _refundAddress
) internal nonReentrant {
// compute the actual cross domain message calldata.
uint256 _messageNonce = IL1MessageQueue(messageQueue).nextCrossDomainMessageIndex();
uint256 _messageNonce = IL1MessageQueueV1(messageQueueV1).nextCrossDomainMessageIndex();
bytes memory _xDomainCalldata = _encodeXDomainCalldata(_msgSender(), _to, _value, _messageNonce, _message);

// compute and deduct the messaging fee to fee vault.
uint256 _fee = IL1MessageQueue(messageQueue).estimateCrossDomainMessageFee(_gasLimit);
uint256 _fee = IL1MessageQueueV1(messageQueueV1).estimateCrossDomainMessageFee(_gasLimit);
require(msg.value >= _fee + _value, "Insufficient msg.value");
if (_fee > 0) {
(bool _success, ) = feeVault.call{value: _fee}("");
require(_success, "Failed to deduct the fee");
}

// append message to L1MessageQueue
IL1MessageQueue(messageQueue).appendCrossDomainMessage(counterpart, _gasLimit, _xDomainCalldata);
IL1MessageQueueV1(messageQueueV1).appendCrossDomainMessage(counterpart, _gasLimit, _xDomainCalldata);

// record the message hash for future use.
bytes32 _xDomainCalldataHash = keccak256(_xDomainCalldata);
Expand Down
6 changes: 3 additions & 3 deletions src/L1/gateways/EnforcedTxGateway.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {EIP712Upgradeable} from "@openzeppelin/contracts-upgradeable/utils/crypt
import {ReentrancyGuardUpgradeable} from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
import {PausableUpgradeable} from "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";

import {IL1MessageQueue} from "../rollup/IL1MessageQueue.sol";
import {IL1MessageQueueV2} from "../rollup/IL1MessageQueueV2.sol";

// solhint-disable reason-string

Expand Down Expand Up @@ -182,15 +182,15 @@ contract EnforcedTxGateway is OwnableUpgradeable, ReentrancyGuardUpgradeable, Pa
address _messageQueue = messageQueue;

// charge fee
uint256 _fee = IL1MessageQueue(_messageQueue).estimateCrossDomainMessageFee(_gasLimit);
uint256 _fee = IL1MessageQueueV2(_messageQueue).estimateCrossDomainMessageFee(_gasLimit);
require(msg.value >= _fee, "Insufficient value for fee");
if (_fee > 0) {
(bool _success, ) = feeVault.call{value: _fee}("");
require(_success, "Failed to deduct the fee");
}

// append transaction
IL1MessageQueue(_messageQueue).appendEnforcedTransaction(_sender, _target, _value, _gasLimit, _data);
IL1MessageQueueV2(_messageQueue).appendEnforcedTransaction(_sender, _target, _value, _gasLimit, _data);

// refund fee to `_refundAddress`
unchecked {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

pragma solidity ^0.8.24;

interface IL1MessageQueue {
interface IL1MessageQueueV1 {
/**********
* Events *
**********/
Expand Down
107 changes: 107 additions & 0 deletions src/L1/rollup/IL1MessageQueueV2.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.24;

interface IL1MessageQueueV2 {
/**********
* Events *
**********/

/// @notice Emitted when a new L1 => L2 transaction is appended to the queue.
/// @param sender The address of account who initiates the transaction.
/// @param target The address of account who will receive the transaction.
/// @param value The value passed with the transaction.
/// @param queueIndex The index of this transaction in the queue.
/// @param gasLimit Gas limit required to complete the message relay on L2.
/// @param data The calldata of the transaction.
event QueueTransaction(
address indexed sender,
address indexed target,
uint256 value,
uint64 queueIndex,
uint256 gasLimit,
bytes data
);

/// @notice Emitted when some L1 => L2 transactions are finalized in L1.
/// @param finalizedIndex The last index of messages finalized.
event FinalizedDequeuedTransaction(uint256 finalizedIndex);

event UpdateL2BaseFeeParameters(uint256 overhead, uint256 scalar);

/// @notice Emitted when owner updates max gas limit.
/// @param _oldMaxGasLimit The old max gas limit.
/// @param _newMaxGasLimit The new max gas limit.
event UpdateMaxGasLimit(uint256 _oldMaxGasLimit, uint256 _newMaxGasLimit);

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

/// @notice The start index of all unfinalized messages.
function nextUnfinalizedQueueIndex() external view returns (uint256);

/// @notice Return the index of next appended message.
/// @dev Also the total number of appended messages, including messages in `L1MessageQueueV1`.
function nextCrossDomainMessageIndex() external view returns (uint256);

/// @notice Return the amount of ETH should pay for cross domain message.
/// @param gasLimit Gas limit required to complete the message relay on L2.
function estimateCrossDomainMessageFee(uint256 gasLimit) external view returns (uint256);

/// @notice Return the estimated base fee in L2.
function estimatedL2BaseFee() external view returns (uint256);

/// @notice Return the amount of intrinsic gas fee should pay for cross domain message.
/// @param data The calldata of L1-initiated transaction.
function calculateIntrinsicGasFee(bytes calldata data) external view returns (uint256);

/// @notice Return the hash of a L1 message.
/// @param sender The address of sender.
/// @param queueIndex The queue index of this message.
/// @param value The amount of Ether transfer to target.
/// @param target The address of target.
/// @param gasLimit The gas limit provided.
/// @param data The calldata passed to target address.
function computeTransactionHash(
address sender,
uint256 queueIndex,
uint256 value,
address target,
uint256 gasLimit,
bytes calldata data
) external view returns (bytes32);

/*****************************
* Public Mutating Functions *
*****************************/

/// @notice Append a L1 to L2 message into this contract.
/// @param target The address of target contract to call in L2.
/// @param gasLimit The maximum gas should be used for relay this message in L2.
/// @param data The calldata passed to target contract.
function appendCrossDomainMessage(
address target,
uint256 gasLimit,
bytes calldata data
) external;

/// @notice Append an enforced transaction to this contract.
/// @dev The address of sender should be an EOA.
/// @param sender The address of sender who will initiate this transaction in L2.
/// @param target The address of target contract to call in L2.
/// @param value The value passed
/// @param gasLimit The maximum gas should be used for this transaction in L2.
/// @param data The calldata passed to target contract.
function appendEnforcedTransaction(
address sender,
address target,
uint256 value,
uint256 gasLimit,
bytes calldata data
) external;

/// @notice Finalize status of popped messages.
/// @param newFinalizedQueueIndexPlusOne The index of message to finalize plus one.
function finalizePoppedCrossDomainMessage(uint256 newFinalizedQueueIndexPlusOne) external;
}
4 changes: 2 additions & 2 deletions src/L1/rollup/IL1MessageQueueWithGasPriceOracle.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

pragma solidity ^0.8.24;

import {IL1MessageQueue} from "./IL1MessageQueue.sol";
import {IL1MessageQueueV1} from "./IL1MessageQueueV1.sol";

interface IL1MessageQueueWithGasPriceOracle is IL1MessageQueue {
interface IL1MessageQueueWithGasPriceOracle is IL1MessageQueueV1 {
/**********
* Events *
**********/
Expand Down
Loading