diff --git a/contracts/docs/apis/L1ScrollMessenger.md b/contracts/docs/apis/L1ScrollMessenger.md index d8c41fc05..884a08298 100644 --- a/contracts/docs/apis/L1ScrollMessenger.md +++ b/contracts/docs/apis/L1ScrollMessenger.md @@ -63,28 +63,6 @@ Initialize the storage of L1ScrollMessenger. | _rollup | address | The address of ScrollChain contract. | | _messageQueue | address | The address of L1MessageQueue contract. | -### isL1MessageRelayed - -```solidity -function isL1MessageRelayed(bytes32) external view returns (bool) -``` - -Mapping from relay id to relay status. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| _0 | bytes32 | undefined | - -#### Returns - -| Name | Type | Description | -|---|---|---| -| _0 | bool | undefined | - ### isL1MessageSent ```solidity diff --git a/contracts/integration-test/L1MessageQueue.spec.ts b/contracts/integration-test/L1MessageQueue.spec.ts index e4676332e..33d21c509 100644 --- a/contracts/integration-test/L1MessageQueue.spec.ts +++ b/contracts/integration-test/L1MessageQueue.spec.ts @@ -2,7 +2,16 @@ /* eslint-disable node/no-missing-import */ import { expect } from "chai"; import { BigNumber, constants } from "ethers"; -import { concat, getAddress, hexlify, keccak256, randomBytes, RLP } from "ethers/lib/utils"; +import { + concat, + getAddress, + hexlify, + keccak256, + randomBytes, + RLP, + stripZeros, + TransactionTypes, +} from "ethers/lib/utils"; import { ethers } from "hardhat"; import { L1MessageQueue, L2GasPriceOracle } from "../typechain"; import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; @@ -94,8 +103,8 @@ describe("L1MessageQueue", async () => { context("#computeTransactionHash", async () => { it("should succeed", async () => { - const sender = hexlify(randomBytes(20)); - const target = hexlify(randomBytes(20)); + const sender = "0xb2a70fab1a45b1b9be443b6567849a1702bc1232"; + const target = "0xcb18150e4efefb6786130e289a5f61a82a5b86d7"; const transactionType = "0x7E"; for (const nonce of [ @@ -123,19 +132,30 @@ describe("L1MessageQueue", async () => { constants.MaxUint256, ]) { for (const dataLen of [0, 1, 2, 3, 4, 55, 56, 100]) { - const data = randomBytes(dataLen); - const transactionPayload = RLP.encode([ - nonce.toHexString(), - gasLimit.toHexString(), - target, - value.toHexString(), - data, - sender, - ]); - const payload = concat([transactionType, transactionPayload]); - const expectedHash = keccak256(payload); - const computedHash = await queue.computeTransactionHash(sender, nonce, value, target, gasLimit, data); - expect(expectedHash).to.eq(computedHash); + const tests = [randomBytes(dataLen)]; + if (dataLen === 1) { + for (const byte of [0, 1, 127, 128]) { + tests.push(Uint8Array.from([byte])); + } + } + for (const data of tests) { + const transactionPayload = RLP.encode([ + stripZeros(nonce.toHexString()), + stripZeros(gasLimit.toHexString()), + target, + stripZeros(value.toHexString()), + data, + sender, + ]); + const payload = concat([transactionType, transactionPayload]); + const expectedHash = keccak256(payload); + const computedHash = await queue.computeTransactionHash(sender, nonce, value, target, gasLimit, data); + if (computedHash !== expectedHash) { + console.log(hexlify(transactionPayload)); + console.log(nonce, gasLimit, target, value, data, sender); + } + expect(expectedHash).to.eq(computedHash); + } } } } diff --git a/contracts/src/L1/L1ScrollMessenger.sol b/contracts/src/L1/L1ScrollMessenger.sol index 874bfacd8..4153ba111 100644 --- a/contracts/src/L1/L1ScrollMessenger.sol +++ b/contracts/src/L1/L1ScrollMessenger.sol @@ -30,9 +30,6 @@ contract L1ScrollMessenger is PausableUpgradeable, ScrollMessengerBase, IL1Scrol * Variables * *************/ - /// @notice Mapping from relay id to relay status. - mapping(bytes32 => bool) public isL1MessageRelayed; - /// @notice Mapping from L1 message hash to sent status. mapping(bytes32 => bool) public isL1MessageSent; @@ -45,28 +42,6 @@ contract L1ScrollMessenger is PausableUpgradeable, ScrollMessengerBase, IL1Scrol /// @notice The address of L1MessageQueue contract. address public messageQueue; - // @note move to ScrollMessengerBase in next big refactor - /// @dev The status of for non-reentrant check. - uint256 private _lock_status; - - /********************** - * Function Modifiers * - **********************/ - - modifier nonReentrant() { - // On the first call to nonReentrant, _notEntered will be true - require(_lock_status != _ENTERED, "ReentrancyGuard: reentrant call"); - - // Any calls to nonReentrant after this point will fail - _lock_status = _ENTERED; - - _; - - // By storing the original value once again, a refund is triggered (see - // https://eips.ethereum.org/EIPS/eip-2200) - _lock_status = _NOT_ENTERED; - } - /*************** * Constructor * ***************/ @@ -162,9 +137,6 @@ contract L1ScrollMessenger is PausableUpgradeable, ScrollMessengerBase, IL1Scrol } else { emit FailedRelayedMessage(_xDomainCalldataHash); } - - bytes32 _relayId = keccak256(abi.encodePacked(_xDomainCalldataHash, msg.sender, block.number)); - isL1MessageRelayed[_relayId] = true; } /// @inheritdoc IL1ScrollMessenger diff --git a/contracts/src/L1/rollup/L1MessageQueue.sol b/contracts/src/L1/rollup/L1MessageQueue.sol index 3b62f8fe5..2606b7fcc 100644 --- a/contracts/src/L1/rollup/L1MessageQueue.sol +++ b/contracts/src/L1/rollup/L1MessageQueue.sol @@ -139,18 +139,27 @@ contract L1MessageQueue is OwnableUpgradeable, IL1MessageQueue { } } - function store_uint(_ptr, v) -> ptr { + // This is used for both store uint and single byte. + // Integer zero is special handled by geth to encode as `0x80` + function store_uint_or_byte(_ptr, v, is_uint) -> ptr { ptr := _ptr switch lt(v, 128) case 1 { - // single byte in the [0x00, 0x7f] - mstore(ptr, shl(248, v)) + switch and(iszero(v), is_uint) + case 1 { + // integer 0 + mstore8(ptr, 0x80) + } + default { + // single byte in the [0x00, 0x7f] + mstore8(ptr, v) + } ptr := add(ptr, 1) } default { // 1-32 bytes long let len := get_uint_bytes(v) - mstore(ptr, shl(248, add(len, 0x80))) + mstore8(ptr, add(len, 0x80)) ptr := add(ptr, 1) mstore(ptr, shl(mul(8, sub(32, len)), v)) ptr := add(ptr, len) @@ -160,7 +169,7 @@ contract L1MessageQueue is OwnableUpgradeable, IL1MessageQueue { function store_address(_ptr, v) -> ptr { ptr := _ptr // 20 bytes long - mstore(ptr, shl(248, 0x94)) // 0x80 + 0x14 + mstore8(ptr, 0x94) // 0x80 + 0x14 ptr := add(ptr, 1) mstore(ptr, shl(96, v)) ptr := add(ptr, 0x14) @@ -170,21 +179,21 @@ contract L1MessageQueue is OwnableUpgradeable, IL1MessageQueue { // 4 byte for list payload length let start_ptr := add(mload(0x40), 5) let ptr := start_ptr - ptr := store_uint(ptr, _queueIndex) - ptr := store_uint(ptr, _gasLimit) + ptr := store_uint_or_byte(ptr, _queueIndex, 1) + ptr := store_uint_or_byte(ptr, _gasLimit, 1) ptr := store_address(ptr, _target) - ptr := store_uint(ptr, _value) + ptr := store_uint_or_byte(ptr, _value, 1) switch eq(_data.length, 1) case 1 { // single byte - ptr := store_uint(ptr, shr(248, calldataload(_data.offset))) + ptr := store_uint_or_byte(ptr, byte(0, calldataload(_data.offset)), 0) } default { switch lt(_data.length, 56) case 1 { // a string is 0-55 bytes long - mstore(ptr, shl(248, add(0x80, _data.length))) + mstore8(ptr, add(0x80, _data.length)) ptr := add(ptr, 1) calldatacopy(ptr, _data.offset, _data.length) ptr := add(ptr, _data.length) @@ -192,7 +201,7 @@ contract L1MessageQueue is OwnableUpgradeable, IL1MessageQueue { default { // a string is more than 55 bytes long let len_bytes := get_uint_bytes(_data.length) - mstore(ptr, shl(248, add(0xb7, len_bytes))) + mstore8(ptr, add(0xb7, len_bytes)) ptr := add(ptr, 1) mstore(ptr, shl(mul(8, sub(32, len_bytes)), _data.length)) ptr := add(ptr, len_bytes) diff --git a/contracts/src/L1/rollup/ScrollChain.sol b/contracts/src/L1/rollup/ScrollChain.sol index 5e26646b3..288fc1910 100644 --- a/contracts/src/L1/rollup/ScrollChain.sol +++ b/contracts/src/L1/rollup/ScrollChain.sol @@ -130,12 +130,7 @@ contract ScrollChain is OwnableUpgradeable, IScrollChain { *****************************/ /// @notice Import layer 2 genesis block - /// @dev Although `_withdrawRoot` is always zero, we add this parameter for the convenience of unit testing. - function importGenesisBatch( - bytes calldata _batchHeader, - bytes32 _stateRoot, - bytes32 _withdrawRoot - ) external { + function importGenesisBatch(bytes calldata _batchHeader, bytes32 _stateRoot) external { // check genesis batch header length require(_stateRoot != bytes32(0), "zero state root"); @@ -157,10 +152,9 @@ contract ScrollChain is OwnableUpgradeable, IScrollChain { committedBatches[0] = _batchHash; finalizedStateRoots[0] = _stateRoot; - withdrawRoots[0] = _withdrawRoot; emit CommitBatch(_batchHash); - emit FinalizeBatch(_batchHash, _stateRoot, _withdrawRoot); + emit FinalizeBatch(_batchHash, _stateRoot, bytes32(0)); } /// @inheritdoc IScrollChain diff --git a/contracts/src/L2/L2ScrollMessenger.sol b/contracts/src/L2/L2ScrollMessenger.sol index d0fb53006..d0560c39f 100644 --- a/contracts/src/L2/L2ScrollMessenger.sol +++ b/contracts/src/L2/L2ScrollMessenger.sol @@ -62,28 +62,6 @@ contract L2ScrollMessenger is ScrollMessengerBase, PausableUpgradeable, IL2Scrol /// @notice The maximum number of times each L1 message can fail on L2. uint256 public maxFailedExecutionTimes; - // @note move to ScrollMessengerBase in next big refactor - /// @dev The status of for non-reentrant check. - uint256 private _lock_status; - - /********************** - * Function Modifiers * - **********************/ - - modifier nonReentrant() { - // On the first call to nonReentrant, _notEntered will be true - require(_lock_status != _ENTERED, "ReentrancyGuard: reentrant call"); - - // Any calls to nonReentrant after this point will fail - _lock_status = _ENTERED; - - _; - - // By storing the original value once again, a refund is triggered (see - // https://eips.ethereum.org/EIPS/eip-2200) - _lock_status = _NOT_ENTERED; - } - /*************** * Constructor * ***************/ @@ -126,14 +104,16 @@ contract L2ScrollMessenger is ScrollMessengerBase, PausableUpgradeable, IL2Scrol require(_expectedStateRoot != bytes32(0), "Block is not imported"); bytes32 _storageKey; - // `mapping(bytes32 => bool) public isL1MessageSent` is the 105-nd slot of contract `L1ScrollMessenger`. + // `mapping(bytes32 => bool) public isL1MessageSent` is the 155-th slot of contract `L1ScrollMessenger`. + // + 1 from `Initializable` // + 50 from `OwnableUpgradeable` + // + 50 from `ContextUpgradeable` // + 4 from `ScrollMessengerBase` // + 50 from `PausableUpgradeable` - // + 2-nd in `L1ScrollMessenger` + // + 1-st in `L1ScrollMessenger` assembly { mstore(0x00, _msgHash) - mstore(0x20, 105) + mstore(0x20, 155) _storageKey := keccak256(0x00, 0x40) } @@ -161,14 +141,16 @@ contract L2ScrollMessenger is ScrollMessengerBase, PausableUpgradeable, IL2Scrol require(_expectedStateRoot != bytes32(0), "Block not imported"); bytes32 _storageKey; - // `mapping(bytes32 => bool) public isL2MessageExecuted` is the 106-th slot of contract `L1ScrollMessenger`. + // `mapping(bytes32 => bool) public isL2MessageExecuted` is the 156-th slot of contract `L1ScrollMessenger`. + // + 1 from `Initializable` // + 50 from `OwnableUpgradeable` + // + 50 from `ContextUpgradeable` // + 4 from `ScrollMessengerBase` // + 50 from `PausableUpgradeable` - // + 3-rd in `L1ScrollMessenger` + // + 2-nd in `L1ScrollMessenger` assembly { mstore(0x00, _msgHash) - mstore(0x20, 106) + mstore(0x20, 156) _storageKey := keccak256(0x00, 0x40) } diff --git a/contracts/src/L2/predeploys/WETH9.sol b/contracts/src/L2/predeploys/WETH9.sol index 11b2974cd..433fbaeb1 100644 --- a/contracts/src/L2/predeploys/WETH9.sol +++ b/contracts/src/L2/predeploys/WETH9.sol @@ -51,7 +51,8 @@ contract WETH9 { balanceOf[msg.sender] -= wad; } - payable(msg.sender).transfer(wad); + (bool success, ) = msg.sender.call{value:wad}(""); + require(success, "withdraw ETH failed"); emit Withdrawal(msg.sender, wad); } diff --git a/contracts/src/libraries/ScrollMessengerBase.sol b/contracts/src/libraries/ScrollMessengerBase.sol index 714c5cd1b..2edf04d05 100644 --- a/contracts/src/libraries/ScrollMessengerBase.sol +++ b/contracts/src/libraries/ScrollMessengerBase.sol @@ -38,6 +38,28 @@ abstract contract ScrollMessengerBase is OwnableUpgradeable, IScrollMessenger { /// @notice The address of fee vault, collecting cross domain messaging fee. address public feeVault; + // @note move to ScrollMessengerBase in next big refactor + /// @dev The status of for non-reentrant check. + uint256 private _lock_status; + + /********************** + * Function Modifiers * + **********************/ + + modifier nonReentrant() { + // On the first call to nonReentrant, _notEntered will be true + require(_lock_status != _ENTERED, "ReentrancyGuard: reentrant call"); + + // Any calls to nonReentrant after this point will fail + _lock_status = _ENTERED; + + _; + + // By storing the original value once again, a refund is triggered (see + // https://eips.ethereum.org/EIPS/eip-2200) + _lock_status = _NOT_ENTERED; + } + /*************** * Constructor * ***************/ diff --git a/contracts/src/test/L1GatewayTestBase.t.sol b/contracts/src/test/L1GatewayTestBase.t.sol index f571e996e..8e67f0f83 100644 --- a/contracts/src/test/L1GatewayTestBase.t.sol +++ b/contracts/src/test/L1GatewayTestBase.t.sol @@ -12,6 +12,10 @@ import {Whitelist} from "../L2/predeploys/Whitelist.sol"; import {L1ScrollMessenger} from "../L1/L1ScrollMessenger.sol"; import {L2ScrollMessenger} from "../L2/L2ScrollMessenger.sol"; +import {MockRollupVerifier} from "./mocks/MockRollupVerifier.sol"; + +// solhint-disable no-inline-assembly + abstract contract L1GatewayTestBase is DSTestPlus { // from L1MessageQueue event QueueTransaction( @@ -44,6 +48,8 @@ abstract contract L1GatewayTestBase is DSTestPlus { EnforcedTxGateway internal enforcedTxGateway; ScrollChain internal rollup; + MockRollupVerifier internal verifier; + address internal feeVault; Whitelist private whitelist; @@ -59,6 +65,7 @@ abstract contract L1GatewayTestBase is DSTestPlus { rollup = new ScrollChain(1233); enforcedTxGateway = new EnforcedTxGateway(); whitelist = new Whitelist(address(this)); + verifier = new MockRollupVerifier(); // Deploy L2 contracts l2Messenger = new L2ScrollMessenger(address(0), address(0), address(0)); @@ -74,7 +81,7 @@ abstract contract L1GatewayTestBase is DSTestPlus { ); gasOracle.initialize(0, 0, 0, 0); gasOracle.updateWhitelist(address(whitelist)); - rollup.initialize(address(messageQueue), address(0), 44); + rollup.initialize(address(messageQueue), address(verifier), 44); address[] memory _accounts = new address[](1); _accounts[0] = address(this); @@ -82,11 +89,40 @@ abstract contract L1GatewayTestBase is DSTestPlus { } function prepareL2MessageRoot(bytes32 messageHash) internal { - bytes memory _batchHeader = new bytes(89); + rollup.updateSequencer(address(this), true); + rollup.updateProver(address(this), true); + + // import genesis batch + bytes memory batchHeader0 = new bytes(89); assembly { - mstore(add(_batchHeader, add(0x20, 25)), 1) + mstore(add(batchHeader0, add(0x20, 25)), 1) + } + rollup.importGenesisBatch(batchHeader0, bytes32(uint256(1))); + bytes32 batchHash0 = rollup.committedBatches(0); + + // commit one batch + bytes[] memory chunks = new bytes[](1); + bytes memory chunk0 = new bytes(1 + 60); + chunk0[0] = bytes1(uint8(1)); // one block in this chunk + chunks[0] = chunk0; + rollup.commitBatch(0, batchHeader0, chunks, new bytes(0)); + + bytes memory batchHeader1 = new bytes(89); + assembly { + mstore(add(batchHeader1, 0x20), 0) // version + mstore(add(batchHeader1, add(0x20, 1)), shl(192, 1)) // batchIndex + mstore(add(batchHeader1, add(0x20, 9)), 0) // l1MessagePopped + mstore(add(batchHeader1, add(0x20, 17)), 0) // totalL1MessagePopped + mstore(add(batchHeader1, add(0x20, 25)), 0x246394445f4fe64ed5598554d55d1682d6fb3fe04bf58eb54ef81d1189fafb51) // dataHash + mstore(add(batchHeader1, add(0x20, 57)), batchHash0) // parentBatchHash } - rollup.importGenesisBatch(_batchHeader, bytes32(uint256(1)), messageHash); + rollup.finalizeBatchWithProof( + batchHeader1, + bytes32(uint256(1)), + bytes32(uint256(2)), + messageHash, + new bytes(0) + ); } } diff --git a/contracts/src/test/L1ScrollMessengerTest.t.sol b/contracts/src/test/L1ScrollMessengerTest.t.sol index cac899317..936752097 100644 --- a/contracts/src/test/L1ScrollMessengerTest.t.sol +++ b/contracts/src/test/L1ScrollMessengerTest.t.sol @@ -12,81 +12,47 @@ import {Whitelist} from "../L2/predeploys/Whitelist.sol"; import {IL1ScrollMessenger, L1ScrollMessenger} from "../L1/L1ScrollMessenger.sol"; import {L2ScrollMessenger} from "../L2/L2ScrollMessenger.sol"; -contract L1ScrollMessengerTest is DSTestPlus { - L2ScrollMessenger internal l2Messenger; - - address internal feeVault; - - L1ScrollMessenger internal l1Messenger; - ScrollChain internal scrollChain; - L1MessageQueue internal l1MessageQueue; - L2GasPriceOracle internal gasOracle; - EnforcedTxGateway internal enforcedTxGateway; - Whitelist internal whitelist; +import {L1GatewayTestBase} from "./L1GatewayTestBase.t.sol"; +contract L1ScrollMessengerTest is L1GatewayTestBase { function setUp() public { - // Deploy L2 contracts - l2Messenger = new L2ScrollMessenger(address(0), address(0), address(0)); - - // Deploy L1 contracts - scrollChain = new ScrollChain(0); - l1MessageQueue = new L1MessageQueue(); - l1Messenger = new L1ScrollMessenger(); - gasOracle = new L2GasPriceOracle(); - enforcedTxGateway = new EnforcedTxGateway(); - whitelist = new Whitelist(address(this)); - - // Initialize L1 contracts - l1Messenger.initialize(address(l2Messenger), feeVault, address(scrollChain), address(l1MessageQueue)); - l1MessageQueue.initialize( - address(l1Messenger), - address(scrollChain), - address(enforcedTxGateway), - address(gasOracle), - 10000000 - ); - gasOracle.initialize(0, 0, 0, 0); - scrollChain.initialize(address(l1MessageQueue), address(0), 44); - - gasOracle.updateWhitelist(address(whitelist)); - address[] memory _accounts = new address[](1); - _accounts[0] = address(this); - whitelist.updateWhitelistStatus(_accounts, true); + L1GatewayTestBase.setUpBase(); } function testForbidCallMessageQueueFromL2() external { - // import genesis batch - bytes memory _batchHeader = new bytes(89); - assembly { - mstore(add(_batchHeader, add(0x20, 25)), 1) - } - scrollChain.importGenesisBatch( - _batchHeader, - bytes32(uint256(1)), - bytes32(0x3152134c22e545ab5d345248502b4f04ef5b45f735f939c7fe6ddc0ffefc9c52) + bytes32 _xDomainCalldataHash = keccak256( + abi.encodeWithSignature( + "relayMessage(address,address,uint256,uint256,bytes)", + address(this), + address(messageQueue), + 0, + 0, + new bytes(0) + ) ); + prepareL2MessageRoot(_xDomainCalldataHash); IL1ScrollMessenger.L2MessageProof memory proof; - proof.batchIndex = scrollChain.lastFinalizedBatchIndex(); + proof.batchIndex = rollup.lastFinalizedBatchIndex(); hevm.expectRevert("Forbid to call message queue"); - l1Messenger.relayMessageWithProof(address(this), address(l1MessageQueue), 0, 0, new bytes(0), proof); + l1Messenger.relayMessageWithProof(address(this), address(messageQueue), 0, 0, new bytes(0), proof); } function testForbidCallSelfFromL2() external { - // import genesis batch - bytes memory _batchHeader = new bytes(89); - assembly { - mstore(add(_batchHeader, 57), 1) - } - scrollChain.importGenesisBatch( - _batchHeader, - bytes32(uint256(1)), - bytes32(0xf7c03e2b13c88e3fca1410b228b001dd94e3f5ab4b4a4a6981d09a4eb3e5b631) + bytes32 _xDomainCalldataHash = keccak256( + abi.encodeWithSignature( + "relayMessage(address,address,uint256,uint256,bytes)", + address(this), + address(l1Messenger), + 0, + 0, + new bytes(0) + ) ); - + prepareL2MessageRoot(_xDomainCalldataHash); IL1ScrollMessenger.L2MessageProof memory proof; - proof.batchIndex = scrollChain.lastFinalizedBatchIndex(); + proof.batchIndex = rollup.lastFinalizedBatchIndex(); hevm.expectRevert("Forbid to call self"); l1Messenger.relayMessageWithProof(address(this), address(l1Messenger), 0, 0, new bytes(0), proof); @@ -110,7 +76,9 @@ contract L1ScrollMessengerTest is DSTestPlus { function testReplayMessage(uint256 exceedValue, address refundAddress) external { hevm.assume(refundAddress.code.length == 0); - hevm.assume(uint256(uint160(refundAddress)) > 100); // ignore some precompile contracts + hevm.assume(uint256(uint160(refundAddress)) > uint256(100)); // ignore some precompile contracts + hevm.assume(refundAddress != feeVault); + hevm.assume(refundAddress != address(0x000000000000000000636F6e736F6c652e6c6f67)); // ignore console/console2 exceedValue = bound(exceedValue, 1, address(this).balance / 2); @@ -170,7 +138,7 @@ contract L1ScrollMessengerTest is DSTestPlus { l1Messenger.sendMessage{value: _fee + value}(address(0), value, hex"0011220033", gasLimit); // update max gas limit - l1MessageQueue.updateMaxGasLimit(gasLimit); + messageQueue.updateMaxGasLimit(gasLimit); l1Messenger.sendMessage{value: _fee + value}(address(0), value, hex"0011220033", gasLimit); } } diff --git a/contracts/src/test/ScrollChain.t.sol b/contracts/src/test/ScrollChain.t.sol index 39f4e6bd4..039f58dd6 100644 --- a/contracts/src/test/ScrollChain.t.sol +++ b/contracts/src/test/ScrollChain.t.sol @@ -53,7 +53,7 @@ contract ScrollChainTest is DSTestPlus { assembly { mstore(add(batchHeader0, add(0x20, 25)), 1) } - rollup.importGenesisBatch(batchHeader0, bytes32(uint256(1)), bytes32(uint256(0))); + rollup.importGenesisBatch(batchHeader0, bytes32(uint256(1))); // caller not sequencer, revert hevm.expectRevert("caller not sequencer"); @@ -136,7 +136,7 @@ contract ScrollChainTest is DSTestPlus { assembly { mstore(add(batchHeader0, add(0x20, 25)), 1) } - rollup.importGenesisBatch(batchHeader0, bytes32(uint256(1)), bytes32(uint256(0))); + rollup.importGenesisBatch(batchHeader0, bytes32(uint256(1))); bytes32 batchHash0 = rollup.committedBatches(0); bytes[] memory chunks = new bytes[](1); @@ -228,7 +228,7 @@ contract ScrollChainTest is DSTestPlus { assembly { mstore(add(batchHeader0, add(0x20, 25)), 1) } - rollup.importGenesisBatch(batchHeader0, bytes32(uint256(1)), bytes32(uint256(0))); + rollup.importGenesisBatch(batchHeader0, bytes32(uint256(1))); bytes32 batchHash0 = rollup.committedBatches(0); bytes memory bitmap; @@ -243,28 +243,28 @@ contract ScrollChainTest is DSTestPlus { // 0000000000000000000000000000000000000000000000000000000000000000 // 0000000000000000 // 0001 - // 50c3caa727394b95dc4885b7d25033ed22ac772b985fb274f2a7c0699a11346d + // a2277fd30bbbe74323309023b56035b376d7768ad237ae4fc46ead7dc9591ae1 // => data hash for chunk0 - // bb88f47194a07d59ed17bc9b2015f83d0afea8f7892d9c5f0b6565563bf06b26 + // 9ef1e5694bdb014a1eea42be756a8f63bfd8781d6332e9ef3b5126d90c62f110 // => data hash for all chunks - // 038433daac85a0b03cd443ed50bc85e832c883061651ae2182b2984751e0b340 + // d9cb6bf9264006fcea490d5c261f7453ab95b1b26033a3805996791b8e3a62f3 // => payload for batch header // 00 - // 0000000000000002 // 0000000000000001 // 0000000000000001 - // 038433daac85a0b03cd443ed50bc85e832c883061651ae2182b2984751e0b340 + // 0000000000000001 + // d9cb6bf9264006fcea490d5c261f7453ab95b1b26033a3805996791b8e3a62f3 // 119b828c2a2798d2c957228ebeaff7e10bb099ae0d4e224f3eeb779ff61cba61 // 0000000000000000000000000000000000000000000000000000000000000000 // => hash for batch header - // cef70bf80683c4d9b8b2813e90c314e8c56648e231300b8cfed9d666b0caf14e + // 00847173b29b238cf319cde79512b7c213e5a8b4138daa7051914c4592b6dfc7 bytes memory batchHeader1 = new bytes(89 + 32); assembly { mstore(add(batchHeader1, 0x20), 0) // version mstore(add(batchHeader1, add(0x20, 1)), shl(192, 1)) // batchIndex = 1 mstore(add(batchHeader1, add(0x20, 9)), shl(192, 1)) // l1MessagePopped = 1 mstore(add(batchHeader1, add(0x20, 17)), shl(192, 1)) // totalL1MessagePopped = 1 - mstore(add(batchHeader1, add(0x20, 25)), 0x038433daac85a0b03cd443ed50bc85e832c883061651ae2182b2984751e0b340) // dataHash + mstore(add(batchHeader1, add(0x20, 25)), 0xd9cb6bf9264006fcea490d5c261f7453ab95b1b26033a3805996791b8e3a62f3) // dataHash mstore(add(batchHeader1, add(0x20, 57)), batchHash0) // parentBatchHash mstore(add(batchHeader1, add(0x20, 89)), 0) // bitmap0 } @@ -280,7 +280,7 @@ contract ScrollChainTest is DSTestPlus { rollup.commitBatch(0, batchHeader0, chunks, bitmap); assertBoolEq(rollup.isBatchFinalized(1), false); bytes32 batchHash1 = rollup.committedBatches(1); - assertEq(batchHash1, bytes32(0xcef70bf80683c4d9b8b2813e90c314e8c56648e231300b8cfed9d666b0caf14e)); + assertEq(batchHash1, bytes32(0x00847173b29b238cf319cde79512b7c213e5a8b4138daa7051914c4592b6dfc7)); // finalize batch1 rollup.finalizeBatchWithProof( @@ -330,26 +330,26 @@ contract ScrollChainTest is DSTestPlus { // 012c // ... (some tx hashes) // => data hash for chunk2 - // 5c91563ee8be18cb94accfc83728f883ff5e3aa600fd0799e0a4e39afc7970b9 + // 0520f1fbe159af97fdf1d6cfcfe7605f99f7bfe3ed876e87b64250b1810df00b // => data hash for all chunks - // bf38f308e0a87ed7bf92fa2da038fa1d59a7b9801eb0f6d487f8eef528632145 + // f52343299f6379fd15b20b23d51fc61b9b357b124be112686626b6278bcffa83 // => payload for batch header // 00 // 0000000000000002 // 0000000000000108 // 0000000000000109 - // bf38f308e0a87ed7bf92fa2da038fa1d59a7b9801eb0f6d487f8eef528632145 + // f52343299f6379fd15b20b23d51fc61b9b357b124be112686626b6278bcffa83 // cef70bf80683c4d9b8b2813e90c314e8c56648e231300b8cfed9d666b0caf14e // aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa800000000000000000000000000000000000000000000000000000000000000aa // => hash for batch header - // 17fe6c12739f3a6261ae6db6486f41758dbd5d0508f19a5ca9ac37df67bbfec2 + // 2231cf185a5c07931584f970738b4cd2ae4fb39e2d90853b26746c7616ea71b9 bytes memory batchHeader2 = new bytes(89 + 32 + 32); assembly { mstore(add(batchHeader2, 0x20), 0) // version mstore(add(batchHeader2, add(0x20, 1)), shl(192, 2)) // batchIndex = 2 mstore(add(batchHeader2, add(0x20, 9)), shl(192, 264)) // l1MessagePopped = 264 mstore(add(batchHeader2, add(0x20, 17)), shl(192, 265)) // totalL1MessagePopped = 265 - mstore(add(batchHeader2, add(0x20, 25)), 0xbf38f308e0a87ed7bf92fa2da038fa1d59a7b9801eb0f6d487f8eef528632145) // dataHash + mstore(add(batchHeader2, add(0x20, 25)), 0xf52343299f6379fd15b20b23d51fc61b9b357b124be112686626b6278bcffa83) // dataHash mstore(add(batchHeader2, add(0x20, 57)), batchHash1) // parentBatchHash mstore( add(batchHeader2, add(0x20, 89)), @@ -398,7 +398,7 @@ contract ScrollChainTest is DSTestPlus { rollup.commitBatch(0, batchHeader1, chunks, bitmap); assertBoolEq(rollup.isBatchFinalized(2), false); bytes32 batchHash2 = rollup.committedBatches(2); - assertEq(batchHash2, bytes32(0x17fe6c12739f3a6261ae6db6486f41758dbd5d0508f19a5ca9ac37df67bbfec2)); + assertEq(batchHash2, bytes32(0x2231cf185a5c07931584f970738b4cd2ae4fb39e2d90853b26746c7616ea71b9)); // verify committed batch correctly rollup.finalizeBatchWithProof( @@ -450,7 +450,7 @@ contract ScrollChainTest is DSTestPlus { assembly { mstore(add(batchHeader0, add(0x20, 25)), 1) } - rollup.importGenesisBatch(batchHeader0, bytes32(uint256(1)), bytes32(uint256(0))); + rollup.importGenesisBatch(batchHeader0, bytes32(uint256(1))); bytes32 batchHash0 = rollup.committedBatches(0); bytes[] memory chunks = new bytes[](1); @@ -577,52 +577,52 @@ contract ScrollChainTest is DSTestPlus { // zero state root, revert batchHeader = new bytes(89); hevm.expectRevert("zero state root"); - rollup.importGenesisBatch(batchHeader, bytes32(0), bytes32(0)); + rollup.importGenesisBatch(batchHeader, bytes32(0)); // batch header length too small, revert batchHeader = new bytes(88); hevm.expectRevert("batch header length too small"); - rollup.importGenesisBatch(batchHeader, bytes32(uint256(1)), bytes32(0)); + rollup.importGenesisBatch(batchHeader, bytes32(uint256(1))); // wrong bitmap length, revert batchHeader = new bytes(90); hevm.expectRevert("wrong bitmap length"); - rollup.importGenesisBatch(batchHeader, bytes32(uint256(1)), bytes32(0)); + rollup.importGenesisBatch(batchHeader, bytes32(uint256(1))); // not all fields are zero, revert batchHeader = new bytes(89); batchHeader[0] = bytes1(uint8(1)); // version not zero hevm.expectRevert("not all fields are zero"); - rollup.importGenesisBatch(batchHeader, bytes32(uint256(1)), bytes32(0)); + rollup.importGenesisBatch(batchHeader, bytes32(uint256(1))); batchHeader = new bytes(89); batchHeader[1] = bytes1(uint8(1)); // batchIndex not zero hevm.expectRevert("not all fields are zero"); - rollup.importGenesisBatch(batchHeader, bytes32(uint256(1)), bytes32(0)); + rollup.importGenesisBatch(batchHeader, bytes32(uint256(1))); batchHeader = new bytes(89 + 32); assembly { mstore(add(batchHeader, add(0x20, 9)), shl(192, 1)) // l1MessagePopped not zero } hevm.expectRevert("not all fields are zero"); - rollup.importGenesisBatch(batchHeader, bytes32(uint256(1)), bytes32(0)); + rollup.importGenesisBatch(batchHeader, bytes32(uint256(1))); batchHeader = new bytes(89); batchHeader[17] = bytes1(uint8(1)); // totalL1MessagePopped not zero hevm.expectRevert("not all fields are zero"); - rollup.importGenesisBatch(batchHeader, bytes32(uint256(1)), bytes32(0)); + rollup.importGenesisBatch(batchHeader, bytes32(uint256(1))); // zero data hash, revert batchHeader = new bytes(89); hevm.expectRevert("zero data hash"); - rollup.importGenesisBatch(batchHeader, bytes32(uint256(1)), bytes32(0)); + rollup.importGenesisBatch(batchHeader, bytes32(uint256(1))); // nonzero parent batch hash, revert batchHeader = new bytes(89); batchHeader[25] = bytes1(uint8(1)); // dataHash not zero batchHeader[57] = bytes1(uint8(1)); // parentBatchHash not zero hevm.expectRevert("nonzero parent batch hash"); - rollup.importGenesisBatch(batchHeader, bytes32(uint256(1)), bytes32(0)); + rollup.importGenesisBatch(batchHeader, bytes32(uint256(1))); // import correctly batchHeader = new bytes(89); @@ -630,13 +630,13 @@ contract ScrollChainTest is DSTestPlus { assertEq(rollup.finalizedStateRoots(0), bytes32(0)); assertEq(rollup.withdrawRoots(0), bytes32(0)); assertEq(rollup.committedBatches(0), bytes32(0)); - rollup.importGenesisBatch(batchHeader, bytes32(uint256(1)), bytes32(uint256(2))); + rollup.importGenesisBatch(batchHeader, bytes32(uint256(1))); assertEq(rollup.finalizedStateRoots(0), bytes32(uint256(1))); - assertEq(rollup.withdrawRoots(0), bytes32(uint256(2))); + assertEq(rollup.withdrawRoots(0), bytes32(0)); assertGt(uint256(rollup.committedBatches(0)), 0); // Genesis batch imported, revert hevm.expectRevert("Genesis batch imported"); - rollup.importGenesisBatch(batchHeader, bytes32(uint256(1)), bytes32(uint256(2))); + rollup.importGenesisBatch(batchHeader, bytes32(uint256(1))); } }