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.
This commit is contained in:
defiQUG
2025-12-12 14:57:48 -08:00
parent a1466e4005
commit 1fb7266469
1720 changed files with 241279 additions and 16 deletions

View File

@@ -0,0 +1,85 @@
#!/usr/bin/env bash
# Deploy all CCIP contracts to Ethereum Mainnet
# This script deploys CCIPLogger which receives Chain-138 transactions
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/../lib/init.sh"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
# Load environment variables
if [ -f "$PROJECT_ROOT/.env" ]; then
source "$PROJECT_ROOT/.env"
else
log_error "Error: .env file not found"
exit 1
fi
log_info "=== Deploying CCIP Contracts to Ethereum Mainnet ==="
# Check prerequisites
if [ -z "$PRIVATE_KEY" ]; then
log_error "Error: PRIVATE_KEY not set in .env"
exit 1
fi
if [ -z "$ETHEREUM_MAINNET_RPC" ]; then
log_warn "Warning: ETHEREUM_MAINNET_RPC not set, using default"
fi
# Configuration
CCIP_ETH_ROUTER="${CCIP_ETH_ROUTER:-0x80226fc0Ee2b096224EeAc085Bb9a8cba1146f7D}"
AUTHORIZED_SIGNER="${AUTHORIZED_SIGNER:-}"
CHAIN138_SELECTOR="${CHAIN138_SELECTOR:-0x000000000000008a}"
echo "Configuration:"
echo " CCIP Router (Ethereum): $CCIP_ETH_ROUTER"
echo " Authorized Signer: ${AUTHORIZED_SIGNER:-Not set (optional)}"
echo " Chain-138 Selector: $CHAIN138_SELECTOR"
# Deploy CCIPLogger
log_warn "Deploying CCIPLogger..."
export CCIP_ETH_ROUTER
export AUTHORIZED_SIGNER
export CHAIN138_SELECTOR
npx hardhat run scripts/ccip-deployment/deploy-ccip-logger.js --network mainnet
CCIP_LOGGER_ADDRESS=$(grep "CCIPLogger deployed to:" <<< "$(npx hardhat run scripts/ccip-deployment/deploy-ccip-logger.js --network mainnet 2>&1)" | awk '{print $NF}')
if [ -z "$CCIP_LOGGER_ADDRESS" ]; then
log_error "Error: Failed to extract CCIPLogger address"
exit 1
fi
log_success "✅ CCIPLogger deployed: $CCIP_LOGGER_ADDRESS"
# Update .env
log_warn "Updating .env file..."
if grep -q "CCIP_LOGGER_ETH_ADDRESS=" "$PROJECT_ROOT/.env"; then
sed -i "s|CCIP_LOGGER_ETH_ADDRESS=.*|CCIP_LOGGER_ETH_ADDRESS=$CCIP_LOGGER_ADDRESS|" "$PROJECT_ROOT/.env"
else
echo "CCIP_LOGGER_ETH_ADDRESS=$CCIP_LOGGER_ADDRESS" >> "$PROJECT_ROOT/.env"
fi
if ! grep -q "CCIP_ETH_ROUTER=" "$PROJECT_ROOT/.env"; then
echo "CCIP_ETH_ROUTER=$CCIP_ETH_ROUTER" >> "$PROJECT_ROOT/.env"
fi
if ! grep -q "CHAIN138_SELECTOR=" "$PROJECT_ROOT/.env"; then
echo "CHAIN138_SELECTOR=$CHAIN138_SELECTOR" >> "$PROJECT_ROOT/.env"
fi
log_success "✅ .env file updated"
log_info "=== Deployment Summary ==="
echo "Deployed Contracts:"
echo " CCIPLogger: $CCIP_LOGGER_ADDRESS"
echo "Next Steps:"
echo " 1. Verify contract on Etherscan"
echo " 2. Deploy CCIPTxReporter to Chain-138"
echo " 3. Configure watcher/relayer service"
echo " 4. Start monitoring"

View File

