Files
smom-dbis-138/contracts/tether/MainnetTether.sol
defiQUG 1fb7266469 Add Oracle Aggregator and CCIP Integration
- Introduced Aggregator.sol for Chainlink-compatible oracle functionality, including round-based updates and access control.
- Added OracleWithCCIP.sol to extend Aggregator with CCIP cross-chain messaging capabilities.
- Created .gitmodules to include OpenZeppelin contracts as a submodule.
- Developed a comprehensive deployment guide in NEXT_STEPS_COMPLETE_GUIDE.md for Phase 2 and smart contract deployment.
- Implemented Vite configuration for the orchestration portal, supporting both Vue and React frameworks.
- Added server-side logic for the Multi-Cloud Orchestration Portal, including API endpoints for environment management and monitoring.
- Created scripts for resource import and usage validation across non-US regions.
- Added tests for CCIP error handling and integration to ensure robust functionality.
- Included various new files and directories for the orchestration portal and deployment scripts.
2025-12-12 14:57:48 -08:00

186 lines
5.6 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
/**
* @title MainnetTether
* @notice Anchors Chain-138 state proofs to Ethereum Mainnet (Kaleido-style)
* @dev Stores signed state proofs from Chain-138 validators, creating an immutable
* and verifiable record of Chain-138's state on Mainnet
*/
contract MainnetTether {
address public admin;
bool public paused;
// Chain-138 chain ID
uint64 public constant CHAIN_138 = 138;
// State proof structure
struct StateProof {
uint256 blockNumber; // Chain-138 block number
bytes32 blockHash; // Chain-138 block hash
bytes32 stateRoot; // Chain-138 state root
bytes32 previousBlockHash; // Previous block hash
uint256 timestamp; // Block timestamp
bytes signatures; // Collective signatures from validators
uint256 validatorCount; // Number of validators that signed
bytes32 proofHash; // Hash of the proof (for indexing)
}
// Mapping: blockNumber => StateProof
mapping(uint256 => StateProof) public stateProofs;
// Array of all anchored block numbers (for iteration)
uint256[] public anchoredBlocks;
// Mapping: proofHash => bool (replay protection)
mapping(bytes32 => bool) public processed;
// Events
event AdminChanged(address indexed newAdmin);
event Paused();
event Unpaused();
event StateProofAnchored(
uint256 indexed blockNumber,
bytes32 indexed blockHash,
bytes32 indexed stateRoot,
uint256 timestamp,
uint256 validatorCount
);
modifier onlyAdmin() {
require(msg.sender == admin, "only admin");
_;
}
modifier whenNotPaused() {
require(!paused, "paused");
_;
}
constructor(address _admin) {
require(_admin != address(0), "zero admin");
admin = _admin;
}
/**
* @notice Anchor a state proof from Chain-138
* @param blockNumber Chain-138 block number
* @param blockHash Chain-138 block hash
* @param stateRoot Chain-138 state root
* @param previousBlockHash Previous block hash
* @param timestamp Block timestamp
* @param signatures Collective signatures from validators
* @param validatorCount Number of validators that signed
*/
function anchorStateProof(
uint256 blockNumber,
bytes32 blockHash,
bytes32 stateRoot,
bytes32 previousBlockHash,
uint256 timestamp,
bytes calldata signatures,
uint256 validatorCount
) external onlyAdmin whenNotPaused {
require(blockNumber > 0, "invalid block");
require(blockHash != bytes32(0), "invalid hash");
require(stateRoot != bytes32(0), "invalid state root");
require(validatorCount > 0, "no validators");
require(signatures.length > 0, "no signatures");
// Calculate proof hash for replay protection
bytes32 proofHash = keccak256(
abi.encodePacked(
blockNumber,
blockHash,
stateRoot,
previousBlockHash,
timestamp,
signatures
)
);
require(!processed[proofHash], "already processed");
require(stateProofs[blockNumber].blockNumber == 0, "block already anchored");
// Store state proof
stateProofs[blockNumber] = StateProof({
blockNumber: blockNumber,
blockHash: blockHash,
stateRoot: stateRoot,
previousBlockHash: previousBlockHash,
timestamp: timestamp,
signatures: signatures,
validatorCount: validatorCount,
proofHash: proofHash
});
anchoredBlocks.push(blockNumber);
processed[proofHash] = true;
emit StateProofAnchored(
blockNumber,
blockHash,
stateRoot,
timestamp,
validatorCount
);
}
/**
* @notice Get state proof for a specific block
* @param blockNumber Chain-138 block number
* @return proof State proof structure
*/
function getStateProof(uint256 blockNumber) external view returns (StateProof memory proof) {
require(stateProofs[blockNumber].blockNumber != 0, "not anchored");
return stateProofs[blockNumber];
}
/**
* @notice Check if a block is anchored
* @param blockNumber Chain-138 block number
* @return true if anchored
*/
function isAnchored(uint256 blockNumber) external view returns (bool) {
return stateProofs[blockNumber].blockNumber != 0;
}
/**
* @notice Get total number of anchored blocks
* @return count Number of anchored blocks
*/
function getAnchoredBlockCount() external view returns (uint256) {
return anchoredBlocks.length;
}
/**
* @notice Get anchored block number at index
* @param index Index in anchoredBlocks array
* @return blockNumber Block number
*/
function getAnchoredBlock(uint256 index) external view returns (uint256) {
require(index < anchoredBlocks.length, "out of bounds");
return anchoredBlocks[index];
}
/**
* @notice Admin functions
*/
function setAdmin(address newAdmin) external onlyAdmin {
require(newAdmin != address(0), "zero admin");
admin = newAdmin;
emit AdminChanged(newAdmin);
}
function pause() external onlyAdmin {
paused = true;
emit Paused();
}
function unpause() external onlyAdmin {
paused = false;
emit Unpaused();
}
}