- 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.
7.5 KiB
Kaleido Tether and Mirror Pattern Implementation
Date: 2025-12-11 Reference: Kaleido's cross-chain architecture patterns
📚 Understanding Kaleido's Patterns
Tether Contract (State Anchoring)
In Kaleido's architecture, a Tether contract is deployed on a public Ethereum network (e.g., Mainnet) that:
- Stores signed state proofs from a private blockchain network
- Creates an immutable, verifiable record of the private chain's state
- Anchors the private chain's state to the public network at specific intervals
- Provides security and transparency by making state proofs publicly verifiable
- Prevents collusion by requiring collective signatures from all nodes
Purpose: State anchoring and integrity verification across chains
Mirror Contract (Address Registry)
In Kaleido's architecture, a Mirror contract:
- Maintains a registry of mirrored token/contract addresses across chains
- Maps source chain addresses to destination chain addresses
- Provides replay protection for cross-chain operations
- Enables address resolution for cross-chain interactions
Purpose: Address mapping and cross-chain contract resolution
🔍 Implementation in This Codebase
1. MirrorManager Contract ✅
File: contracts/mirror/MirrorManager.sol
Status: ✅ Available, ❌ Not deployed to Mainnet
Functionality:
- Registry of mirrored token/contract addresses across chains
- Mapping:
(sourceChain, sourceAddress) => (destChain => destAddress) - Replay protection via
processedmapping - Pausability for emergency stops
- Admin-controlled configuration
Kaleido Pattern: ✅ Implements Mirror pattern
Deployment:
forge script script/DeployMirrorManager.s.sol \
--rpc-url $ETH_MAINNET_RPC_URL \
--private-key $PRIVATE_KEY \
--broadcast \
--verify
Required Environment Variables:
MIRROR_ADMIN- Admin address (multisig recommended)
2. TwoWayTokenBridge (Tether-like Pattern) ✅
Files:
contracts/bridge/TwoWayTokenBridgeL1.sol(Mainnet/L1 side)contracts/bridge/TwoWayTokenBridgeL2.sol(Chain-138/L2 side)
Status: ✅ Available, ❌ Not deployed to Mainnet
Functionality:
- L1 Side: Locks canonical tokens and sends CCIP messages to mint on L2
- L2 Side: Mints mirrored tokens on inbound, burns on outbound
- State synchronization via CCIP messages
- Replay protection
- Destination chain configuration
Kaleido Pattern: ✅ Implements Tether-like pattern (state synchronization)
Deployment:
forge script script/DeployTwoWayBridge.s.sol \
--rpc-url $ETH_MAINNET_RPC_URL \
--private-key $PRIVATE_KEY \
--broadcast \
--verify
Required Environment Variables:
CCIP_ROUTER- CCIP router address (set)CCIP_FEE_TOKEN- LINK token address (set)BRIDGE_L1_TOKEN- Canonical token on Mainnet (NOT SET)BRIDGE_L2_TOKEN- Mintable token on Chain-138 (NOT SET)
🔄 Relationship Between Contracts
MirrorManager + TwoWayTokenBridge
-
MirrorManager maintains the address registry:
- Maps Mainnet token addresses to Chain-138 addresses
- Used by other contracts to resolve cross-chain addresses
-
TwoWayTokenBridge handles token transfers:
- Uses MirrorManager to resolve destination addresses
- Locks tokens on L1, mints on L2 (or vice versa)
- Maintains state synchronization via CCIP
Typical Flow:
User on Mainnet
↓
TwoWayTokenBridgeL1.lockAndSend()
↓
CCIP Message → Chain-138
↓
TwoWayTokenBridgeL2.ccipReceive()
↓
MirrorManager.getMirror() → Resolve address
↓
Mint mirrored tokens on Chain-138
📋 Deployment Status
✅ Available Contracts
| Contract | Pattern | Status | Deployment Script |
|---|---|---|---|
| MirrorManager | Mirror | ❌ Not Deployed | script/DeployMirrorManager.s.sol |
| TwoWayTokenBridgeL1 | Tether-like | ❌ Not Deployed | script/DeployTwoWayBridge.s.sol |
| TwoWayTokenBridgeL2 | Tether-like | ❌ Not Deployed | script/DeployTwoWayBridge.s.sol |
⚠️ Missing Configuration
MirrorManager:
MIRROR_ADMIN- Not set in.env
TwoWayTokenBridge:
BRIDGE_L1_TOKEN- Not set in.envBRIDGE_L2_TOKEN- Not set in.env
🚀 Deployment Plan
Step 1: Deploy MirrorManager
# Set admin address (multisig recommended)
export MIRROR_ADMIN=0x...
# Deploy
forge script script/DeployMirrorManager.s.sol \
--rpc-url $ETH_MAINNET_RPC_URL \
--private-key $PRIVATE_KEY \
--broadcast \
--verify
# Update .env
echo "MIRRORMANAGER_MAINNET=<deployed_address>" >> .env
Step 2: Deploy TwoWayTokenBridge
# Set token addresses
export BRIDGE_L1_TOKEN=0x... # Canonical token on Mainnet
export BRIDGE_L2_TOKEN=0x... # Mintable token on Chain-138
# Deploy (deploys both L1 and L2)
forge script script/DeployTwoWayBridge.s.sol \
--rpc-url $ETH_MAINNET_RPC_URL \
--private-key $PRIVATE_KEY \
--broadcast \
--verify
# Update .env
echo "TWOWAY_BRIDGE_L1_MAINNET=<l1_address>" >> .env
echo "TWOWAY_BRIDGE_L2_CHAIN138=<l2_address>" >> .env
Step 3: Configure MirrorManager
# Register bridge addresses in MirrorManager
cast send $MIRRORMANAGER_MAINNET \
"setMirror(uint64,address,uint64,address)" \
1 \ # Mainnet chain selector
$TWOWAY_BRIDGE_L1_MAINNET \
138 \ # Chain-138 selector
$TWOWAY_BRIDGE_L2_CHAIN138 \
--rpc-url $ETH_MAINNET_RPC_URL \
--private-key $PRIVATE_KEY
Step 4: Configure TwoWayTokenBridge
# Configure L1 bridge to point to L2
cast send $TWOWAY_BRIDGE_L1_MAINNET \
"addDestination(uint64,address)" \
138 \ # Chain-138 selector
$TWOWAY_BRIDGE_L2_CHAIN138 \
--rpc-url $ETH_MAINNET_RPC_URL \
--private-key $PRIVATE_KEY
# Configure L2 bridge to point to L1
cast send $TWOWAY_BRIDGE_L2_CHAIN138 \
"addDestination(uint64,address)" \
1 \ # Mainnet selector
$TWOWAY_BRIDGE_L1_MAINNET \
--rpc-url $RPC_URL_138 \
--private-key $PRIVATE_KEY
🔗 Integration with Existing Contracts
CCIPWETH9Bridge / CCIPWETH10Bridge
The existing CCIP bridges can use MirrorManager to:
- Resolve destination addresses for cross-chain transfers
- Verify address mappings before processing transfers
- Maintain consistency across chains
Example Integration:
// In CCIPWETH9Bridge
MirrorManager mirror = MirrorManager(mirrorManagerAddress);
address destBridge = mirror.getMirror(
block.chainid,
address(this),
destChainSelector
);
📊 Comparison with Kaleido
| Feature | Kaleido Pattern | This Implementation |
|---|---|---|
| State Anchoring | Tether Contract | TwoWayTokenBridge |
| Address Registry | Mirror Contract | MirrorManager |
| Cross-Chain Messaging | Custom | CCIP (Chainlink) |
| Replay Protection | ✅ | ✅ |
| Pausability | ✅ | ✅ |
| Admin Control | ✅ | ✅ |
⚠️ Important Notes
- MirrorManager should be deployed before TwoWayTokenBridge for proper address resolution
- TwoWayTokenBridge requires mintable tokens on L2 (Chain-138)
- Both contracts should use multisig for admin addresses
- Configure MirrorManager mappings after deployment
- Test with small amounts before production use
📚 References
Last Updated: 2025-12-11 Status: Documentation complete, deployment pending