@@ -0,0 +1,55 @@
const { ethers } = require("hardhat");
require("dotenv").config();
/**
* Deploy CCIPLogger to Ethereum Mainnet
* This contract receives and logs Chain-138 transactions via CCIP
*/
async function main() {
const [deployer] = await ethers.getSigners();
console.log("Deploying CCIPLogger with account:", deployer.address);
console.log("Account balance:", (await ethers.provider.getBalance(deployer.address)).toString());
// Get configuration from environment
const routerAddress = process.env.CCIP_ETH_ROUTER || "0x80226fc0Ee2b096224EeAc085Bb9a8cba1146f7D"; // Official Chainlink CCIP Router on Mainnet
const authorizedSigner = process.env.AUTHORIZED_SIGNER || ethers.ZeroAddress;
const sourceChainSelector = process.env.CHAIN138_SELECTOR || "0x000000000000008a"; // Chain-138 selector (update with actual value from CCIP Directory)
console.log("\nConfiguration:");
console.log(" Router:", routerAddress);
console.log(" Authorized Signer:", authorizedSigner);
console.log(" Source Chain Selector:", sourceChainSelector);
// Deploy CCIPLogger
const CCIPLogger = await ethers.getContractFactory("CCIPLogger");
console.log("\nDeploying CCIPLogger...");
const logger = await CCIPLogger.deploy(
routerAddress,
authorizedSigner,
sourceChainSelector
);
await logger.waitForDeployment();
const loggerAddress = await logger.getAddress();
console.log("\n✅ CCIPLogger deployed to:", loggerAddress);
console.log("\nDeployment details:");
console.log(" Router:", await logger.getRouter());
console.log(" Authorized Signer:", await logger.authorizedSigner());
console.log(" Source Chain Selector:", await logger.expectedSourceChainSelector());
console.log(" Owner:", await logger.owner());
console.log("\n📝 Next steps:");
console.log(" 1. Verify contract on Etherscan:");
console.log(` npx hardhat verify --network mainnet ${loggerAddress} "${routerAddress}" "${authorizedSigner}" "${sourceChainSelector}"`);
console.log(" 2. Update .env with CCIP_LOGGER_ETH_ADDRESS=" + loggerAddress);
console.log(" 3. Deploy CCIPTxReporter to Chain-138 with this address as destination");
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});

View File

@@ -0,0 +1,63 @@
const { ethers } = require("hardhat");
require("dotenv").config();
/**
* Deploy CCIPTxReporter to Chain-138
* This contract reports Chain-138 transactions to Ethereum Mainnet via CCIP
*/
async function main() {
const [deployer] = await ethers.getSigners();
console.log("Deploying CCIPTxReporter with account:", deployer.address);
console.log("Account balance:", (await ethers.provider.getBalance(deployer.address)).toString());
// Get configuration from environment
const routerAddress = process.env.CCIP_CHAIN138_ROUTER || process.env.CCIP_ROUTER || ethers.ZeroAddress;
const destChainSelector = process.env.ETH_MAINNET_SELECTOR || "0x500147"; // Ethereum Mainnet selector (update with actual value from CCIP Directory)
const destReceiver = process.env.CCIP_LOGGER_ETH_ADDRESS || ethers.ZeroAddress;
if (routerAddress === ethers.ZeroAddress) {
throw new Error("CCIP_ROUTER or CCIP_CHAIN138_ROUTER must be set in .env");
}
if (destReceiver === ethers.ZeroAddress) {
throw new Error("CCIP_LOGGER_ETH_ADDRESS must be set in .env (deploy CCIPLogger first)");
}
console.log("\nConfiguration:");
console.log(" Router (Chain-138):", routerAddress);
console.log(" Destination Chain Selector (Ethereum):", destChainSelector);
console.log(" Destination Receiver (CCIPLogger):", destReceiver);
// Deploy CCIPTxReporter
const CCIPTxReporter = await ethers.getContractFactory("CCIPTxReporter");
console.log("\nDeploying CCIPTxReporter...");
const reporter = await CCIPTxReporter.deploy(
routerAddress,
destChainSelector,
destReceiver
);
await reporter.waitForDeployment();
const reporterAddress = await reporter.getAddress();
console.log("\n✅ CCIPTxReporter deployed to:", reporterAddress);
console.log("\nDeployment details:");
console.log(" Router:", await reporter.router());
console.log(" Destination Chain Selector:", await reporter.destChainSelector());
console.log(" Destination Receiver:", await reporter.destReceiver());
console.log(" Owner:", await reporter.owner());
console.log("\n📝 Next steps:");
console.log(" 1. Verify contract on Chain-138 explorer (if available)");
console.log(" 2. Update .env with CCIP_REPORTER_CHAIN138_ADDRESS=" + reporterAddress);
console.log(" 3. Fund the contract with ETH for CCIP fees");
console.log(" 4. Start the watcher/relayer service");
console.log(" 5. Test with a sample transaction report");
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});

