// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import {CheckpointStorage} from "./storage/CheckpointStorage.sol"; import {IChain138MainnetCheckpoint} from "./interfaces/IChain138MainnetCheckpoint.sol"; interface ILegacyTransactionMirror { function getMirroredTransactionCount() external view returns (uint256); function transactions(bytes32 txHash) external view returns ( bytes32, address, address, uint256, uint256, uint256, uint256, bool, bytes memory, bytes32 ); } interface ILegacyMainnetTether { function stateProofs(uint256 blockNumber) external view returns ( uint256, bytes32, bytes32, bytes32, uint256, bytes memory, uint256, bytes32 ); } /// @notice Read-only unified view over v1 mirror/tether + v2 checkpoint hub. contract LegacyCheckpointAdapter { IChain138MainnetCheckpoint public immutable checkpointV2; ILegacyTransactionMirror public immutable mirrorV1; ILegacyMainnetTether public immutable tetherV1; constructor(address checkpoint, address mirror, address tether) { checkpointV2 = IChain138MainnetCheckpoint(checkpoint); mirrorV1 = ILegacyTransactionMirror(mirror); tetherV1 = ILegacyMainnetTether(tether); } function latestAttestationBlock() external view returns (uint256 blockNumber, uint64 batchId, bool fromV2) { batchId = checkpointV2.getLatestBatchId(); if (batchId > 0) { CheckpointStorage.CheckpointHeader memory h = checkpointV2.getLatestCheckpoint(); return (h.checkpointBlock, batchId, true); } return (0, 0, false); } function isTxMirroredV1(bytes32 txHash) external view returns (bool) { (, , , , uint256 blockNumber, , , , , ) = mirrorV1.transactions(txHash); return blockNumber > 0; } function getTetherStateRoot(uint256 blockNumber) external view returns (bytes32 stateRoot, bool found) { (, , stateRoot, , , , , ) = tetherV1.stateProofs(blockNumber); found = stateRoot != bytes32(0); } function v1MirrorCount() external view returns (uint256) { return mirrorV1.getMirroredTransactionCount(); } }