Overview
ETH Balance
ETH Value
$0.00Cross-Chain Transactions
Loading...
Loading
Contract Name:
L2MessageQueue
Compiler Version
v0.8.16+commit.07a7930e
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity =0.8.16;
import {AppendOnlyMerkleTree} from "../../libraries/common/AppendOnlyMerkleTree.sol";
import {OwnableBase} from "../../libraries/common/OwnableBase.sol";
/// @title L2MessageQueue
/// @notice The original idea is from Optimism, see [OVM_L2ToL1MessagePasser](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/L2/predeploys/OVM_L2ToL1MessagePasser.sol).
/// The L2 to L1 Message Passer is a utility contract which facilitate an L1 proof of the
/// of a message on L2. The L1 Cross Domain Messenger performs this proof in its
/// _verifyStorageProof function, which verifies the existence of the transaction hash in this
/// contract's `sentMessages` mapping.
contract L2MessageQueue is AppendOnlyMerkleTree, OwnableBase {
/**********
* Events *
**********/
/// @notice Emitted when a new message is added to the merkle tree.
/// @param index The index of the corresponding message.
/// @param messageHash The hash of the corresponding message.
event AppendMessage(uint256 index, bytes32 messageHash);
/*************
* Variables *
*************/
/// @notice The address of L2ScrollMessenger contract.
address public messenger;
/***************
* Constructor *
***************/
constructor(address _owner) {
_transferOwnership(_owner);
}
/// @notice Initialize the state of `L2MessageQueue`
/// @dev You are not allowed to initialize when there are some messages appended.
/// @param _messenger The address of messenger to update.
function initialize(address _messenger) external onlyOwner {
require(nextMessageIndex == 0, "cannot initialize");
_initializeMerkleTree();
messenger = _messenger;
}
/*****************************
* Public Mutating Functions *
*****************************/
/// @notice record the message to merkle tree and compute the new root.
/// @param _messageHash The hash of the new added message.
function appendMessage(bytes32 _messageHash) external returns (bytes32) {
require(msg.sender == messenger, "only messenger");
(uint256 _currentNonce, bytes32 _currentRoot) = _appendMessageHash(_messageHash);
// We can use the event to compute the merkle tree locally.
emit AppendMessage(_currentNonce, _messageHash);
return _currentRoot;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;
abstract contract AppendOnlyMerkleTree {
/// @dev The maximum height of the withdraw merkle tree.
uint256 private constant MAX_TREE_HEIGHT = 40;
/// @notice The merkle root of the current merkle tree.
/// @dev This is actual equal to `branches[n]`.
bytes32 public messageRoot;
/// @notice The next unused message index.
uint256 public nextMessageIndex;
/// @notice The list of zero hash in each height.
bytes32[MAX_TREE_HEIGHT] private zeroHashes;
/// @notice The list of minimum merkle proofs needed to compute next root.
/// @dev Only first `n` elements are used, where `n` is the minimum value that `2^{n-1} >= currentMaxNonce + 1`.
/// It means we only use `currentMaxNonce + 1` leaf nodes to construct the merkle tree.
bytes32[MAX_TREE_HEIGHT] public branches;
function _initializeMerkleTree() internal {
// Compute hashes in empty sparse Merkle tree
for (uint256 height = 0; height + 1 < MAX_TREE_HEIGHT; height++) {
zeroHashes[height + 1] = _efficientHash(zeroHashes[height], zeroHashes[height]);
}
}
function _appendMessageHash(bytes32 _messageHash) internal returns (uint256, bytes32) {
require(zeroHashes[1] != bytes32(0), "call before initialization");
uint256 _currentMessageIndex = nextMessageIndex;
bytes32 _hash = _messageHash;
uint256 _height = 0;
while (_currentMessageIndex != 0) {
if (_currentMessageIndex % 2 == 0) {
// it may be used in next round.
branches[_height] = _hash;
// it's a left child, the right child must be null
_hash = _efficientHash(_hash, zeroHashes[_height]);
} else {
// it's a right child, use previously computed hash
_hash = _efficientHash(branches[_height], _hash);
}
unchecked {
_height += 1;
}
_currentMessageIndex >>= 1;
}
branches[_height] = _hash;
messageRoot = _hash;
_currentMessageIndex = nextMessageIndex;
unchecked {
nextMessageIndex = _currentMessageIndex + 1;
}
return (_currentMessageIndex, _hash);
}
function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
// solhint-disable-next-line no-inline-assembly
assembly {
mstore(0x00, a)
mstore(0x20, b)
value := keccak256(0x00, 0x40)
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;
abstract contract OwnableBase {
/**********
* Events *
**********/
/// @notice Emitted when owner is changed by current owner.
/// @param _oldOwner The address of previous owner.
/// @param _newOwner The address of new owner.
event OwnershipTransferred(address indexed _oldOwner, address indexed _newOwner);
/*************
* Variables *
*************/
/// @notice The address of the current owner.
address public owner;
/**********************
* Function Modifiers *
**********************/
/// @dev Throws if called by any account other than the owner.
modifier onlyOwner() {
require(owner == msg.sender, "caller is not the owner");
_;
}
/************************
* Restricted Functions *
************************/
/// @notice Leaves the contract without owner. It will not be possible to call
/// `onlyOwner` functions anymore. Can only be called by the current owner.
///
/// @dev Renouncing ownership will leave the contract without an owner,
/// thereby removing any functionality that is only available to the owner.
function renounceOwnership() public onlyOwner {
_transferOwnership(address(0));
}
/// @notice Transfers ownership of the contract to a new account (`newOwner`).
/// Can only be called by the current owner.
function transferOwnership(address _newOwner) public onlyOwner {
require(_newOwner != address(0), "new owner is the zero address");
_transferOwnership(_newOwner);
}
/**********************
* Internal Functions *
**********************/
/// @dev Transfers ownership of the contract to a new account (`newOwner`).
/// Internal function without access restriction.
function _transferOwnership(address _newOwner) internal {
address _oldOwner = owner;
owner = _newOwner;
emit OwnershipTransferred(_oldOwner, _newOwner);
}
}{
"remappings": [
"@openzeppelin/=node_modules/@openzeppelin/",
"ds-test/=lib/ds-test/src/",
"forge-std/=lib/forge-std/src/",
"hardhat/=node_modules/hardhat/",
"solmate/=lib/solmate/src/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs"
},
"outputSelection": {
"*": {
"": [
"ast"
],
"*": [
"abi",
"evm.bytecode",
"evm.deployedBytecode",
"evm.methodIdentifiers",
"metadata"
]
}
},
"evmVersion": "london",
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"messageHash","type":"bytes32"}],"name":"AppendMessage","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"_newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[{"internalType":"bytes32","name":"_messageHash","type":"bytes32"}],"name":"appendMessage","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"branches","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_messenger","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"messageRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"messenger","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextMessageIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b50600436106100935760003560e01c806383cc76601161006657806383cc7660146100fc5780638da5cb5b1461010f578063c4d66de814610122578063d4b9f4fa14610135578063f2fde38b1461013e57600080fd5b806326aad7b7146100985780633cb747bf146100b4578063600a2e77146100df578063715018a6146100f2575b600080fd5b6100a160015481565b6040519081526020015b60405180910390f35b6053546100c7906001600160a01b031681565b6040516001600160a01b0390911681526020016100ab565b6100a16100ed36600461054a565b610151565b6100fa6101f6565b005b6100a161010a36600461054a565b61022c565b6052546100c7906001600160a01b031681565b6100fa610130366004610563565b610243565b6100a160005481565b6100fa61014c366004610563565b6102db565b6053546000906001600160a01b031633146101a45760405162461bcd60e51b815260206004820152600e60248201526d37b7363c9036b2b9b9b2b733b2b960911b60448201526064015b60405180910390fd5b6000806101b084610367565b60408051838152602081018890529294509092507ffaa617c2d8ce12c62637dbce76efcc18dae60574aa95709bdcedce7e76071693910160405180910390a19392505050565b6052546001600160a01b031633146102205760405162461bcd60e51b815260040161019b90610593565b61022a6000610486565b565b602a816028811061023c57600080fd5b0154905081565b6052546001600160a01b0316331461026d5760405162461bcd60e51b815260040161019b90610593565b600154156102b15760405162461bcd60e51b815260206004820152601160248201527063616e6e6f7420696e697469616c697a6560781b604482015260640161019b565b6102b96104d8565b605380546001600160a01b0319166001600160a01b0392909216919091179055565b6052546001600160a01b031633146103055760405162461bcd60e51b815260040161019b90610593565b6001600160a01b03811661035b5760405162461bcd60e51b815260206004820152601d60248201527f6e6577206f776e657220697320746865207a65726f2061646472657373000000604482015260640161019b565b61036481610486565b50565b60035460009081906103bb5760405162461bcd60e51b815260206004820152601a60248201527f63616c6c206265666f726520696e697469616c697a6174696f6e000000000000604482015260640161019b565b6001548360005b8215610456576103d36002846105e0565b60000361041f5781602a82602881106103ee576103ee6105ca565b01556104188260028360288110610407576104076105ca565b015460009182526020526040902090565b915061044a565b610447602a8260288110610435576104356105ca565b01548360009182526020526040902090565b91505b600192831c92016103c2565b81602a826028811061046a5761046a6105ca565b0155506000819055600180548082019091559590945092505050565b605280546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60005b60286104e8826001610618565b10156103645761051960028260288110610504576105046105ca565b015460028360288110610407576104076105ca565b6002610526836001610618565b60288110610536576105366105ca565b01558061054281610631565b9150506104db565b60006020828403121561055c57600080fd5b5035919050565b60006020828403121561057557600080fd5b81356001600160a01b038116811461058c57600080fd5b9392505050565b60208082526017908201527f63616c6c6572206973206e6f7420746865206f776e6572000000000000000000604082015260600190565b634e487b7160e01b600052603260045260246000fd5b6000826105fd57634e487b7160e01b600052601260045260246000fd5b500690565b634e487b7160e01b600052601160045260246000fd5b8082018082111561062b5761062b610602565b92915050565b60006001820161064357610643610602565b506001019056fea26469706673582212208fb1cb9933bb17dd0a7c17de7c890919b08d2fd7eb2bede7b41caa32709b30b564736f6c63430008100033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100935760003560e01c806383cc76601161006657806383cc7660146100fc5780638da5cb5b1461010f578063c4d66de814610122578063d4b9f4fa14610135578063f2fde38b1461013e57600080fd5b806326aad7b7146100985780633cb747bf146100b4578063600a2e77146100df578063715018a6146100f2575b600080fd5b6100a160015481565b6040519081526020015b60405180910390f35b6053546100c7906001600160a01b031681565b6040516001600160a01b0390911681526020016100ab565b6100a16100ed36600461054a565b610151565b6100fa6101f6565b005b6100a161010a36600461054a565b61022c565b6052546100c7906001600160a01b031681565b6100fa610130366004610563565b610243565b6100a160005481565b6100fa61014c366004610563565b6102db565b6053546000906001600160a01b031633146101a45760405162461bcd60e51b815260206004820152600e60248201526d37b7363c9036b2b9b9b2b733b2b960911b60448201526064015b60405180910390fd5b6000806101b084610367565b60408051838152602081018890529294509092507ffaa617c2d8ce12c62637dbce76efcc18dae60574aa95709bdcedce7e76071693910160405180910390a19392505050565b6052546001600160a01b031633146102205760405162461bcd60e51b815260040161019b90610593565b61022a6000610486565b565b602a816028811061023c57600080fd5b0154905081565b6052546001600160a01b0316331461026d5760405162461bcd60e51b815260040161019b90610593565b600154156102b15760405162461bcd60e51b815260206004820152601160248201527063616e6e6f7420696e697469616c697a6560781b604482015260640161019b565b6102b96104d8565b605380546001600160a01b0319166001600160a01b0392909216919091179055565b6052546001600160a01b031633146103055760405162461bcd60e51b815260040161019b90610593565b6001600160a01b03811661035b5760405162461bcd60e51b815260206004820152601d60248201527f6e6577206f776e657220697320746865207a65726f2061646472657373000000604482015260640161019b565b61036481610486565b50565b60035460009081906103bb5760405162461bcd60e51b815260206004820152601a60248201527f63616c6c206265666f726520696e697469616c697a6174696f6e000000000000604482015260640161019b565b6001548360005b8215610456576103d36002846105e0565b60000361041f5781602a82602881106103ee576103ee6105ca565b01556104188260028360288110610407576104076105ca565b015460009182526020526040902090565b915061044a565b610447602a8260288110610435576104356105ca565b01548360009182526020526040902090565b91505b600192831c92016103c2565b81602a826028811061046a5761046a6105ca565b0155506000819055600180548082019091559590945092505050565b605280546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60005b60286104e8826001610618565b10156103645761051960028260288110610504576105046105ca565b015460028360288110610407576104076105ca565b6002610526836001610618565b60288110610536576105366105ca565b01558061054281610631565b9150506104db565b60006020828403121561055c57600080fd5b5035919050565b60006020828403121561057557600080fd5b81356001600160a01b038116811461058c57600080fd5b9392505050565b60208082526017908201527f63616c6c6572206973206e6f7420746865206f776e6572000000000000000000604082015260600190565b634e487b7160e01b600052603260045260246000fd5b6000826105fd57634e487b7160e01b600052601260045260246000fd5b500690565b634e487b7160e01b600052601160045260246000fd5b8082018082111561062b5761062b610602565b92915050565b60006001820161064357610643610602565b506001019056fea26469706673582212208fb1cb9933bb17dd0a7c17de7c890919b08d2fd7eb2bede7b41caa32709b30b564736f6c63430008100033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.