文件 1 的 15: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 的 15:IBondManager.sol
pragma solidity ^0.8.9;
interface IBondManager {
function isCollateralized(address _who) external view returns (bool);
}
文件 3 的 15:ICanonicalTransactionChain.sol
pragma solidity >0.5.0 <0.9.0;
import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol";
import { IChainStorageContainer } from "./IChainStorageContainer.sol";
interface ICanonicalTransactionChain {
event L2GasParamsUpdated(
uint256 l2GasDiscountDivisor,
uint256 enqueueGasCost,
uint256 enqueueL2GasPrepaid
);
event TransactionEnqueued(
address indexed _l1TxOrigin,
address indexed _target,
uint256 _gasLimit,
bytes _data,
uint256 indexed _queueIndex,
uint256 _timestamp
);
event QueueBatchAppended(
uint256 _startingQueueIndex,
uint256 _numQueueElements,
uint256 _totalElements
);
event SequencerBatchAppended(
uint256 _startingQueueIndex,
uint256 _numQueueElements,
uint256 _totalElements
);
event TransactionBatchAppended(
uint256 indexed _batchIndex,
bytes32 _batchRoot,
uint256 _batchSize,
uint256 _prevTotalElements,
bytes _extraData
);
struct BatchContext {
uint256 numSequencedTransactions;
uint256 numSubsequentQueueTransactions;
uint256 timestamp;
uint256 blockNumber;
}
function setGasParams(uint256 _l2GasDiscountDivisor, uint256 _enqueueGasCost) external;
function batches() external view returns (IChainStorageContainer);
function getTotalElements() external view returns (uint256 _totalElements);
function getTotalBatches() external view returns (uint256 _totalBatches);
function getNextQueueIndex() external view returns (uint40);
function getQueueElement(uint256 _index)
external
view
returns (Lib_OVMCodec.QueueElement memory _element);
function getLastTimestamp() external view returns (uint40);
function getLastBlockNumber() external view returns (uint40);
function getNumPendingQueueElements() external view returns (uint40);
function getQueueLength() external view returns (uint40);
function enqueue(
address _target,
uint256 _gasLimit,
bytes memory _data
) external;
function appendSequencerBatch(
) external;
}
文件 4 的 15:IChainStorageContainer.sol
pragma solidity >0.5.0 <0.9.0;
interface IChainStorageContainer {
function setGlobalMetadata(bytes27 _globalMetadata) external;
function getGlobalMetadata() external view returns (bytes27);
function length() external view returns (uint256);
function push(bytes32 _object) external;
function push(bytes32 _object, bytes27 _globalMetadata) external;
function get(uint256 _index) external view returns (bytes32);
function deleteElementsAfterInclusive(uint256 _index) external;
function deleteElementsAfterInclusive(uint256 _index, bytes27 _globalMetadata) external;
}
文件 5 的 15:IStateCommitmentChain.sol
pragma solidity >0.5.0 <0.9.0;
import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol";
interface IStateCommitmentChain {
event StateBatchAppended(
uint256 indexed _batchIndex,
bytes32 _batchRoot,
uint256 _batchSize,
uint256 _prevTotalElements,
bytes _extraData
);
event StateBatchDeleted(uint256 indexed _batchIndex, bytes32 _batchRoot);
function getTotalElements() external view returns (uint256 _totalElements);
function getTotalBatches() external view returns (uint256 _totalBatches);
function getLastSequencerTimestamp() external view returns (uint256 _lastSequencerTimestamp);
function appendStateBatch(bytes32[] calldata _batch, uint256 _shouldStartAtElement) external;
function deleteStateBatch(Lib_OVMCodec.ChainBatchHeader memory _batchHeader) external;
function verifyStateCommitment(
bytes32 _element,
Lib_OVMCodec.ChainBatchHeader memory _batchHeader,
Lib_OVMCodec.ChainInclusionProof memory _proof
) external view returns (bool _verified);
function insideFraudProofWindow(Lib_OVMCodec.ChainBatchHeader memory _batchHeader)
external
view
returns (bool _inside);
}
文件 6 的 15: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));
}
}
文件 7 的 15: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);
}
}
文件 8 的 15: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)));
}
}
文件 9 的 15: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);
}
}
文件 10 的 15:Lib_MerkleTree.sol
pragma solidity ^0.8.9;
library Lib_MerkleTree {
function getMerkleRoot(bytes32[] memory _elements) internal pure returns (bytes32) {
require(_elements.length > 0, "Lib_MerkleTree: Must provide at least one leaf hash.");
if (_elements.length == 1) {
return _elements[0];
}
uint256[16] memory defaults = [
0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563,
0x633dc4d7da7256660a892f8f1604a44b5432649cc8ec5cb3ced4c4e6ac94dd1d,
0x890740a8eb06ce9be422cb8da5cdafc2b58c0a5e24036c578de2a433c828ff7d,
0x3b8ec09e026fdc305365dfc94e189a81b38c7597b3d941c279f042e8206e0bd8,
0xecd50eee38e386bd62be9bedb990706951b65fe053bd9d8a521af753d139e2da,
0xdefff6d330bb5403f63b14f33b578274160de3a50df4efecf0e0db73bcdd3da5,
0x617bdd11f7c0a11f49db22f629387a12da7596f9d1704d7465177c63d88ec7d7,
0x292c23a9aa1d8bea7e2435e555a4a60e379a5a35f3f452bae60121073fb6eead,
0xe1cea92ed99acdcb045a6726b2f87107e8a61620a232cf4d7d5b5766b3952e10,
0x7ad66c0a68c72cb89e4fb4303841966e4062a76ab97451e3b9fb526a5ceb7f82,
0xe026cc5a4aed3c22a58cbd3d2ac754c9352c5436f638042dca99034e83636516,
0x3d04cffd8b46a874edf5cfae63077de85f849a660426697b06a829c70dd1409c,
0xad676aa337a485e4728a0b240d92b3ef7b3c372d06d189322bfd5f61f1e7203e,
0xa2fca4a49658f9fab7aa63289c91b7c7b6c832a6d0e69334ff5b0a3483d09dab,
0x4ebfd9cd7bca2505f7bef59cc1c12ecc708fff26ae4af19abe852afe9e20c862,
0x2def10d13dd169f550f578bda343d9717a138562e0093b380a1120789d53cf10
];
bytes memory buf = new bytes(64);
bytes32 leftSibling;
bytes32 rightSibling;
uint256 rowSize = _elements.length;
uint256 depth = 0;
uint256 halfRowSize;
bool rowSizeIsOdd;
while (rowSize > 1) {
halfRowSize = rowSize / 2;
rowSizeIsOdd = rowSize % 2 == 1;
for (uint256 i = 0; i < halfRowSize; i++) {
leftSibling = _elements[(2 * i)];
rightSibling = _elements[(2 * i) + 1];
assembly {
mstore(add(buf, 32), leftSibling)
mstore(add(buf, 64), rightSibling)
}
_elements[i] = keccak256(buf);
}
if (rowSizeIsOdd) {
leftSibling = _elements[rowSize - 1];
rightSibling = bytes32(defaults[depth]);
assembly {
mstore(add(buf, 32), leftSibling)
mstore(add(buf, 64), rightSibling)
}
_elements[halfRowSize] = keccak256(buf);
}
rowSize = halfRowSize + (rowSizeIsOdd ? 1 : 0);
depth++;
}
return _elements[0];
}
function verify(
bytes32 _root,
bytes32 _leaf,
uint256 _index,
bytes32[] memory _siblings,
uint256 _totalLeaves
) internal pure returns (bool) {
require(_totalLeaves > 0, "Lib_MerkleTree: Total leaves must be greater than zero.");
require(_index < _totalLeaves, "Lib_MerkleTree: Index out of bounds.");
require(
_siblings.length == _ceilLog2(_totalLeaves),
"Lib_MerkleTree: Total siblings does not correctly correspond to total leaves."
);
bytes32 computedRoot = _leaf;
for (uint256 i = 0; i < _siblings.length; i++) {
if ((_index & 1) == 1) {
computedRoot = keccak256(abi.encodePacked(_siblings[i], computedRoot));
} else {
computedRoot = keccak256(abi.encodePacked(computedRoot, _siblings[i]));
}
_index >>= 1;
}
return _root == computedRoot;
}
function _ceilLog2(uint256 _in) private pure returns (uint256) {
require(_in > 0, "Lib_MerkleTree: Cannot compute ceil(log_2) of 0.");
if (_in == 1) {
return 0;
}
uint256 val = _in;
uint256 highest = 0;
for (uint256 i = 128; i >= 1; i >>= 1) {
if (val & (((uint256(1) << i) - 1) << i) != 0) {
highest += i;
val >>= i;
}
}
if ((uint256(1) << highest) != _in) {
highest += 1;
}
return highest;
}
}
文件 11 的 15: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
)
);
}
}
文件 12 的 15: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);
}
}
文件 13 的 15: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;
}
}
文件 14 的 15: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);
}
}
文件 15 的 15:StateCommitmentChain.sol
pragma solidity ^0.8.9;
import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol";
import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol";
import { Lib_MerkleTree } from "../../libraries/utils/Lib_MerkleTree.sol";
import { IStateCommitmentChain } from "./IStateCommitmentChain.sol";
import { ICanonicalTransactionChain } from "./ICanonicalTransactionChain.sol";
import { IBondManager } from "../verification/IBondManager.sol";
import { IChainStorageContainer } from "./IChainStorageContainer.sol";
contract StateCommitmentChain is IStateCommitmentChain, Lib_AddressResolver {
uint256 public FRAUD_PROOF_WINDOW;
uint256 public SEQUENCER_PUBLISH_WINDOW;
constructor(
address _libAddressManager,
uint256 _fraudProofWindow,
uint256 _sequencerPublishWindow
) Lib_AddressResolver(_libAddressManager) {
FRAUD_PROOF_WINDOW = _fraudProofWindow;
SEQUENCER_PUBLISH_WINDOW = _sequencerPublishWindow;
}
function batches() public view returns (IChainStorageContainer) {
return IChainStorageContainer(resolve("ChainStorageContainer-SCC-batches"));
}
function getTotalElements() public view returns (uint256 _totalElements) {
(uint40 totalElements, ) = _getBatchExtraData();
return uint256(totalElements);
}
function getTotalBatches() public view returns (uint256 _totalBatches) {
return batches().length();
}
function getLastSequencerTimestamp() public view returns (uint256 _lastSequencerTimestamp) {
(, uint40 lastSequencerTimestamp) = _getBatchExtraData();
return uint256(lastSequencerTimestamp);
}
function appendStateBatch(bytes32[] memory _batch, uint256 _shouldStartAtElement) public {
require(
_shouldStartAtElement == getTotalElements(),
"Actual batch start index does not match expected start index."
);
require(
IBondManager(resolve("BondManager")).isCollateralized(msg.sender),
"Proposer does not have enough collateral posted"
);
require(_batch.length > 0, "Cannot submit an empty state batch.");
require(
getTotalElements() + _batch.length <=
ICanonicalTransactionChain(resolve("CanonicalTransactionChain")).getTotalElements(),
"Number of state roots cannot exceed the number of canonical transactions."
);
_appendBatch(_batch, abi.encode(block.timestamp, msg.sender));
}
function deleteStateBatch(Lib_OVMCodec.ChainBatchHeader memory _batchHeader) public {
require(
msg.sender == resolve("OVM_FraudVerifier"),
"State batches can only be deleted by the OVM_FraudVerifier."
);
require(_isValidBatchHeader(_batchHeader), "Invalid batch header.");
require(
insideFraudProofWindow(_batchHeader),
"State batches can only be deleted within the fraud proof window."
);
_deleteBatch(_batchHeader);
}
function verifyStateCommitment(
bytes32 _element,
Lib_OVMCodec.ChainBatchHeader memory _batchHeader,
Lib_OVMCodec.ChainInclusionProof memory _proof
) public view returns (bool) {
require(_isValidBatchHeader(_batchHeader), "Invalid batch header.");
require(
Lib_MerkleTree.verify(
_batchHeader.batchRoot,
_element,
_proof.index,
_proof.siblings,
_batchHeader.batchSize
),
"Invalid inclusion proof."
);
return true;
}
function insideFraudProofWindow(Lib_OVMCodec.ChainBatchHeader memory _batchHeader)
public
view
returns (bool _inside)
{
(uint256 timestamp, ) = abi.decode(_batchHeader.extraData, (uint256, address));
require(timestamp != 0, "Batch header timestamp cannot be zero");
return (timestamp + FRAUD_PROOF_WINDOW) > block.timestamp;
}
function _getBatchExtraData() internal view returns (uint40, uint40) {
bytes27 extraData = batches().getGlobalMetadata();
uint40 totalElements;
uint40 lastSequencerTimestamp;
assembly {
extraData := shr(40, extraData)
totalElements := and(
extraData,
0x000000000000000000000000000000000000000000000000000000FFFFFFFFFF
)
lastSequencerTimestamp := shr(
40,
and(extraData, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000)
)
}
return (totalElements, lastSequencerTimestamp);
}
function _makeBatchExtraData(uint40 _totalElements, uint40 _lastSequencerTimestamp)
internal
pure
returns (bytes27)
{
bytes27 extraData;
assembly {
extraData := _totalElements
extraData := or(extraData, shl(40, _lastSequencerTimestamp))
extraData := shl(40, extraData)
}
return extraData;
}
function _appendBatch(bytes32[] memory _batch, bytes memory _extraData) internal {
address sequencer = resolve("OVM_Proposer");
(uint40 totalElements, uint40 lastSequencerTimestamp) = _getBatchExtraData();
if (msg.sender == sequencer) {
lastSequencerTimestamp = uint40(block.timestamp);
} else {
require(
lastSequencerTimestamp + SEQUENCER_PUBLISH_WINDOW < block.timestamp,
"Cannot publish state roots within the sequencer publication window."
);
}
Lib_OVMCodec.ChainBatchHeader memory batchHeader = Lib_OVMCodec.ChainBatchHeader({
batchIndex: getTotalBatches(),
batchRoot: Lib_MerkleTree.getMerkleRoot(_batch),
batchSize: _batch.length,
prevTotalElements: totalElements,
extraData: _extraData
});
emit StateBatchAppended(
batchHeader.batchIndex,
batchHeader.batchRoot,
batchHeader.batchSize,
batchHeader.prevTotalElements,
batchHeader.extraData
);
batches().push(
Lib_OVMCodec.hashBatchHeader(batchHeader),
_makeBatchExtraData(
uint40(batchHeader.prevTotalElements + batchHeader.batchSize),
lastSequencerTimestamp
)
);
}
function _deleteBatch(Lib_OVMCodec.ChainBatchHeader memory _batchHeader) internal {
require(_batchHeader.batchIndex < batches().length(), "Invalid batch index.");
require(_isValidBatchHeader(_batchHeader), "Invalid batch header.");
batches().deleteElementsAfterInclusive(
_batchHeader.batchIndex,
_makeBatchExtraData(uint40(_batchHeader.prevTotalElements), 0)
);
emit StateBatchDeleted(_batchHeader.batchIndex, _batchHeader.batchRoot);
}
function _isValidBatchHeader(Lib_OVMCodec.ChainBatchHeader memory _batchHeader)
internal
view
returns (bool)
{
return Lib_OVMCodec.hashBatchHeader(_batchHeader) == batches().get(_batchHeader.batchIndex);
}
}
{
"compilationTarget": {
"contracts/L1/rollup/StateCommitmentChain.sol": "StateCommitmentChain"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 10000
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_libAddressManager","type":"address"},{"internalType":"uint256","name":"_fraudProofWindow","type":"uint256"},{"internalType":"uint256","name":"_sequencerPublishWindow","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_batchIndex","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"_batchRoot","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"_batchSize","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_prevTotalElements","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"StateBatchAppended","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_batchIndex","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"_batchRoot","type":"bytes32"}],"name":"StateBatchDeleted","type":"event"},{"inputs":[],"name":"FRAUD_PROOF_WINDOW","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SEQUENCER_PUBLISH_WINDOW","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"_batch","type":"bytes32[]"},{"internalType":"uint256","name":"_shouldStartAtElement","type":"uint256"}],"name":"appendStateBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"batches","outputs":[{"internalType":"contract IChainStorageContainer","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"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":"_batchHeader","type":"tuple"}],"name":"deleteStateBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getLastSequencerTimestamp","outputs":[{"internalType":"uint256","name":"_lastSequencerTimestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalBatches","outputs":[{"internalType":"uint256","name":"_totalBatches","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalElements","outputs":[{"internalType":"uint256","name":"_totalElements","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"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":"_batchHeader","type":"tuple"}],"name":"insideFraudProofWindow","outputs":[{"internalType":"bool","name":"_inside","type":"bool"}],"stateMutability":"view","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"},{"inputs":[{"internalType":"bytes32","name":"_element","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":"_batchHeader","type":"tuple"},{"components":[{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"bytes32[]","name":"siblings","type":"bytes32[]"}],"internalType":"struct Lib_OVMCodec.ChainInclusionProof","name":"_proof","type":"tuple"}],"name":"verifyStateCommitment","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]