View File

@@ -0,0 +1,26 @@
const hre = require("hardhat");
async function main() {
const [deployer] = await hre.ethers.getSigners();
console.log("Deploying CCIPWETH10Bridge to Chain-138 with account:", deployer.address);
const CCIPRouter = process.env.CCIP_CHAIN138_ROUTER || "";
const WETH10 = process.env.WETH10_ADDRESS || "0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f";
const MainnetSelector = process.env.MAINNET_SELECTOR || "5009297550715157269";
if (!CCIPRouter) {
throw new Error("CCIP_CHAIN138_ROUTER environment variable not set");
}
const CCIPWETH10Bridge = await hre.ethers.getContractFactory("CCIPWETH10Bridge");
const bridge = await CCIPWETH10Bridge.deploy(CCIPRouter, WETH10, MainnetSelector);
await bridge.waitForDeployment();
const address = await bridge.getAddress();
console.log("CCIPWETH10Bridge deployed to Chain-138 at:", address);
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});

View File

@@ -0,0 +1,31 @@
const hre = require("hardhat");
async function main() {
const [deployer] = await hre.ethers.getSigners();
console.log("Deploying CCIPWETH10Bridge to Mainnet with account:", deployer.address);
const CCIPRouter = process.env.CCIP_ETH_ROUTER || "0x80226fc0Ee2b096224EeAc085Bb9a8cba1146f7D";
const WETH10 = process.env.WETH10_ADDRESS || "0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f";
const Chain138Selector = process.env.CHAIN138_SELECTOR || "0x000000000000000000000000000000000000008A";
const CCIPWETH10Bridge = await hre.ethers.getContractFactory("CCIPWETH10Bridge");
const bridge = await CCIPWETH10Bridge.deploy(CCIPRouter, WETH10, Chain138Selector);
await bridge.waitForDeployment();
const address = await bridge.getAddress();
console.log("CCIPWETH10Bridge deployed to:", address);
// Verify on Etherscan
if (process.env.ETHERSCAN_API_KEY) {
console.log("Verifying on Etherscan...");
await hre.run("verify:verify", {
address: address,
constructorArguments: [CCIPRouter, WETH10, Chain138Selector],
});
}
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});

View File

@@ -0,0 +1,26 @@
const hre = require("hardhat");
async function main() {
const [deployer] = await hre.ethers.getSigners();
console.log("Deploying CCIPWETH9Bridge to Chain-138 with account:", deployer.address);
const CCIPRouter = process.env.CCIP_CHAIN138_ROUTER || "";
const WETH9 = process.env.WETH9_ADDRESS || "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2";
const MainnetSelector = process.env.MAINNET_SELECTOR || "5009297550715157269";
if (!CCIPRouter) {
throw new Error("CCIP_CHAIN138_ROUTER environment variable not set");
}
const CCIPWETH9Bridge = await hre.ethers.getContractFactory("CCIPWETH9Bridge");
const bridge = await CCIPWETH9Bridge.deploy(CCIPRouter, WETH9, MainnetSelector);
await bridge.waitForDeployment();
const address = await bridge.getAddress();
console.log("CCIPWETH9Bridge deployed to Chain-138 at:", address);
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});

View File

@@ -0,0 +1,31 @@
const hre = require("hardhat");
async function main() {
const [deployer] = await hre.ethers.getSigners();
console.log("Deploying CCIPWETH9Bridge to Mainnet with account:", deployer.address);
const CCIPRouter = process.env.CCIP_ETH_ROUTER || "0x80226fc0Ee2b096224EeAc085Bb9a8cba1146f7D";
const WETH9 = process.env.WETH9_ADDRESS || "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2";
const Chain138Selector = process.env.CHAIN138_SELECTOR || "0x000000000000000000000000000000000000008A";
const CCIPWETH9Bridge = await hre.ethers.getContractFactory("CCIPWETH9Bridge");
const bridge = await CCIPWETH9Bridge.deploy(CCIPRouter, WETH9, Chain138Selector);
await bridge.waitForDeployment();
const address = await bridge.getAddress();
console.log("CCIPWETH9Bridge deployed to:", address);
// Verify on Etherscan
if (process.env.ETHERSCAN_API_KEY) {
console.log("Verifying on Etherscan...");
await hre.run("verify:verify", {
address: address,
constructorArguments: [CCIPRouter, WETH9, Chain138Selector],
});
}
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});