// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import {Test} from "forge-std/Test.sol"; import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; import {Chain138MainnetCheckpoint} from "../../contracts/mainnet-checkpoint/Chain138MainnetCheckpoint.sol"; import {CheckpointStorage} from "../../contracts/mainnet-checkpoint/storage/CheckpointStorage.sol"; import {CheckpointLeaf} from "../../contracts/mainnet-checkpoint/libraries/CheckpointLeaf.sol"; import {CheckpointFlags} from "../../contracts/mainnet-checkpoint/libraries/CheckpointFlags.sol"; import {CheckpointErrors} from "../../contracts/mainnet-checkpoint/libraries/CheckpointErrors.sol"; contract Chain138MainnetCheckpointTest is Test { Chain138MainnetCheckpoint checkpoint; address admin = address(0xA11CE); address submitter = address(0xB0B); function setUp() public { Chain138MainnetCheckpoint impl = new Chain138MainnetCheckpoint(); bytes memory initData = abi.encodeCall( Chain138MainnetCheckpoint.initialize, (admin, address(0xC0C0C0C0), uint64(1380001), address(0)) ); checkpoint = Chain138MainnetCheckpoint(address(new ERC1967Proxy(address(impl), initData))); vm.startPrank(admin); checkpoint.grantRole(checkpoint.SUBMITTER_ROLE(), submitter); vm.stopPrank(); } function _leaf(bytes32 txHash) internal pure returns (CheckpointLeaf.PaymentLeafV1 memory) { return CheckpointLeaf.PaymentLeafV1({ txHash: txHash, from: address(1), to: address(2), value: 1 ether, blockNumber: 100, blockTimestamp: 1, gasUsed: 21000, success: true }); } function _buildRoot(CheckpointLeaf.PaymentLeafV1[] memory leaves) internal pure returns (bytes32) { require(leaves.length == 1, "single leaf test"); return CheckpointLeaf.paymentLeafV1(138, leaves[0]); } function testSubmitCheckpointUpdatesLatest() public { CheckpointLeaf.PaymentLeafV1[] memory leaves = new CheckpointLeaf.PaymentLeafV1[](1); leaves[0] = _leaf(keccak256("tx1")); bytes32 root = _buildRoot(leaves); CheckpointStorage.CheckpointHeader memory header = CheckpointStorage.CheckpointHeader({ batchId: 1, previousBatchId: 0, chainId: 138, checkpointBlock: 100, startBlock: 99, endBlock: 100, blockHash: keccak256("bh"), stateRoot: keccak256("sr"), paymentsRoot: root, receiptsRoot: bytes32(0), txCount: 1, flags: CheckpointFlags.PARTIAL_BATCH, submittedAt: 0, submitter: address(0), contentURI: bytes32(0) }); bytes32[] memory hashes = new bytes32[](1); hashes[0] = leaves[0].txHash; vm.prank(submitter); checkpoint.submitCheckpoint(header, hex"01", hashes, abi.encode(leaves)); assertEq(checkpoint.getLatestBatchId(), 1); assertEq(checkpoint.getLatestCheckpoint().paymentsRoot, root); (bool inc,) = checkpoint.isTxIncluded(leaves[0].txHash); assertTrue(inc); } function testPauseBlocksSubmit() public { vm.prank(admin); checkpoint.pause(); CheckpointStorage.CheckpointHeader memory header; vm.prank(submitter); vm.expectRevert(CheckpointErrors.Paused.selector); checkpoint.submitCheckpoint(header, hex"01", new bytes32[](0), ""); } }