文件 1 的 12:Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 2 的 12:ICrossDomainMessenger.sol
pragma solidity >0.5.0 <0.9.0;
interface ICrossDomainMessenger {
event SentMessage(
address indexed target,
address sender,
bytes message,
uint256 messageNonce,
uint256 gasLimit
);
event RelayedMessage(bytes32 indexed msgHash);
event FailedRelayedMessage(bytes32 indexed msgHash);
function xDomainMessageSender() external view returns (address);
function sendMessage(
address _target,
bytes calldata _message,
uint32 _gasLimit
) external;
}
文件 3 的 12:IL1CrossDomainMessenger.sol
pragma solidity ^0.8.9;
import {Lib_OVMCodec} from '../../libraries/codec/Lib_OVMCodec.sol';
import {ICrossDomainMessenger} from '../../libraries/bridge/ICrossDomainMessenger.sol';
interface IL1CrossDomainMessenger is ICrossDomainMessenger {
struct L2MessageInclusionProof {
bytes32 stateRoot;
Lib_OVMCodec.ChainBatchHeader stateRootBatchHeader;
Lib_OVMCodec.ChainInclusionProof stateRootProof;
bytes stateTrieWitness;
bytes storageTrieWitness;
}
function relayMessage(
address _target,
address _sender,
bytes memory _message,
uint256 _messageNonce,
L2MessageInclusionProof memory _proof
) external;
function replayMessage(
address _target,
address _sender,
bytes memory _message,
uint256 _queueIndex,
uint32 _oldGasLimit,
uint32 _newGasLimit
) external;
}
文件 4 的 12:L1MultiMessageRelayer.sol
pragma solidity >0.7.5;
pragma experimental ABIEncoderV2;
import {IL1CrossDomainMessenger} from './IL1CrossDomainMessenger.sol';
import {Lib_AddressResolver} from '../../libraries/resolver/Lib_AddressResolver.sol';
contract L1MultiMessageRelayer is Lib_AddressResolver {
struct L2ToL1Message {
address target;
address sender;
bytes message;
uint256 messageNonce;
IL1CrossDomainMessenger.L2MessageInclusionProof proof;
}
constructor(address _libAddressManager)
Lib_AddressResolver(_libAddressManager)
{}
modifier onlyBatchRelayer() {
require(
msg.sender == resolve('L2BatchMessageRelayer'),
'L1MultiMessageRelayer: Function can only be called by the L2BatchMessageRelayer'
);
_;
}
function batchRelayMessages(L2ToL1Message[] calldata _messages)
external
onlyBatchRelayer
{
IL1CrossDomainMessenger messenger = IL1CrossDomainMessenger(
resolve('Proxy__L1CrossDomainMessenger')
);
for (uint256 i = 0; i < _messages.length; i++) {
L2ToL1Message memory message = _messages[i];
messenger.relayMessage(
message.target,
message.sender,
message.message,
message.messageNonce,
message.proof
);
}
}
}
文件 5 的 12:Lib_AddressManager.sol
pragma solidity ^0.8.9;
import {Ownable} from '@openzeppelin/contracts/access/Ownable.sol';
contract Lib_AddressManager is Ownable {
event AddressSet(
string indexed _name,
address _newAddress,
address _oldAddress
);
mapping(bytes32 => address) private addresses;
function setAddress(string memory _name, address _address)
external
onlyOwner
{
bytes32 nameHash = _getNameHash(_name);
address oldAddress = addresses[nameHash];
addresses[nameHash] = _address;
emit AddressSet(_name, _address, oldAddress);
}
function getAddress(string memory _name) external view returns (address) {
return addresses[_getNameHash(_name)];
}
function _getNameHash(string memory _name) internal pure returns (bytes32) {
return keccak256(abi.encodePacked(_name));
}
}
文件 6 的 12:Lib_AddressResolver.sol
pragma solidity ^0.8.9;
import {Lib_AddressManager} from './Lib_AddressManager.sol';
abstract contract Lib_AddressResolver {
Lib_AddressManager public libAddressManager;
constructor(address _libAddressManager) {
libAddressManager = Lib_AddressManager(_libAddressManager);
}
function resolve(string memory _name) public view returns (address) {
return libAddressManager.getAddress(_name);
}
}
文件 7 的 12:Lib_Bytes32Utils.sol
pragma solidity ^0.8.9;
library Lib_Bytes32Utils {
function toBool(bytes32 _in) internal pure returns (bool) {
return _in != 0;
}
function fromBool(bool _in) internal pure returns (bytes32) {
return bytes32(uint256(_in ? 1 : 0));
}
function toAddress(bytes32 _in) internal pure returns (address) {
return address(uint160(uint256(_in)));
}
function fromAddress(address _in) internal pure returns (bytes32) {
return bytes32(uint256(uint160(_in)));
}
}
文件 8 的 12:Lib_BytesUtils.sol
pragma solidity ^0.8.9;
library Lib_BytesUtils {
function slice(
bytes memory _bytes,
uint256 _start,
uint256 _length
) internal pure returns (bytes memory) {
require(_length + 31 >= _length, 'slice_overflow');
require(_start + _length >= _start, 'slice_overflow');
require(_bytes.length >= _start + _length, 'slice_outOfBounds');
bytes memory tempBytes;
assembly {
switch iszero(_length)
case 0 {
tempBytes := mload(0x40)
let lengthmod := and(_length, 31)
let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))
let end := add(mc, _length)
for {
let cc := add(
add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))),
_start
)
} lt(mc, end) {
mc := add(mc, 0x20)
cc := add(cc, 0x20)
} {
mstore(mc, mload(cc))
}
mstore(tempBytes, _length)
mstore(0x40, and(add(mc, 31), not(31)))
}
default {
tempBytes := mload(0x40)
mstore(tempBytes, 0)
mstore(0x40, add(tempBytes, 0x20))
}
}
return tempBytes;
}
function slice(bytes memory _bytes, uint256 _start)
internal
pure
returns (bytes memory)
{
if (_start >= _bytes.length) {
return bytes('');
}
return slice(_bytes, _start, _bytes.length - _start);
}
function toBytes32(bytes memory _bytes) internal pure returns (bytes32) {
if (_bytes.length < 32) {
bytes32 ret;
assembly {
ret := mload(add(_bytes, 32))
}
return ret;
}
return abi.decode(_bytes, (bytes32));
}
function toUint256(bytes memory _bytes) internal pure returns (uint256) {
return uint256(toBytes32(_bytes));
}
function toNibbles(bytes memory _bytes) internal pure returns (bytes memory) {
bytes memory nibbles = new bytes(_bytes.length * 2);
for (uint256 i = 0; i < _bytes.length; i++) {
nibbles[i * 2] = _bytes[i] >> 4;
nibbles[i * 2 + 1] = bytes1(uint8(_bytes[i]) % 16);
}
return nibbles;
}
function fromNibbles(bytes memory _bytes)
internal
pure
returns (bytes memory)
{
bytes memory ret = new bytes(_bytes.length / 2);
for (uint256 i = 0; i < ret.length; i++) {
ret[i] = (_bytes[i * 2] << 4) | (_bytes[i * 2 + 1]);
}
return ret;
}
function equal(bytes memory _bytes, bytes memory _other)
internal
pure
returns (bool)
{
return keccak256(_bytes) == keccak256(_other);
}
}
文件 9 的 12:Lib_OVMCodec.sol
pragma solidity ^0.8.9;
import {Lib_RLPReader} from '../rlp/Lib_RLPReader.sol';
import {Lib_RLPWriter} from '../rlp/Lib_RLPWriter.sol';
import {Lib_BytesUtils} from '../utils/Lib_BytesUtils.sol';
import {Lib_Bytes32Utils} from '../utils/Lib_Bytes32Utils.sol';
library Lib_OVMCodec {
enum QueueOrigin {
SEQUENCER_QUEUE,
L1TOL2_QUEUE
}
struct EVMAccount {
uint256 nonce;
uint256 balance;
bytes32 storageRoot;
bytes32 codeHash;
}
struct ChainBatchHeader {
uint256 batchIndex;
bytes32 batchRoot;
uint256 batchSize;
uint256 prevTotalElements;
bytes extraData;
}
struct ChainInclusionProof {
uint256 index;
bytes32[] siblings;
}
struct Transaction {
uint256 timestamp;
uint256 blockNumber;
QueueOrigin l1QueueOrigin;
address l1TxOrigin;
address entrypoint;
uint256 gasLimit;
bytes data;
}
struct TransactionChainElement {
bool isSequenced;
uint256 queueIndex;
uint256 timestamp;
uint256 blockNumber;
bytes txData;
}
struct QueueElement {
bytes32 transactionHash;
uint40 timestamp;
uint40 blockNumber;
}
function encodeTransaction(Transaction memory _transaction)
internal
pure
returns (bytes memory)
{
return
abi.encodePacked(
_transaction.timestamp,
_transaction.blockNumber,
_transaction.l1QueueOrigin,
_transaction.l1TxOrigin,
_transaction.entrypoint,
_transaction.gasLimit,
_transaction.data
);
}
function hashTransaction(Transaction memory _transaction)
internal
pure
returns (bytes32)
{
return keccak256(encodeTransaction(_transaction));
}
function decodeEVMAccount(bytes memory _encoded)
internal
pure
returns (EVMAccount memory)
{
Lib_RLPReader.RLPItem[] memory accountState = Lib_RLPReader.readList(
_encoded
);
return
EVMAccount({
nonce: Lib_RLPReader.readUint256(accountState[0]),
balance: Lib_RLPReader.readUint256(accountState[1]),
storageRoot: Lib_RLPReader.readBytes32(accountState[2]),
codeHash: Lib_RLPReader.readBytes32(accountState[3])
});
}
function hashBatchHeader(Lib_OVMCodec.ChainBatchHeader memory _batchHeader)
internal
pure
returns (bytes32)
{
return
keccak256(
abi.encode(
_batchHeader.batchRoot,
_batchHeader.batchSize,
_batchHeader.prevTotalElements,
_batchHeader.extraData
)
);
}
}
文件 10 的 12:Lib_RLPReader.sol
pragma solidity ^0.8.9;
library Lib_RLPReader {
uint256 internal constant MAX_LIST_LENGTH = 32;
enum RLPItemType {
DATA_ITEM,
LIST_ITEM
}
struct RLPItem {
uint256 length;
uint256 ptr;
}
function toRLPItem(bytes memory _in) internal pure returns (RLPItem memory) {
uint256 ptr;
assembly {
ptr := add(_in, 32)
}
return RLPItem({length: _in.length, ptr: ptr});
}
function readList(RLPItem memory _in)
internal
pure
returns (RLPItem[] memory)
{
(uint256 listOffset, , RLPItemType itemType) = _decodeLength(_in);
require(itemType == RLPItemType.LIST_ITEM, 'Invalid RLP list value.');
RLPItem[] memory out = new RLPItem[](MAX_LIST_LENGTH);
uint256 itemCount = 0;
uint256 offset = listOffset;
while (offset < _in.length) {
require(
itemCount < MAX_LIST_LENGTH,
'Provided RLP list exceeds max list length.'
);
(uint256 itemOffset, uint256 itemLength, ) = _decodeLength(
RLPItem({length: _in.length - offset, ptr: _in.ptr + offset})
);
out[itemCount] = RLPItem({
length: itemLength + itemOffset,
ptr: _in.ptr + offset
});
itemCount += 1;
offset += itemOffset + itemLength;
}
assembly {
mstore(out, itemCount)
}
return out;
}
function readList(bytes memory _in) internal pure returns (RLPItem[] memory) {
return readList(toRLPItem(_in));
}
function readBytes(RLPItem memory _in) internal pure returns (bytes memory) {
(
uint256 itemOffset,
uint256 itemLength,
RLPItemType itemType
) = _decodeLength(_in);
require(itemType == RLPItemType.DATA_ITEM, 'Invalid RLP bytes value.');
return _copy(_in.ptr, itemOffset, itemLength);
}
function readBytes(bytes memory _in) internal pure returns (bytes memory) {
return readBytes(toRLPItem(_in));
}
function readString(RLPItem memory _in)
internal
pure
returns (string memory)
{
return string(readBytes(_in));
}
function readString(bytes memory _in) internal pure returns (string memory) {
return readString(toRLPItem(_in));
}
function readBytes32(RLPItem memory _in) internal pure returns (bytes32) {
require(_in.length <= 33, 'Invalid RLP bytes32 value.');
(
uint256 itemOffset,
uint256 itemLength,
RLPItemType itemType
) = _decodeLength(_in);
require(itemType == RLPItemType.DATA_ITEM, 'Invalid RLP bytes32 value.');
uint256 ptr = _in.ptr + itemOffset;
bytes32 out;
assembly {
out := mload(ptr)
if lt(itemLength, 32) {
out := div(out, exp(256, sub(32, itemLength)))
}
}
return out;
}
function readBytes32(bytes memory _in) internal pure returns (bytes32) {
return readBytes32(toRLPItem(_in));
}
function readUint256(RLPItem memory _in) internal pure returns (uint256) {
return uint256(readBytes32(_in));
}
function readUint256(bytes memory _in) internal pure returns (uint256) {
return readUint256(toRLPItem(_in));
}
function readBool(RLPItem memory _in) internal pure returns (bool) {
require(_in.length == 1, 'Invalid RLP boolean value.');
uint256 ptr = _in.ptr;
uint256 out;
assembly {
out := byte(0, mload(ptr))
}
require(
out == 0 || out == 1,
'Lib_RLPReader: Invalid RLP boolean value, must be 0 or 1'
);
return out != 0;
}
function readBool(bytes memory _in) internal pure returns (bool) {
return readBool(toRLPItem(_in));
}
function readAddress(RLPItem memory _in) internal pure returns (address) {
if (_in.length == 1) {
return address(0);
}
require(_in.length == 21, 'Invalid RLP address value.');
return address(uint160(readUint256(_in)));
}
function readAddress(bytes memory _in) internal pure returns (address) {
return readAddress(toRLPItem(_in));
}
function readRawBytes(RLPItem memory _in)
internal
pure
returns (bytes memory)
{
return _copy(_in);
}
function _decodeLength(RLPItem memory _in)
private
pure
returns (
uint256,
uint256,
RLPItemType
)
{
require(_in.length > 0, 'RLP item cannot be null.');
uint256 ptr = _in.ptr;
uint256 prefix;
assembly {
prefix := byte(0, mload(ptr))
}
if (prefix <= 0x7f) {
return (0, 1, RLPItemType.DATA_ITEM);
} else if (prefix <= 0xb7) {
uint256 strLen = prefix - 0x80;
require(_in.length > strLen, 'Invalid RLP short string.');
return (1, strLen, RLPItemType.DATA_ITEM);
} else if (prefix <= 0xbf) {
uint256 lenOfStrLen = prefix - 0xb7;
require(_in.length > lenOfStrLen, 'Invalid RLP long string length.');
uint256 strLen;
assembly {
strLen := div(mload(add(ptr, 1)), exp(256, sub(32, lenOfStrLen)))
}
require(_in.length > lenOfStrLen + strLen, 'Invalid RLP long string.');
return (1 + lenOfStrLen, strLen, RLPItemType.DATA_ITEM);
} else if (prefix <= 0xf7) {
uint256 listLen = prefix - 0xc0;
require(_in.length > listLen, 'Invalid RLP short list.');
return (1, listLen, RLPItemType.LIST_ITEM);
} else {
uint256 lenOfListLen = prefix - 0xf7;
require(_in.length > lenOfListLen, 'Invalid RLP long list length.');
uint256 listLen;
assembly {
listLen := div(mload(add(ptr, 1)), exp(256, sub(32, lenOfListLen)))
}
require(_in.length > lenOfListLen + listLen, 'Invalid RLP long list.');
return (1 + lenOfListLen, listLen, RLPItemType.LIST_ITEM);
}
}
function _copy(
uint256 _src,
uint256 _offset,
uint256 _length
) private pure returns (bytes memory) {
bytes memory out = new bytes(_length);
if (out.length == 0) {
return out;
}
uint256 src = _src + _offset;
uint256 dest;
assembly {
dest := add(out, 32)
}
for (uint256 i = 0; i < _length / 32; i++) {
assembly {
mstore(dest, mload(src))
}
src += 32;
dest += 32;
}
uint256 mask;
unchecked {
mask = 256**(32 - (_length % 32)) - 1;
}
assembly {
mstore(dest, or(and(mload(src), not(mask)), and(mload(dest), mask)))
}
return out;
}
function _copy(RLPItem memory _in) private pure returns (bytes memory) {
return _copy(_in.ptr, 0, _in.length);
}
}
文件 11 的 12:Lib_RLPWriter.sol
pragma solidity ^0.8.9;
library Lib_RLPWriter {
function writeBytes(bytes memory _in) internal pure returns (bytes memory) {
bytes memory encoded;
if (_in.length == 1 && uint8(_in[0]) < 128) {
encoded = _in;
} else {
encoded = abi.encodePacked(_writeLength(_in.length, 128), _in);
}
return encoded;
}
function writeList(bytes[] memory _in) internal pure returns (bytes memory) {
bytes memory list = _flatten(_in);
return abi.encodePacked(_writeLength(list.length, 192), list);
}
function writeString(string memory _in) internal pure returns (bytes memory) {
return writeBytes(bytes(_in));
}
function writeAddress(address _in) internal pure returns (bytes memory) {
return writeBytes(abi.encodePacked(_in));
}
function writeUint(uint256 _in) internal pure returns (bytes memory) {
return writeBytes(_toBinary(_in));
}
function writeBool(bool _in) internal pure returns (bytes memory) {
bytes memory encoded = new bytes(1);
encoded[0] = (_in ? bytes1(0x01) : bytes1(0x80));
return encoded;
}
function _writeLength(uint256 _len, uint256 _offset)
private
pure
returns (bytes memory)
{
bytes memory encoded;
if (_len < 56) {
encoded = new bytes(1);
encoded[0] = bytes1(uint8(_len) + uint8(_offset));
} else {
uint256 lenLen;
uint256 i = 1;
while (_len / i != 0) {
lenLen++;
i *= 256;
}
encoded = new bytes(lenLen + 1);
encoded[0] = bytes1(uint8(lenLen) + uint8(_offset) + 55);
for (i = 1; i <= lenLen; i++) {
encoded[i] = bytes1(uint8((_len / (256**(lenLen - i))) % 256));
}
}
return encoded;
}
function _toBinary(uint256 _x) private pure returns (bytes memory) {
bytes memory b = abi.encodePacked(_x);
uint256 i = 0;
for (; i < 32; i++) {
if (b[i] != 0) {
break;
}
}
bytes memory res = new bytes(32 - i);
for (uint256 j = 0; j < res.length; j++) {
res[j] = b[i++];
}
return res;
}
function _memcpy(
uint256 _dest,
uint256 _src,
uint256 _len
) private pure {
uint256 dest = _dest;
uint256 src = _src;
uint256 len = _len;
for (; len >= 32; len -= 32) {
assembly {
mstore(dest, mload(src))
}
dest += 32;
src += 32;
}
uint256 mask;
unchecked {
mask = 256**(32 - len) - 1;
}
assembly {
let srcpart := and(mload(src), not(mask))
let destpart := and(mload(dest), mask)
mstore(dest, or(destpart, srcpart))
}
}
function _flatten(bytes[] memory _list) private pure returns (bytes memory) {
if (_list.length == 0) {
return new bytes(0);
}
uint256 len;
uint256 i = 0;
for (; i < _list.length; i++) {
len += _list[i].length;
}
bytes memory flattened = new bytes(len);
uint256 flattenedPtr;
assembly {
flattenedPtr := add(flattened, 0x20)
}
for (i = 0; i < _list.length; i++) {
bytes memory item = _list[i];
uint256 listPtr;
assembly {
listPtr := add(item, 0x20)
}
_memcpy(flattenedPtr, listPtr, item.length);
flattenedPtr += _list[i].length;
}
return flattened;
}
}
文件 12 的 12:Ownable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
_setOwner(_msgSender());
}
function owner() public view virtual returns (address) {
return _owner;
}
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
function renounceOwnership() public virtual onlyOwner {
_setOwner(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_setOwner(newOwner);
}
function _setOwner(address newOwner) private {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
{
"compilationTarget": {
"contracts/L1/messaging/L1MultiMessageRelayer.sol": "L1MultiMessageRelayer"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "none",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 10000
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_libAddressManager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"bytes","name":"message","type":"bytes"},{"internalType":"uint256","name":"messageNonce","type":"uint256"},{"components":[{"internalType":"bytes32","name":"stateRoot","type":"bytes32"},{"components":[{"internalType":"uint256","name":"batchIndex","type":"uint256"},{"internalType":"bytes32","name":"batchRoot","type":"bytes32"},{"internalType":"uint256","name":"batchSize","type":"uint256"},{"internalType":"uint256","name":"prevTotalElements","type":"uint256"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"internalType":"struct Lib_OVMCodec.ChainBatchHeader","name":"stateRootBatchHeader","type":"tuple"},{"components":[{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"bytes32[]","name":"siblings","type":"bytes32[]"}],"internalType":"struct Lib_OVMCodec.ChainInclusionProof","name":"stateRootProof","type":"tuple"},{"internalType":"bytes","name":"stateTrieWitness","type":"bytes"},{"internalType":"bytes","name":"storageTrieWitness","type":"bytes"}],"internalType":"struct IL1CrossDomainMessenger.L2MessageInclusionProof","name":"proof","type":"tuple"}],"internalType":"struct L1MultiMessageRelayer.L2ToL1Message[]","name":"_messages","type":"tuple[]"}],"name":"batchRelayMessages","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"libAddressManager","outputs":[{"internalType":"contract Lib_AddressManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_name","type":"string"}],"name":"resolve","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]