Some checks failed
CI/CD Pipeline / Solidity Contracts (push) Failing after 1m3s
CI/CD Pipeline / Security Scanning (push) Successful in 2m18s
CI/CD Pipeline / Lint and Format (push) Failing after 34s
CI/CD Pipeline / Terraform Validation (push) Failing after 20s
CI/CD Pipeline / Kubernetes Validation (push) Successful in 22s
Deploy ChainID 138 / Deploy ChainID 138 (push) Failing after 40s
HYBX OMNL TypeScript & anchor / token-aggregation build + reconcile artifact (push) Failing after 49s
OMNL reconcile anchor / Run omnl:reconcile and upload artifacts (push) Failing after 21s
Validation / validate-genesis (push) Successful in 25s
Validation / validate-terraform (push) Failing after 21s
Validation / validate-kubernetes (push) Failing after 8s
Validation / validate-smart-contracts (push) Failing after 8s
Validation / validate-security (push) Failing after 1m11s
Validation / validate-documentation (push) Failing after 14s
Verify Deployment / Verify Deployment (push) Failing after 45s
Ship AddressActivityRegistry V1/V2, ISO20022IntakeGateway, Chain138ParticipantSurface, checkpoint hub contracts, checkpoint-core package, aggregator/indexer/sdk services, relay profile guards, M00 diamond bridge facet, and OMNL compliance contracts. Co-authored-by: Cursor <cursoragent@cursor.com>
146 lines
5.6 KiB
Solidity
146 lines
5.6 KiB
Solidity
// SPDX-License-Identifier: MIT
|
|
pragma solidity ^0.8.20;
|
|
|
|
import "@openzeppelin/contracts/access/AccessControl.sol";
|
|
import "../M00BridgeStorage.sol";
|
|
import "../interfaces/IM00MainnetBridgeFacet.sol";
|
|
import "../interfaces/IChain138BatchEmitterBridge.sol";
|
|
import "../interfaces/ILegacyMainnetMirror.sol";
|
|
|
|
/**
|
|
* @title M00MainnetBridgeFacet
|
|
* @notice ERC-2535 facet: two-way Chain 138 ↔ Mainnet attestation path.
|
|
* @dev Outbound: Chain138BatchEmitter (CCIP) + optional direct v1 mirror/tether relay on mainnet.
|
|
* Inbound: ackInboundCheckpoint after CCIP delivery (relayer/emitter calls on 138).
|
|
* Full tx mirror on mainnet is executed by operator/aggregator with MAINNET mirror admin — hub schedules + correlates.
|
|
*/
|
|
contract M00MainnetBridgeFacet is AccessControl, IM00MainnetBridgeFacet {
|
|
bytes32 public constant BRIDGE_OPERATOR_ROLE = keccak256("BRIDGE_OPERATOR_ROLE");
|
|
bytes32 public constant MIRROR_RELAYER_ROLE = keccak256("MIRROR_RELAYER_ROLE");
|
|
|
|
constructor(address admin) {
|
|
_grantRole(DEFAULT_ADMIN_ROLE, admin);
|
|
_grantRole(BRIDGE_OPERATOR_ROLE, admin);
|
|
_grantRole(MIRROR_RELAYER_ROLE, admin);
|
|
}
|
|
|
|
function wireMainnetBridge(BridgeConfig calldata cfg) external onlyRole(DEFAULT_ADMIN_ROLE) {
|
|
M00BridgeStorage.Layout storage l = M00BridgeStorage.layout();
|
|
l.chain138BatchEmitter = cfg.chain138BatchEmitter;
|
|
l.chain138Mirror = cfg.chain138Mirror;
|
|
l.mainnetCheckpoint = cfg.mainnetCheckpoint;
|
|
l.mainnetMirror = cfg.mainnetMirror;
|
|
l.mainnetTether = cfg.mainnetTether;
|
|
l.rwaTokenFactory = cfg.rwaTokenFactory;
|
|
l.rwaTokenRegistry = cfg.rwaTokenRegistry;
|
|
emit MainnetBridgeWired(cfg);
|
|
}
|
|
|
|
function getMainnetBridgeConfig() external view returns (BridgeConfig memory) {
|
|
M00BridgeStorage.Layout storage l = M00BridgeStorage.layout();
|
|
return BridgeConfig({
|
|
chain138BatchEmitter: l.chain138BatchEmitter,
|
|
chain138Mirror: l.chain138Mirror,
|
|
mainnetCheckpoint: l.mainnetCheckpoint,
|
|
mainnetMirror: l.mainnetMirror,
|
|
mainnetTether: l.mainnetTether,
|
|
rwaTokenFactory: l.rwaTokenFactory,
|
|
rwaTokenRegistry: l.rwaTokenRegistry
|
|
});
|
|
}
|
|
|
|
function commitBatchOn138(
|
|
uint64 batchId,
|
|
bytes32 paymentsRoot,
|
|
uint256 checkpointBlock,
|
|
uint256 startBlock,
|
|
uint16 txCount,
|
|
bytes32[] calldata txHashes
|
|
) external onlyRole(BRIDGE_OPERATOR_ROLE) {
|
|
address emitter = M00BridgeStorage.layout().chain138BatchEmitter;
|
|
require(emitter != address(0), "M00Bridge: emitter");
|
|
IChain138BatchEmitterBridge(emitter).commitBatch(
|
|
batchId, paymentsRoot, checkpointBlock, startBlock, txCount, txHashes
|
|
);
|
|
M00BridgeStorage.layout().lastCommittedBatchId = batchId;
|
|
M00BridgeStorage.layout().lastAnchoredBlock138 = checkpointBlock;
|
|
emit BatchCommittedOnHub(batchId, paymentsRoot, checkpointBlock);
|
|
}
|
|
|
|
function sendBatchToMainnet(uint64 batchId, bytes calldata encodedCheckpointPayload, uint256 linkFee)
|
|
external
|
|
onlyRole(BRIDGE_OPERATOR_ROLE)
|
|
returns (bytes32 ccipMessageId)
|
|
{
|
|
address emitter = M00BridgeStorage.layout().chain138BatchEmitter;
|
|
require(emitter != address(0), "M00Bridge: emitter");
|
|
return IChain138BatchEmitterBridge(emitter).sendBatchToMainnet(batchId, encodedCheckpointPayload, linkFee);
|
|
}
|
|
|
|
/// @notice Record mirror intent; relayer with MIRROR_RELAYER_ROLE calls mirrorOnMainnet on mainnet.
|
|
function scheduleMirrorToMainnet(
|
|
bytes32 txHash,
|
|
address from,
|
|
address to,
|
|
uint256 value,
|
|
uint256 blockNumber,
|
|
uint256 blockTimestamp,
|
|
uint256 gasUsed,
|
|
bool success,
|
|
bytes calldata data
|
|
) external onlyRole(BRIDGE_OPERATOR_ROLE) {
|
|
txHash;
|
|
from;
|
|
to;
|
|
value;
|
|
blockTimestamp;
|
|
gasUsed;
|
|
success;
|
|
data;
|
|
emit OutboundMirrorScheduled(txHash, blockNumber);
|
|
}
|
|
|
|
/// @notice Relayer executes v1 TransactionMirror.mirrorTransaction on Ethereum mainnet (separate chain).
|
|
function mirrorOnMainnet(
|
|
bytes32 txHash,
|
|
address from,
|
|
address to,
|
|
uint256 value,
|
|
uint256 blockNumber,
|
|
uint256 blockTimestamp,
|
|
uint256 gasUsed,
|
|
bool success,
|
|
bytes calldata data
|
|
) external onlyRole(MIRROR_RELAYER_ROLE) {
|
|
address mirror = M00BridgeStorage.layout().mainnetMirror;
|
|
require(mirror != address(0), "M00Bridge: mirror");
|
|
ILegacyMainnetMirror(mirror).mirrorTransaction(
|
|
txHash, from, to, value, blockNumber, blockTimestamp, gasUsed, success, data
|
|
);
|
|
}
|
|
|
|
function anchorStateProofOnMainnet(
|
|
uint256 blockNumber,
|
|
bytes32 blockHash,
|
|
bytes32 stateRoot,
|
|
bytes32 previousBlockHash,
|
|
uint256 timestamp,
|
|
bytes calldata signatures,
|
|
uint256 validatorCount
|
|
) external onlyRole(MIRROR_RELAYER_ROLE) {
|
|
address tether = M00BridgeStorage.layout().mainnetTether;
|
|
require(tether != address(0), "M00Bridge: tether");
|
|
ILegacyMainnetTether(tether).anchorStateProof(
|
|
blockNumber, blockHash, stateRoot, previousBlockHash, timestamp, signatures, validatorCount
|
|
);
|
|
M00BridgeStorage.layout().lastAnchoredBlock138 = blockNumber;
|
|
}
|
|
|
|
function ackInboundCheckpoint(uint64 batchId, bytes32 paymentsRoot)
|
|
external
|
|
onlyRole(BRIDGE_OPERATOR_ROLE)
|
|
{
|
|
emit InboundCheckpointAck(batchId, paymentsRoot);
|
|
}
|
|
}
|