From 1734d889891258735dd61ca3c6dd261d262281da Mon Sep 17 00:00:00 2001 From: defiQUG Date: Tue, 2 Jun 2026 05:59:06 -0700 Subject: [PATCH] Import sibling archive WIP: keeper stack, CCIP scripts, and CCIP docs Co-authored-by: Cursor --- .../reserve/ChainlinkKeeperCompatible.sol | 67 ++ contracts/reserve/GelatoKeeperCompatible.sol | 54 ++ docker/Dockerfile.keeper | 25 + docker/docker-compose.keeper.yml | 54 ++ docs/00-meta/SIBLING_WIP_IMPORT.md | 65 ++ docs/ccip/archive-import/API_REFERENCE.md | 296 +++++++ .../CHAIN_SELECTOR_CALCULATION.md | 202 +++++ .../archive-import/DEPLOYMENT_CHECKLIST.md | 188 ++++ .../DEPLOYMENT_GUIDE_CHAIN138.md | 292 ++++++ .../archive-import/IMPLEMENTATION_SUMMARY.md | 262 ++++++ docs/ccip/archive-import/README.md | 7 + docs/ccip/archive-import/README_KEEPER.md | 247 ++++++ docs/ccip/archive-import/TESTING_GUIDE.md | 194 ++++ .../CCIP_INTEGRATION_GUIDE.md | 319 +++++++ .../docs/AWS_DEPLOYMENT_GUIDE.md | 837 ++++++++++++++++++ .../docs/CCIP_CHAIN138_QUICK_REFERENCE.md | 126 +++ .../docs/CCIP_CHAIN138_REVIEW.md | 347 ++++++++ .../docs/ETH_WETH_CHAINLINK_GUIDE.md | 743 ++++++++++++++++ .../integration/KEEPER_DEPLOYMENT_COMPLETE.md | 211 +++++ .../KEEPER_INTEGRATION_COMPLETE.md | 497 +++++++++++ .../docs/operations/ADMIN_KEY_MANAGEMENT.md | 231 +++++ .../operations/CCIP_MONITORING.md | 252 ++++++ .../operations/CCIP_RUNBOOKS.md | 367 ++++++++ .../archive-import/security/CCIP_SECURITY.md | 256 ++++++ .../user-guides/CCIP_BRIDGE_USER_GUIDE.md | 282 ++++++ script/DeployCCIPLoggerChain138.s.sol | 80 ++ script/DeployGovernanceToken.s.sol | 115 +++ script/DeployUSDC.s.sol | 101 +++ script/DeployUSDT.s.sol | 101 +++ script/helpers/Roles.sol | 14 + script/reserve/DeployChainlinkKeeper.s.sol | 48 + script/reserve/DeployGelatoKeeper.s.sol | 52 ++ scripts/ccip/calculate-chain-selector.sh | 87 ++ scripts/deployment/configure-ccip-router.sh | 95 ++ .../deploy-ccip-chain138-complete.sh | 189 ++++ scripts/deployment/verify-ccip-deployment.sh | 180 ++++ scripts/reserve/chainlink-keeper-setup.js | 141 +++ scripts/reserve/deploy-all.sh | 103 +++ scripts/reserve/gelato-keeper-setup.js | 136 +++ scripts/reserve/monitor-keeper.js | 249 ++++++ systemd/price-feed-keeper.service | 35 + 41 files changed, 8147 insertions(+) create mode 100644 contracts/reserve/ChainlinkKeeperCompatible.sol create mode 100644 contracts/reserve/GelatoKeeperCompatible.sol create mode 100644 docker/Dockerfile.keeper create mode 100644 docker/docker-compose.keeper.yml create mode 100644 docs/00-meta/SIBLING_WIP_IMPORT.md create mode 100644 docs/ccip/archive-import/API_REFERENCE.md create mode 100644 docs/ccip/archive-import/CHAIN_SELECTOR_CALCULATION.md create mode 100644 docs/ccip/archive-import/DEPLOYMENT_CHECKLIST.md create mode 100644 docs/ccip/archive-import/DEPLOYMENT_GUIDE_CHAIN138.md create mode 100644 docs/ccip/archive-import/IMPLEMENTATION_SUMMARY.md create mode 100644 docs/ccip/archive-import/README.md create mode 100644 docs/ccip/archive-import/README_KEEPER.md create mode 100644 docs/ccip/archive-import/TESTING_GUIDE.md create mode 100644 docs/ccip/archive-import/developer-guides/CCIP_INTEGRATION_GUIDE.md create mode 100644 docs/ccip/archive-import/docs/AWS_DEPLOYMENT_GUIDE.md create mode 100644 docs/ccip/archive-import/docs/CCIP_CHAIN138_QUICK_REFERENCE.md create mode 100644 docs/ccip/archive-import/docs/CCIP_CHAIN138_REVIEW.md create mode 100644 docs/ccip/archive-import/docs/ETH_WETH_CHAINLINK_GUIDE.md create mode 100644 docs/ccip/archive-import/docs/integration/KEEPER_DEPLOYMENT_COMPLETE.md create mode 100644 docs/ccip/archive-import/docs/integration/KEEPER_INTEGRATION_COMPLETE.md create mode 100644 docs/ccip/archive-import/docs/operations/ADMIN_KEY_MANAGEMENT.md create mode 100644 docs/ccip/archive-import/operations/CCIP_MONITORING.md create mode 100644 docs/ccip/archive-import/operations/CCIP_RUNBOOKS.md create mode 100644 docs/ccip/archive-import/security/CCIP_SECURITY.md create mode 100644 docs/ccip/archive-import/user-guides/CCIP_BRIDGE_USER_GUIDE.md create mode 100644 script/DeployCCIPLoggerChain138.s.sol create mode 100644 script/DeployGovernanceToken.s.sol create mode 100644 script/DeployUSDC.s.sol create mode 100644 script/DeployUSDT.s.sol create mode 100644 script/helpers/Roles.sol create mode 100644 script/reserve/DeployChainlinkKeeper.s.sol create mode 100644 script/reserve/DeployGelatoKeeper.s.sol create mode 100755 scripts/ccip/calculate-chain-selector.sh create mode 100755 scripts/deployment/configure-ccip-router.sh create mode 100755 scripts/deployment/deploy-ccip-chain138-complete.sh create mode 100755 scripts/deployment/verify-ccip-deployment.sh create mode 100755 scripts/reserve/chainlink-keeper-setup.js create mode 100755 scripts/reserve/deploy-all.sh create mode 100755 scripts/reserve/gelato-keeper-setup.js create mode 100755 scripts/reserve/monitor-keeper.js create mode 100644 systemd/price-feed-keeper.service diff --git a/contracts/reserve/ChainlinkKeeperCompatible.sol b/contracts/reserve/ChainlinkKeeperCompatible.sol new file mode 100644 index 0000000..3b27f3a --- /dev/null +++ b/contracts/reserve/ChainlinkKeeperCompatible.sol @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import "./PriceFeedKeeper.sol"; + +/** + * @title ChainlinkKeeperCompatible + * @notice Chainlink Keepers compatible wrapper for PriceFeedKeeper + * @dev Implements AutomationCompatibleInterface for Chainlink Automation + * + * Note: This interface matches Chainlink's AutomationCompatibleInterface. + * If Chainlink contracts are installed, you can import from: + * chainlink/contracts/src/v0.8/interfaces/AutomationCompatibleInterface.sol + */ +interface AutomationCompatibleInterface { + function checkUpkeep(bytes calldata checkData) external view returns (bool upkeepNeeded, bytes memory performData); + function performUpkeep(bytes calldata performData) external; +} + +contract ChainlinkKeeperCompatible is AutomationCompatibleInterface { + PriceFeedKeeper public immutable keeper; + + constructor(address keeperAddress) { + keeper = PriceFeedKeeper(keeperAddress); + } + + /** + * @notice Chainlink checkUpkeep function + * @param checkData Encoded data (unused for our keeper) + * @return upkeepNeeded True if upkeep is needed + * @return performData Encoded data for performUpkeep + */ + function checkUpkeep(bytes calldata checkData) + external + view + override + returns (bool upkeepNeeded, bytes memory performData) + { + (bool needsUpdate, address[] memory assets) = keeper.checkUpkeep(); + + if (needsUpdate && assets.length > 0) { + upkeepNeeded = true; + performData = abi.encode(assets); + } else { + upkeepNeeded = false; + performData = ""; + } + + // Use checkData if provided (for custom filtering) + if (checkData.length > 0) { + // Custom logic can be added here + } + } + + /** + * @notice Chainlink performUpkeep function + * @param performData Encoded data from checkUpkeep + */ + function performUpkeep(bytes calldata performData) external override { + if (performData.length > 0) { + address[] memory assets = abi.decode(performData, (address[])); + keeper.updateAssets(assets); + } else { + keeper.performUpkeep(); + } + } +} diff --git a/contracts/reserve/GelatoKeeperCompatible.sol b/contracts/reserve/GelatoKeeperCompatible.sol new file mode 100644 index 0000000..aab2118 --- /dev/null +++ b/contracts/reserve/GelatoKeeperCompatible.sol @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import "./PriceFeedKeeper.sol"; + +/** + * @title GelatoKeeperCompatible + * @notice Gelato Network compatible keeper for PriceFeedKeeper + * @dev Implements Gelato's task execution pattern + */ +contract GelatoKeeperCompatible { + PriceFeedKeeper public immutable keeper; + address public immutable gelato; + + event TaskExecuted(address indexed executor, address[] assets, uint256 timestamp); + + constructor(address keeperAddress, address gelato_) { + keeper = PriceFeedKeeper(keeperAddress); + gelato = gelato_; + } + + /** + * @notice Gelato task execution function + * @dev Called by Gelato executors + */ + function executeTask() external { + require(msg.sender == gelato, "GelatoKeeperCompatible: only Gelato"); + + (bool needsUpdate, address[] memory assets) = keeper.checkUpkeep(); + + if (needsUpdate && assets.length > 0) { + keeper.updateAssets(assets); + emit TaskExecuted(msg.sender, assets, block.timestamp); + } + } + + /** + * @notice Check if task can be executed + * @return canExec True if task can be executed + * @return execData Encoded execution data + */ + function canExec() external view returns (bool canExec, bytes memory execData) { + (bool needsUpdate, address[] memory assets) = keeper.checkUpkeep(); + + if (needsUpdate && assets.length > 0) { + canExec = true; + execData = abi.encodeWithSelector(this.executeTask.selector); + } else { + canExec = false; + execData = ""; + } + } +} + diff --git a/docker/Dockerfile.keeper b/docker/Dockerfile.keeper new file mode 100644 index 0000000..6f2fa2b --- /dev/null +++ b/docker/Dockerfile.keeper @@ -0,0 +1,25 @@ +FROM node:18-alpine + +WORKDIR /app + +# Install dependencies +COPY package.json package-lock.json* ./ +RUN npm ci --only=production + +# Copy application files +COPY scripts/reserve/keeper-service.js ./ +COPY scripts/reserve/ ./scripts/reserve/ + +# Create non-root user +RUN addgroup -g 1000 keeper && \ + adduser -D -u 1000 -G keeper keeper && \ + chown -R keeper:keeper /app + +USER keeper + +# Health check endpoint +EXPOSE 3000 + +# Start keeper service +CMD ["node", "scripts/reserve/keeper-service.js"] + diff --git a/docker/docker-compose.keeper.yml b/docker/docker-compose.keeper.yml new file mode 100644 index 0000000..f5655e4 --- /dev/null +++ b/docker/docker-compose.keeper.yml @@ -0,0 +1,54 @@ +version: '3.8' + +services: + keeper: + build: + context: .. + dockerfile: docker/Dockerfile.keeper + container_name: price-feed-keeper + restart: unless-stopped + environment: + - RPC_URL_138=${RPC_URL_138:-https://rpc.d-bis.org} + - KEEPER_PRIVATE_KEY=${KEEPER_PRIVATE_KEY} + - PRICE_FEED_KEEPER_ADDRESS=${PRICE_FEED_KEEPER_ADDRESS} + - UPDATE_INTERVAL=${UPDATE_INTERVAL:-30} + - NODE_ENV=production + volumes: + - ./logs:/app/logs + - ./config:/app/config + networks: + - keeper-network + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + healthcheck: + test: ["CMD", "node", "-e", "require('http').get('http://localhost:3000/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + + monitor: + build: + context: .. + dockerfile: docker/Dockerfile.monitor + container_name: keeper-monitor + restart: unless-stopped + environment: + - RPC_URL_138=${RPC_URL_138:-https://rpc.d-bis.org} + - PRICE_FEED_KEEPER_ADDRESS=${PRICE_FEED_KEEPER_ADDRESS} + - ALERT_WEBHOOK=${ALERT_WEBHOOK} + - CHECK_INTERVAL=${CHECK_INTERVAL:-60} + volumes: + - ./logs:/app/logs + networks: + - keeper-network + depends_on: + - keeper + +networks: + keeper-network: + driver: bridge + diff --git a/docs/00-meta/SIBLING_WIP_IMPORT.md b/docs/00-meta/SIBLING_WIP_IMPORT.md new file mode 100644 index 0000000..4426861 --- /dev/null +++ b/docs/00-meta/SIBLING_WIP_IMPORT.md @@ -0,0 +1,65 @@ +# Sibling WIP archive import + +## Source +- Archive: `/home/intlc/projects/archives/smom-dbis-138-sibling-wip-20260602` +- Date: 2026-06-02 +- Extract: `/tmp/smom-wip-extract/` (from `untracked-files.tar.gz`) +- Patch reference: `/home/intlc/projects/archives/smom-dbis-138-sibling-wip-20260602/git-diff.patch` + +## Files imported (40) +``` +contracts/reserve/ChainlinkKeeperCompatible.sol +contracts/reserve/GelatoKeeperCompatible.sol +docker/Dockerfile.keeper +docker/docker-compose.keeper.yml +docs/ccip/archive-import/API_REFERENCE.md +docs/ccip/archive-import/CHAIN_SELECTOR_CALCULATION.md +docs/ccip/archive-import/DEPLOYMENT_CHECKLIST.md +docs/ccip/archive-import/DEPLOYMENT_GUIDE_CHAIN138.md +docs/ccip/archive-import/IMPLEMENTATION_SUMMARY.md +docs/ccip/archive-import/README.md +docs/ccip/archive-import/README_KEEPER.md +docs/ccip/archive-import/TESTING_GUIDE.md +docs/ccip/archive-import/developer-guides/CCIP_INTEGRATION_GUIDE.md +docs/ccip/archive-import/docs/AWS_DEPLOYMENT_GUIDE.md +docs/ccip/archive-import/docs/CCIP_CHAIN138_QUICK_REFERENCE.md +docs/ccip/archive-import/docs/CCIP_CHAIN138_REVIEW.md +docs/ccip/archive-import/docs/ETH_WETH_CHAINLINK_GUIDE.md +docs/ccip/archive-import/docs/integration/KEEPER_DEPLOYMENT_COMPLETE.md +docs/ccip/archive-import/docs/integration/KEEPER_INTEGRATION_COMPLETE.md +docs/ccip/archive-import/docs/operations/ADMIN_KEY_MANAGEMENT.md +docs/ccip/archive-import/operations/CCIP_MONITORING.md +docs/ccip/archive-import/operations/CCIP_RUNBOOKS.md +docs/ccip/archive-import/security/CCIP_SECURITY.md +docs/ccip/archive-import/user-guides/CCIP_BRIDGE_USER_GUIDE.md +script/DeployCCIPLoggerChain138.s.sol +script/DeployGovernanceToken.s.sol +script/DeployUSDC.s.sol +script/DeployUSDT.s.sol +script/helpers/Roles.sol +script/reserve/DeployChainlinkKeeper.s.sol +script/reserve/DeployGelatoKeeper.s.sol +scripts/ccip/calculate-chain-selector.sh +scripts/deployment/configure-ccip-router.sh +scripts/deployment/deploy-ccip-chain138-complete.sh +scripts/deployment/verify-ccip-deployment.sh +scripts/reserve/chainlink-keeper-setup.js +scripts/reserve/deploy-all.sh +scripts/reserve/gelato-keeper-setup.js +scripts/reserve/monitor-keeper.js +systemd/price-feed-keeper.service +``` + +## Files skipped (policy) +- `contracts/compliance/*`, CompliantUSDC/USDT ? canonical compliance superseded +- `config/*.toml`, `genesis.json`, `static-nodes.json` ? config drift; not merged +- Any path already present in canonical (copy-if-missing only) +- Canonical pre-existing dirty/working-tree changes ? not part of this commit + +## Manual follow-ups +- Review `git-diff.patch` hunks for CCIPSender, reserve contracts, and `package.json` +- Reconcile keeper/reserve wiring with canonical deploy scripts +- Prefer current ops docs: [docs/ccip-integration/](../ccip-integration/) and runbooks + +## Archive docs +Imported CCIP and keeper documentation lives under [docs/ccip/archive-import/](../ccip/archive-import/). diff --git a/docs/ccip/archive-import/API_REFERENCE.md b/docs/ccip/archive-import/API_REFERENCE.md new file mode 100644 index 0000000..6282e9d --- /dev/null +++ b/docs/ccip/archive-import/API_REFERENCE.md @@ -0,0 +1,296 @@ +# CCIP API Reference for ChainID 138 + +**Date**: 2025-01-27 +**Network**: ChainID 138 (DeFi Oracle Meta Mainnet) + +--- + +## Overview + +This document provides API reference for CCIP contracts on ChainID 138. + +--- + +## CCIP Router API + +### Functions + +#### `ccipSend(uint64 destinationChainSelector, EVM2AnyMessage memory message)` + +Send a message to a destination chain. + +**Parameters**: +- `destinationChainSelector`: Chain selector of destination chain +- `message`: CCIP message structure + +**Returns**: +- `bytes32 messageId`: Unique message identifier +- `uint256 fees`: Fees paid for the message + +**Example**: +```solidity +IRouterClient.EVM2AnyMessage memory message = IRouterClient.EVM2AnyMessage({ + receiver: abi.encode(receiverAddress), + data: messageData, + tokenAmounts: new IRouterClient.TokenAmount[](0), + feeToken: address(0), // Native ETH + extraArgs: "" +}); + +(bytes32 messageId, uint256 fees) = router.ccipSend{value: fee}( + destinationSelector, + message +); +``` + +#### `getFee(uint64 destinationChainSelector, EVM2AnyMessage memory message)` + +Calculate fee for sending a message. + +**Parameters**: +- `destinationChainSelector`: Chain selector of destination chain +- `message`: CCIP message structure + +**Returns**: +- `uint256 fee`: Required fee amount + +**Example**: +```solidity +uint256 fee = router.getFee(destinationSelector, message); +``` + +#### `getSupportedTokens(uint64 destinationChainSelector)` + +Get list of supported tokens for a destination chain. + +**Parameters**: +- `destinationChainSelector`: Chain selector + +**Returns**: +- `address[] tokens`: Array of supported token addresses + +#### `addSupportedChain(uint64 chainSelector)` (Admin Only) + +Add a supported destination chain. + +**Parameters**: +- `chainSelector`: Chain selector to add + +#### `removeSupportedChain(uint64 chainSelector)` (Admin Only) + +Remove a supported destination chain. + +#### `addSupportedToken(uint64 chainSelector, address token)` (Admin Only) + +Add a supported token for a chain. + +**Parameters**: +- `chainSelector`: Chain selector +- `token`: Token address + +#### `updateFees(uint256 baseFee, uint256 dataFeePerByte)` (Admin Only) + +Update fee configuration. + +**Parameters**: +- `baseFee`: New base fee +- `dataFeePerByte`: New data fee per byte + +--- + +## CCIPWETH9Bridge API + +### Functions + +#### `sendCrossChain(uint64 destinationChainSelector, address recipient, uint256 amount)` + +Send WETH9 tokens to another chain. + +**Parameters**: +- `destinationChainSelector`: Destination chain selector +- `recipient`: Recipient address on destination chain +- `amount`: Amount of WETH9 to send + +**Returns**: +- `bytes32 messageId`: Message ID for tracking + +**Example**: +```solidity +// Approve first +weth9.approve(address(bridge), amount); + +// Send +bytes32 messageId = bridge.sendCrossChain( + 5009297550715157269, // Ethereum Mainnet + recipientAddress, + amount +); +``` + +#### `ccipReceive(Any2EVMMessage calldata message)` (Router Only) + +Receive WETH9 tokens from another chain. Called by router. + +#### `calculateFee(uint64 destinationChainSelector, uint256 amount)` + +Calculate fee for cross-chain transfer. + +**Parameters**: +- `destinationChainSelector`: Destination chain selector +- `amount`: Transfer amount + +**Returns**: +- `uint256 fee`: Required fee + +#### `addDestination(uint64 chainSelector, address receiverBridge)` (Admin Only) + +Add destination chain configuration. + +#### `removeDestination(uint64 chainSelector)` (Admin Only) + +Remove destination chain. + +#### `updateDestination(uint64 chainSelector, address receiverBridge)` (Admin Only) + +Update destination receiver bridge address. + +#### `getDestinationChains()` + +Get list of configured destination chains. + +**Returns**: +- `uint64[]`: Array of chain selectors + +#### `getUserNonce(address user)` + +Get user's current nonce. + +**Returns**: +- `uint256`: User nonce + +--- + +## CCIPWETH10Bridge API + +Same as CCIPWETH9Bridge, but for WETH10 tokens. + +--- + +## Events + +### Router Events + +```solidity +event MessageSent( + bytes32 indexed messageId, + uint64 indexed destinationChainSelector, + address indexed sender, + bytes receiver, + bytes data, + TokenAmount[] tokenAmounts, + address feeToken, + bytes extraArgs +); + +event MessageReceived( + bytes32 indexed messageId, + uint64 indexed sourceChainSelector, + address indexed sender, + bytes data, + TokenAmount[] tokenAmounts +); +``` + +### Bridge Events + +```solidity +event CrossChainTransferInitiated( + bytes32 indexed messageId, + address indexed sender, + uint64 indexed destinationChainSelector, + address recipient, + uint256 amount, + uint256 nonce +); + +event CrossChainTransferCompleted( + bytes32 indexed messageId, + uint64 indexed sourceChainSelector, + address indexed recipient, + uint256 amount +); + +event DestinationAdded(uint64 chainSelector, address receiverBridge); +event DestinationRemoved(uint64 chainSelector); +event DestinationUpdated(uint64 chainSelector, address receiverBridge); +``` + +--- + +## Data Structures + +### EVM2AnyMessage + +```solidity +struct EVM2AnyMessage { + bytes receiver; // Encoded receiver address + bytes data; // Message data + TokenAmount[] tokenAmounts; // Token amounts to transfer + address feeToken; // Fee token address (0 for native) + bytes extraArgs; // Extra arguments +} +``` + +### Any2EVMMessage + +```solidity +struct Any2EVMMessage { + bytes32 messageId; // Unique message ID + uint64 sourceChainSelector; // Source chain selector + bytes sender; // Encoded sender address + bytes data; // Message data + TokenAmount[] tokenAmounts; // Token amounts received +} +``` + +### TokenAmount + +```solidity +struct TokenAmount { + address token; // Token address + uint256 amount; // Amount + TokenAmountType amountType; // Fiat or Native +} +``` + +--- + +## Error Codes + +### Router Errors + +- `CCIPRouter: chain not supported` +- `CCIPRouter: insufficient native token fee` +- `CCIPRouter: duplicate message` +- `CCIPRouter: empty receiver` + +### Bridge Errors + +- `CCIPWETH9Bridge: destination not enabled` +- `CCIPWETH9Bridge: transfer failed` +- `CCIPWETH9Bridge: transfer already processed` +- `CCIPWETH9Bridge: invalid amount` +- `CCIPWETH9Bridge: zero recipient` + +--- + +## Related Documentation + +- [Developer Integration Guide](../developer-guides/CCIP_INTEGRATION_GUIDE.md) +- [User Guide](../user-guides/CCIP_BRIDGE_USER_GUIDE.md) +- [Deployment Guide](DEPLOYMENT_GUIDE_CHAIN138.md) + +--- + +**Last Updated**: 2025-01-27 + diff --git a/docs/ccip/archive-import/CHAIN_SELECTOR_CALCULATION.md b/docs/ccip/archive-import/CHAIN_SELECTOR_CALCULATION.md new file mode 100644 index 0000000..ecf4355 --- /dev/null +++ b/docs/ccip/archive-import/CHAIN_SELECTOR_CALCULATION.md @@ -0,0 +1,202 @@ +# CCIP Chain Selector Calculation for ChainID 138 + +**Date**: 2025-01-27 +**Chain ID**: 138 +**Network**: DeFi Oracle Meta Mainnet + +--- + +## Overview + +CCIP chain selectors are unique identifiers used to route messages between chains in the Chainlink CCIP network. For ChainID 138, we need to calculate or define a chain selector that is consistent and unique. + +--- + +## Calculation Methods + +### Method 1: Simple ChainID (Recommended for Custom CCIP) + +For custom CCIP router implementations, the simplest approach is to use the chain ID directly as the selector: + +``` +Chain Selector = Chain ID (as uint64) +Chain Selector = 138 +Hex Format: 0x000000000000008a +``` + +**Advantages**: +- Simple and deterministic +- Easy to remember and verify +- Compatible with custom CCIP implementations +- No calculation required + +**Usage**: +```solidity +uint64 chainSelector = 138; // or 0x000000000000008a +``` + +### Method 2: Chainlink Official Format + +If integrating with Chainlink's official CCIP network, chain selectors are calculated using a deterministic hash-based method. The exact formula used by Chainlink is: + +```solidity +uint64(uint256(keccak256(abi.encodePacked(chainId, "CCIP"))) >> 192) +``` + +However, for custom chains not yet registered with Chainlink, you may need to: +1. Register the chain with Chainlink +2. Use Chainlink's assigned selector +3. Or use a custom format for your implementation + +### Method 3: Deterministic Hash-Based + +For a deterministic but more complex selector, you can use: + +```bash +# Using cast (Foundry) +cast keccak "$(printf '0x%064x' 138)CCIP" +# Extract first 8 bytes (uint64) from the hash +``` + +--- + +## Recommended Selector for ChainID 138 + +**Selected Method**: Method 1 (Simple ChainID) + +**Selector Value**: +- **Decimal**: `138` +- **Hex**: `0x000000000000008a` +- **Type**: `uint64` + +**Rationale**: +- Simple and deterministic +- Easy to verify and document +- Compatible with custom CCIP router implementation +- No external dependencies or calculations + +--- + +## Implementation + +### Environment Variable + +```bash +CHAIN138_SELECTOR=0x000000000000008a +# Or simply: +CHAIN138_SELECTOR=138 +``` + +### In Solidity + +```solidity +uint64 constant CHAIN138_SELECTOR = 138; +// Or +uint64 constant CHAIN138_SELECTOR = 0x000000000000008a; +``` + +### In Scripts + +```bash +# Use the calculated selector +CHAIN138_SELECTOR=138 +# Or hex format +CHAIN138_SELECTOR=0x000000000000008a +``` + +--- + +## Usage in CCIP Configuration + +### Router Configuration + +When configuring the CCIP Router to support ChainID 138: + +```solidity +router.addSupportedChain(138); // or 0x000000000000008a +``` + +### Bridge Configuration + +When configuring bridges to send to ChainID 138: + +```solidity +bridge.addDestination(138, receiverBridgeAddress); +``` + +### Message Sending + +When sending CCIP messages to ChainID 138: + +```solidity +router.ccipSend(138, message); +``` + +--- + +## Verification + +To verify the selector is correct: + +1. **Uniqueness**: Ensure no other chain uses selector `138` +2. **Consistency**: Use the same selector across all configurations +3. **Documentation**: Document the selector in all relevant files + +### Verification Script + +Run the calculation script to verify: + +```bash +./scripts/ccip/calculate-chain-selector.sh +``` + +--- + +## Integration with Other Chains + +When configuring bidirectional bridges, ensure: + +1. **ChainID 138 → Ethereum Mainnet**: + - Source selector: `138` + - Destination selector: `5009297550715157269` (Ethereum Mainnet) + +2. **Ethereum Mainnet → ChainID 138**: + - Source selector: `5009297550715157269` + - Destination selector: `138` + +--- + +## Chain Selector Reference Table + +| Network | Chain ID | CCIP Chain Selector | +|---------|----------|---------------------| +| Ethereum Mainnet | 1 | `5009297550715157269` | +| BSC | 56 | `11344663589394136015` | +| Polygon | 137 | `4051577828743386545` | +| Avalanche | 43114 | `6433500567565415381` | +| Base | 8453 | `15971525489660198786` | +| Arbitrum | 42161 | `4949039107694359620` | +| Optimism | 10 | `3734403246176062136` | +| **ChainID 138** | **138** | **`138`** (or `0x000000000000008a`) | + +--- + +## Notes + +- For custom CCIP implementations, you have flexibility in selector format +- The selector must be consistent across all contracts and configurations +- If integrating with Chainlink's official CCIP, you may need to register the chain +- The selector is used in all CCIP message routing and bridge configurations + +--- + +## Related Files + +- `scripts/ccip/calculate-chain-selector.sh` - Calculation script +- `docs/ETH_WETH_CHAINLINK_GUIDE.md` - Main guide with selector reference +- `docs/deployment/ENV_EXAMPLE_CONTENT.md` - Environment variable examples + +--- + +**Last Updated**: 2025-01-27 + diff --git a/docs/ccip/archive-import/DEPLOYMENT_CHECKLIST.md b/docs/ccip/archive-import/DEPLOYMENT_CHECKLIST.md new file mode 100644 index 0000000..16d7fc2 --- /dev/null +++ b/docs/ccip/archive-import/DEPLOYMENT_CHECKLIST.md @@ -0,0 +1,188 @@ +# CCIP ChainID 138 Deployment Checklist + +**Date**: 2025-01-27 +**Network**: ChainID 138 (DeFi Oracle Meta Mainnet) + +--- + +## Pre-Deployment Checklist + +### Environment Setup +- [ ] ChainID 138 network is running and accessible +- [ ] RPC endpoint configured (`RPC_URL_138` or `CHAIN138_RPC_URL`) +- [ ] Private key configured (`PRIVATE_KEY`) +- [ ] Sufficient native token balance for deployment +- [ ] Foundry/Forge installed and working +- [ ] `cast` command available + +### Configuration +- [ ] `.env` file exists and is configured +- [ ] Chain selector calculated (run `./scripts/ccip/calculate-chain-selector.sh`) +- [ ] Fee token decision made (LINK or native ETH) +- [ ] Fee amounts configured (`CCIP_BASE_FEE`, `CCIP_DATA_FEE_PER_BYTE`) + +--- + +## Phase 1: Core Infrastructure + +### Chain Selector +- [ ] Run chain selector calculation script +- [ ] Verify selector value: `138` (or `0x000000000000008a`) +- [ ] Update `.env` with `CHAIN138_SELECTOR` +- [ ] Document selector in all relevant files + +### Fee Token +- [ ] Decide: LINK token or native ETH +- [ ] If LINK: Deploy LINK token contract +- [ ] Update `.env` with `CCIP_CHAIN138_LINK_TOKEN` +- [ ] If native ETH: Set to `address(0)` + +### CCIP Router +- [ ] Deploy CCIPRouter contract +- [ ] Verify deployment on explorer +- [ ] Update `.env` with `CCIP_CHAIN138_ROUTER` +- [ ] Configure router with supported chains +- [ ] Add supported tokens +- [ ] Verify configuration + +--- + +## Phase 2: Bridge Deployment + +### CCIPWETH9Bridge +- [ ] Deploy CCIPWETH9Bridge contract +- [ ] Verify deployment on explorer +- [ ] Update `.env` with `CCIPWETH9_BRIDGE_CHAIN138` +- [ ] Verify bridge configuration (router, WETH9, fee token) + +### CCIPWETH10Bridge +- [ ] Deploy CCIPWETH10Bridge contract +- [ ] Verify deployment on explorer +- [ ] Update `.env` with `CCIPWETH10_BRIDGE_CHAIN138` +- [ ] Verify bridge configuration (router, WETH10, fee token) + +--- + +## Phase 3: Bridge Configuration + +### CCIPWETH9Bridge Destinations +- [ ] Add Ethereum Mainnet as destination on ChainID 138 bridge +- [ ] Add ChainID 138 as destination on Ethereum Mainnet bridge +- [ ] Verify bidirectional configuration +- [ ] Test connectivity + +### CCIPWETH10Bridge Destinations +- [ ] Add Ethereum Mainnet as destination on ChainID 138 bridge +- [ ] Add ChainID 138 as destination on Ethereum Mainnet bridge +- [ ] Verify bidirectional configuration +- [ ] Test connectivity + +--- + +## Phase 4: Verification + +### Contract Verification +- [ ] Verify CCIPRouter on explorer +- [ ] Verify CCIPWETH9Bridge on explorer +- [ ] Verify CCIPWETH10Bridge on explorer +- [ ] Verify LINK token (if deployed) on explorer + +### Configuration Verification +- [ ] Run verification script: `./scripts/deployment/verify-ccip-deployment.sh` +- [ ] Verify router supports Ethereum Mainnet +- [ ] Verify bridges have destinations configured +- [ ] Verify chain selector is correct + +### Functional Testing +- [ ] Test router message sending +- [ ] Test bridge token transfer (WETH9) +- [ ] Test bridge token transfer (WETH10) +- [ ] Test fee payment +- [ ] Test error handling + +--- + +## Phase 5: Documentation + +### Update Documentation +- [ ] Update `docs/ETH_WETH_CHAINLINK_GUIDE.md` with deployed addresses +- [ ] Update `docs/CCIP_CHAIN138_REVIEW.md` with deployment status +- [ ] Update `docs/deployment/ENV_EXAMPLE_CONTENT.md` with actual values +- [ ] Create deployment summary document + +### Create Guides +- [ ] Deployment guide (created) +- [ ] User guide (created) +- [ ] Developer guide (created) +- [ ] Monitoring guide (created) +- [ ] Security guide (created) +- [ ] Runbooks (created) + +--- + +## Phase 6: Operations + +### Monitoring Setup +- [ ] Set up event monitoring +- [ ] Configure alerts +- [ ] Create dashboards +- [ ] Test alerting + +### Security +- [ ] Review security measures +- [ ] Set up admin key management +- [ ] Document security procedures +- [ ] Schedule security audit + +### Operational Procedures +- [ ] Create deployment runbook +- [ ] Create configuration runbook +- [ ] Create troubleshooting guide +- [ ] Create emergency response procedures + +--- + +## Post-Deployment + +### Testing +- [ ] End-to-end cross-chain transfer test +- [ ] Error handling tests +- [ ] Load testing +- [ ] Security testing + +### Monitoring +- [ ] Monitor for 24-48 hours +- [ ] Review all events +- [ ] Check for errors +- [ ] Verify performance + +### Documentation +- [ ] Finalize all documentation +- [ ] Update status in all files +- [ ] Create deployment report +- [ ] Archive deployment artifacts + +--- + +## Success Criteria + +- [ ] All contracts deployed and verified +- [ ] All bridges configured with destinations +- [ ] Cross-chain transfers working bidirectionally +- [ ] All documentation updated +- [ ] Monitoring and alerting operational +- [ ] Security measures in place +- [ ] Operational procedures documented + +--- + +## Related Documentation + +- [Deployment Guide](DEPLOYMENT_GUIDE_CHAIN138.md) +- [Chain Selector Calculation](CHAIN_SELECTOR_CALCULATION.md) +- [CCIP Review](../CCIP_CHAIN138_REVIEW.md) + +--- + +**Last Updated**: 2025-01-27 + diff --git a/docs/ccip/archive-import/DEPLOYMENT_GUIDE_CHAIN138.md b/docs/ccip/archive-import/DEPLOYMENT_GUIDE_CHAIN138.md new file mode 100644 index 0000000..90e0443 --- /dev/null +++ b/docs/ccip/archive-import/DEPLOYMENT_GUIDE_CHAIN138.md @@ -0,0 +1,292 @@ +# CCIP Deployment Guide for ChainID 138 + +**Date**: 2025-01-27 +**Network**: ChainID 138 (DeFi Oracle Meta Mainnet) + +--- + +## Overview + +This guide provides step-by-step instructions for deploying and configuring Chainlink CCIP on ChainID 138. Follow these steps in order to ensure proper configuration. + +--- + +## Prerequisites + +- ChainID 138 network running and accessible +- RPC endpoint configured (`RPC_URL_138` or `CHAIN138_RPC_URL`) +- Private key configured (`PRIVATE_KEY`) +- Sufficient native token balance for deployment +- Foundry/Forge installed +- `cast` command available (from Foundry) + +--- + +## Phase 1: Calculate Chain Selector + +### Step 1.1: Calculate Chain Selector + +Run the chain selector calculation script: + +```bash +./scripts/ccip/calculate-chain-selector.sh +``` + +This will: +- Calculate the recommended chain selector for ChainID 138 +- Update `.env` with `CHAIN138_SELECTOR=0x000000000000008a` (or `138`) + +**Result**: Chain selector is `138` (hex: `0x000000000000008a`) + +--- + +## Phase 2: Deploy CCIP Router + +### Step 2.1: Decide on Fee Token + +Choose one: +- **Option A**: Use native ETH (recommended for simplicity) + - Set `CCIP_CHAIN138_LINK_TOKEN=0x0000000000000000000000000000000000000000` +- **Option B**: Deploy LINK token + - Deploy ERC-20 LINK token contract + - Set `CCIP_CHAIN138_LINK_TOKEN=` + +### Step 2.2: Configure Environment Variables + +Add to `.env`: + +```bash +# CCIP Router Configuration +CCIP_CHAIN138_LINK_TOKEN=0x0000000000000000000000000000000000000000 # Use native ETH +CCIP_BASE_FEE=1000000000000000 # 0.001 ETH (1e15 wei) +CCIP_DATA_FEE_PER_BYTE=100000000 # 0.1 gwei per byte (1e8 wei) +``` + +### Step 2.3: Deploy CCIP Router + +```bash +forge script script/DeployCCIPRouter.s.sol \ + --rpc-url $RPC_URL_138 \ + --broadcast \ + --private-key $PRIVATE_KEY +``` + +### Step 2.4: Update Environment + +After deployment, update `.env`: + +```bash +CCIP_CHAIN138_ROUTER= +``` + +### Step 2.5: Configure Router + +Run the configuration script: + +```bash +./scripts/deployment/configure-ccip-router.sh +``` + +This will: +- Add Ethereum Mainnet as a supported chain +- Add WETH9 and WETH10 as supported tokens + +--- + +## Phase 3: Deploy CCIP Bridges + +### Step 3.1: Deploy CCIPWETH9Bridge + +```bash +# Ensure CCIP_CHAIN138_ROUTER is set in .env +forge script script/DeployCCIPWETH9Bridge.s.sol \ + --rpc-url $RPC_URL_138 \ + --broadcast \ + --private-key $PRIVATE_KEY +``` + +Update `.env`: + +```bash +CCIPWETH9_BRIDGE_CHAIN138= +``` + +### Step 3.2: Deploy CCIPWETH10Bridge + +```bash +forge script script/DeployCCIPWETH10Bridge.s.sol \ + --rpc-url $RPC_URL_138 \ + --broadcast \ + --private-key $PRIVATE_KEY +``` + +Update `.env`: + +```bash +CCIPWETH10_BRIDGE_CHAIN138= +``` + +--- + +## Phase 4: Configure Bridge Destinations + +### Step 4.1: Configure CCIPWETH9Bridge + +Run the configuration script: + +```bash +./scripts/deployment/configure-weth9-bridge.sh +``` + +Or manually: + +```bash +# Add ChainID 138 destination on Ethereum Mainnet bridge +cast send $CCIPWETH9_BRIDGE_MAINNET \ + "addDestination(uint64,address)" \ + 138 \ + $CCIPWETH9_BRIDGE_CHAIN138 \ + --rpc-url $ETHEREUM_MAINNET_RPC \ + --private-key $PRIVATE_KEY + +# Add Ethereum Mainnet destination on ChainID 138 bridge +cast send $CCIPWETH9_BRIDGE_CHAIN138 \ + "addDestination(uint64,address)" \ + 5009297550715157269 \ + $CCIPWETH9_BRIDGE_MAINNET \ + --rpc-url $RPC_URL_138 \ + --private-key $PRIVATE_KEY +``` + +### Step 4.2: Configure CCIPWETH10Bridge + +Run the configuration script: + +```bash +./scripts/deployment/configure-weth10-bridge.sh +``` + +Or manually (similar to WETH9 above). + +--- + +## Phase 5: Verification + +### Step 5.1: Verify Deployment + +Run the verification script: + +```bash +./scripts/deployment/verify-ccip-deployment.sh +``` + +This will check: +- All contracts are deployed +- Router configuration +- Bridge configuration +- Chain selector + +### Step 5.2: Manual Verification + +Verify each contract on the explorer: + +```bash +# Check router +cast code $CCIP_CHAIN138_ROUTER --rpc-url $RPC_URL_138 + +# Check bridges +cast code $CCIPWETH9_BRIDGE_CHAIN138 --rpc-url $RPC_URL_138 +cast code $CCIPWETH10_BRIDGE_CHAIN138 --rpc-url $RPC_URL_138 +``` + +--- + +## Phase 6: Testing + +### Step 6.1: Test Router Message Sending + +```solidity +// Test sending a message via router +router.ccipSend( + 5009297550715157269, // Ethereum Mainnet selector + message +); +``` + +### Step 6.2: Test Bridge Token Transfer + +```bash +# Test WETH9 bridge transfer +# 1. Approve bridge to spend WETH9 +# 2. Call sendCrossChain() +# 3. Verify on destination chain +``` + +--- + +## Environment Variables Summary + +After complete deployment, your `.env` should include: + +```bash +# ChainID 138 CCIP Configuration +CHAIN138_SELECTOR=0x000000000000008a +CCIP_CHAIN138_ROUTER= +CCIP_CHAIN138_LINK_TOKEN=0x0000000000000000000000000000000000000000 # or LINK address +CCIPWETH9_BRIDGE_CHAIN138= +CCIPWETH10_BRIDGE_CHAIN138= + +# Router Configuration +CCIP_BASE_FEE=1000000000000000 +CCIP_DATA_FEE_PER_BYTE=100000000 +``` + +--- + +## Troubleshooting + +### Issue: Router deployment fails + +**Solution**: +- Check RPC connectivity +- Verify sufficient balance +- Check gas price settings + +### Issue: Bridge deployment fails + +**Solution**: +- Ensure router is deployed first +- Verify router address in environment +- Check WETH addresses match genesis + +### Issue: Configuration fails + +**Solution**: +- Verify contract addresses +- Check chain selectors are correct +- Ensure admin key has permissions + +--- + +## Next Steps + +After deployment: + +1. **Update Documentation**: Update all docs with deployed addresses +2. **Contract Verification**: Verify contracts on explorer +3. **Testing**: Run comprehensive tests +4. **Monitoring**: Set up monitoring and alerting +5. **Security**: Review security measures + +--- + +## Related Documentation + +- [Chain Selector Calculation](CHAIN_SELECTOR_CALCULATION.md) +- [CCIP Review](../CCIP_CHAIN138_REVIEW.md) +- [Main Guide](../ETH_WETH_CHAINLINK_GUIDE.md) + +--- + +**Last Updated**: 2025-01-27 + diff --git a/docs/ccip/archive-import/IMPLEMENTATION_SUMMARY.md b/docs/ccip/archive-import/IMPLEMENTATION_SUMMARY.md new file mode 100644 index 0000000..870966f --- /dev/null +++ b/docs/ccip/archive-import/IMPLEMENTATION_SUMMARY.md @@ -0,0 +1,262 @@ +# CCIP ChainID 138 Implementation Summary + +**Date**: 2025-01-27 +**Status**: ✅ **IMPLEMENTATION COMPLETE** - Ready for Deployment + +--- + +## Overview + +All required infrastructure, scripts, and documentation have been implemented for fully enabling Chainlink CCIP on ChainID 138. The implementation includes deployment scripts, configuration tools, verification scripts, and comprehensive documentation. + +--- + +## Implementation Status + +### ✅ Phase 1: Core Infrastructure Setup + +#### 1.1 Chain Selector Calculation +- ✅ Calculation script created: `scripts/ccip/calculate-chain-selector.sh` +- ✅ Documentation created: `docs/ccip/CHAIN_SELECTOR_CALCULATION.md` +- ✅ Selector value: `138` (decimal) or `0x000000000000008a` (hex) +- ✅ All scripts updated with correct selector + +#### 1.2 Fee Token Decision +- ✅ Documentation updated with options (LINK or native ETH) +- ✅ Deployment scripts support both options +- ✅ Environment variables configured + +#### 1.3 CCIP Router Deployment +- ✅ Deployment script updated: `script/DeployCCIPRouter.s.sol` +- ✅ Supports ChainID 138 specific environment variables +- ✅ Includes helpful deployment output +- ✅ Configuration script created: `scripts/deployment/configure-ccip-router.sh` + +#### 1.4 Router Configuration +- ✅ Configuration script created +- ✅ Supports adding destination chains +- ✅ Supports adding supported tokens +- ✅ Includes verification steps + +### ✅ Phase 2: Bridge Deployment + +#### 2.1 CCIPWETH9Bridge Deployment +- ✅ Deployment script updated: `script/DeployCCIPWETH9Bridge.s.sol` +- ✅ Uses ChainID 138 specific environment variables +- ✅ Includes deployment verification + +#### 2.2 CCIPWETH10Bridge Deployment +- ✅ Deployment script updated: `script/DeployCCIPWETH10Bridge.s.sol` +- ✅ Uses ChainID 138 specific environment variables +- ✅ Includes deployment verification + +### ✅ Phase 3: Bridge Configuration + +#### 3.1 Bridge Configuration Scripts +- ✅ `scripts/deployment/configure-weth9-bridge.sh` - Updated with correct selectors +- ✅ `scripts/deployment/configure-weth10-bridge.sh` - Updated with correct selectors +- ✅ `scripts/deployment/execute-bridge-config.sh` - Updated with correct selectors +- ✅ `scripts/deployment/configure-bridge-destinations.sh` - Updated with correct selectors + +### ✅ Phase 4: Environment & Documentation + +#### 4.1 Environment Variables +- ✅ `docs/deployment/ENV_EXAMPLE_CONTENT.md` - Updated with ChainID 138 placeholders +- ✅ All required variables documented +- ✅ Fee configuration variables added + +#### 4.2 Documentation +- ✅ `docs/ETH_WETH_CHAINLINK_GUIDE.md` - Updated with chain selector +- ✅ `docs/CCIP_CHAIN138_REVIEW.md` - Updated with selector status +- ✅ `docs/ccip/CHAIN_SELECTOR_CALCULATION.md` - Complete calculation guide +- ✅ `docs/ccip/DEPLOYMENT_GUIDE_CHAIN138.md` - Complete deployment guide +- ✅ `docs/ccip/DEPLOYMENT_CHECKLIST.md` - Deployment checklist + +### ✅ Phase 5: Testing & Verification + +#### 5.1 Verification Scripts +- ✅ `scripts/deployment/verify-ccip-deployment.sh` - Complete verification script +- ✅ Checks contract deployment +- ✅ Verifies configuration +- ✅ Generates status report + +#### 5.2 Testing Documentation +- ✅ Testing procedures documented +- ✅ Integration test examples provided +- ✅ Error handling documented + +### ✅ Phase 6: Security & Operations + +#### 6.1 Security Documentation +- ✅ `docs/security/CCIP_SECURITY.md` - Complete security guide +- ✅ Security best practices documented +- ✅ Audit checklist provided +- ✅ Incident response procedures + +#### 6.2 Operational Documentation +- ✅ `docs/operations/CCIP_MONITORING.md` - Monitoring guide +- ✅ `docs/operations/CCIP_RUNBOOKS.md` - Operational runbooks +- ✅ `docs/operations/ADMIN_KEY_MANAGEMENT.md` - Key management guide + +### ✅ Phase 7: Advanced Features + +#### 7.1 User Documentation +- ✅ `docs/user-guides/CCIP_BRIDGE_USER_GUIDE.md` - User guide +- ✅ Step-by-step instructions +- ✅ Code examples +- ✅ Troubleshooting guide + +#### 7.2 Developer Documentation +- ✅ `docs/developer-guides/CCIP_INTEGRATION_GUIDE.md` - Developer guide +- ✅ Integration patterns +- ✅ Code examples +- ✅ Best practices + +--- + +## Created Files + +### Scripts +1. `scripts/ccip/calculate-chain-selector.sh` - Chain selector calculation +2. `scripts/deployment/configure-ccip-router.sh` - Router configuration +3. `scripts/deployment/verify-ccip-deployment.sh` - Deployment verification +4. `scripts/deployment/deploy-ccip-chain138-complete.sh` - Complete deployment script + +### Documentation +1. `docs/ccip/CHAIN_SELECTOR_CALCULATION.md` - Chain selector guide +2. `docs/ccip/DEPLOYMENT_GUIDE_CHAIN138.md` - Deployment guide +3. `docs/ccip/DEPLOYMENT_CHECKLIST.md` - Deployment checklist +4. `docs/ccip/IMPLEMENTATION_SUMMARY.md` - This file +5. `docs/operations/CCIP_MONITORING.md` - Monitoring guide +6. `docs/operations/CCIP_RUNBOOKS.md` - Operational runbooks +7. `docs/operations/ADMIN_KEY_MANAGEMENT.md` - Key management +8. `docs/security/CCIP_SECURITY.md` - Security guide +9. `docs/user-guides/CCIP_BRIDGE_USER_GUIDE.md` - User guide +10. `docs/developer-guides/CCIP_INTEGRATION_GUIDE.md` - Developer guide + +### Updated Files +1. `script/DeployCCIPRouter.s.sol` - Enhanced for ChainID 138 +2. `script/DeployCCIPWETH9Bridge.s.sol` - Enhanced for ChainID 138 +3. `script/DeployCCIPWETH10Bridge.s.sol` - Enhanced for ChainID 138 +4. `scripts/deployment/configure-weth9-bridge.sh` - Updated selectors +5. `scripts/deployment/configure-weth10-bridge.sh` - Updated selectors +6. `scripts/deployment/execute-bridge-config.sh` - Updated selectors +7. `scripts/deployment/configure-bridge-destinations.sh` - Updated selectors +8. `docs/ETH_WETH_CHAINLINK_GUIDE.md` - Updated chain selector +9. `docs/CCIP_CHAIN138_REVIEW.md` - Updated selector status +10. `docs/deployment/ENV_EXAMPLE_CONTENT.md` - Updated with ChainID 138 config + +--- + +## Deployment Readiness + +### Ready for Deployment +- ✅ All deployment scripts ready +- ✅ All configuration scripts ready +- ✅ All verification scripts ready +- ✅ All documentation complete +- ✅ Environment variables documented +- ✅ Chain selector calculated + +### Pending Deployment +- ⏳ CCIP Router deployment (requires network access) +- ⏳ LINK token deployment (optional - can use native ETH) +- ⏳ CCIPWETH9Bridge deployment +- ⏳ CCIPWETH10Bridge deployment +- ⏳ Bridge destination configuration +- ⏳ Contract verification on explorer + +--- + +## Quick Start + +### Complete Deployment + +Run the complete deployment script: + +```bash +./scripts/deployment/deploy-ccip-chain138-complete.sh +``` + +This will: +1. Calculate chain selector +2. Deploy CCIP Router +3. Configure router +4. Deploy CCIPWETH9Bridge +5. Deploy CCIPWETH10Bridge +6. Verify deployment + +### Manual Deployment + +Follow the step-by-step guide: + +```bash +# 1. Calculate selector +./scripts/ccip/calculate-chain-selector.sh + +# 2. Deploy router +forge script script/DeployCCIPRouter.s.sol --rpc-url $RPC_URL_138 --broadcast --private-key $PRIVATE_KEY + +# 3. Configure router +./scripts/deployment/configure-ccip-router.sh + +# 4. Deploy bridges +forge script script/DeployCCIPWETH9Bridge.s.sol --rpc-url $RPC_URL_138 --broadcast --private-key $PRIVATE_KEY +forge script script/DeployCCIPWETH10Bridge.s.sol --rpc-url $RPC_URL_138 --broadcast --private-key $PRIVATE_KEY + +# 5. Configure bridges +./scripts/deployment/configure-weth9-bridge.sh +./scripts/deployment/configure-weth10-bridge.sh + +# 6. Verify +./scripts/deployment/verify-ccip-deployment.sh +``` + +--- + +## Documentation Index + +### Core Documentation +- [CCIP Review](../CCIP_CHAIN138_REVIEW.md) - Complete enablement review +- [Chain Selector Calculation](CHAIN_SELECTOR_CALCULATION.md) - Selector calculation guide +- [Deployment Guide](DEPLOYMENT_GUIDE_CHAIN138.md) - Step-by-step deployment +- [Deployment Checklist](DEPLOYMENT_CHECKLIST.md) - Deployment checklist + +### User Guides +- [Bridge User Guide](../user-guides/CCIP_BRIDGE_USER_GUIDE.md) - How to use bridges + +### Developer Guides +- [Integration Guide](../developer-guides/CCIP_INTEGRATION_GUIDE.md) - Developer integration + +### Operations +- [Monitoring Guide](../operations/CCIP_MONITORING.md) - Monitoring setup +- [Runbooks](../operations/CCIP_RUNBOOKS.md) - Operational procedures +- [Key Management](../operations/ADMIN_KEY_MANAGEMENT.md) - Admin key management + +### Security +- [Security Guide](../security/CCIP_SECURITY.md) - Security best practices + +--- + +## Next Steps + +1. **Deploy Infrastructure**: Run deployment scripts when network is ready +2. **Configure Bridges**: Set up destination chains +3. **Verify Contracts**: Verify on explorer +4. **Test Functionality**: Test cross-chain transfers +5. **Monitor Operations**: Set up monitoring and alerting + +--- + +## Success Criteria + +All implementation tasks are complete. The project is ready for deployment when: +- Network is accessible +- Deployment keys are configured +- Sufficient balance is available + +--- + +**Last Updated**: 2025-01-27 +**Implementation Status**: ✅ **COMPLETE** + diff --git a/docs/ccip/archive-import/README.md b/docs/ccip/archive-import/README.md new file mode 100644 index 0000000..91b1263 --- /dev/null +++ b/docs/ccip/archive-import/README.md @@ -0,0 +1,7 @@ +# CCIP archive-import index + +Historical CCIP and keeper documentation imported from the sibling WIP archive (2026-06-02). + +**Current operations:** use canonical [docs/ccip-integration/](../../ccip-integration/) and repository runbooks matching `runbooks/ccip-*` for live procedures. + +This folder is read-only reference from the archive; do not treat it as the source of truth over `ccip-integration`. diff --git a/docs/ccip/archive-import/README_KEEPER.md b/docs/ccip/archive-import/README_KEEPER.md new file mode 100644 index 0000000..5265569 --- /dev/null +++ b/docs/ccip/archive-import/README_KEEPER.md @@ -0,0 +1,247 @@ +# Price Feed Keeper - Complete Integration Guide + +**Status**: ✅ **ALL INTEGRATION OPTIONS COMPLETE** + +This document provides a quick reference for all keeper integration options. + +--- + +## Quick Start + +### Option 1: Standalone Service (Simplest) + +```bash +# Deploy keeper +forge script script/reserve/DeployKeeper.s.sol:DeployKeeper --rpc-url chain138 --broadcast + +# Start service +export KEEPER_PRIVATE_KEY= +export PRICE_FEED_KEEPER_ADDRESS=
+node scripts/reserve/keeper-service.js +``` + +### Option 2: Complete Deployment (All Options) + +```bash +# Install Node.js dependencies +npm install + +# Deploy everything +./scripts/reserve/deploy-all.sh +``` + +--- + +## Integration Options + +### 1. Standalone Service ✅ + +**Best for**: Development, testing, simple deployments + +- Node.js service: `scripts/reserve/keeper-service.js` +- Bash service: `scripts/reserve/keeper-service.sh` + +**Setup**: See [KEEPER_SETUP.md](./docs/integration/KEEPER_SETUP.md) + +--- + +### 2. Chainlink Keepers ✅ + +**Best for**: Decentralized, reliable automation + +- Contract: `ChainlinkKeeperCompatible.sol` +- Setup: `scripts/reserve/chainlink-keeper-setup.js` + +**Requirements**: +- Chainlink KeeperRegistry address +- LINK token for funding +- Gas limit configuration + +**Setup**: +```bash +# Deploy compatible contract +forge script script/reserve/DeployChainlinkKeeper.s.sol:DeployChainlinkKeeper --rpc-url chain138 --broadcast + +# Register upkeep +export LINK_TOKEN_ADDRESS= +export KEEPER_REGISTRY_ADDRESS= +node scripts/reserve/chainlink-keeper-setup.js +``` + +--- + +### 3. Gelato Network ✅ + +**Best for**: Cost-effective automation + +- Contract: `GelatoKeeperCompatible.sol` +- Setup: `scripts/reserve/gelato-keeper-setup.js` + +**Requirements**: +- Gelato Ops address +- Native token for funding + +**Setup**: +```bash +# Deploy compatible contract +forge script script/reserve/DeployGelatoKeeper.s.sol:DeployGelatoKeeper --rpc-url chain138 --broadcast + +# Create task +export GELATO_OPS= +node scripts/reserve/gelato-keeper-setup.js +``` + +--- + +### 4. Systemd Service ✅ + +**Best for**: Production Linux servers + +- Service file: `systemd/price-feed-keeper.service` + +**Setup**: +```bash +sudo cp systemd/price-feed-keeper.service /etc/systemd/system/ +sudo systemctl enable price-feed-keeper +sudo systemctl start price-feed-keeper +``` + +--- + +### 5. Docker Container ✅ + +**Best for**: Containerized deployments + +- Compose file: `docker/docker-compose.keeper.yml` +- Dockerfile: `docker/Dockerfile.keeper` + +**Setup**: +```bash +docker-compose -f docker/docker-compose.keeper.yml up -d +``` + +--- + +## Monitoring + +### Start Monitor Service + +```bash +export PRICE_FEED_KEEPER_ADDRESS=
+export ALERT_WEBHOOK= # Optional +node scripts/reserve/monitor-keeper.js +``` + +### Health Checks + +```bash +curl http://localhost:3000/health +curl http://localhost:3000/stats +``` + +--- + +## Configuration + +### Required Environment Variables + +```bash +export RPC_URL_138=https://rpc.d-bis.org +export PRIVATE_KEY= +export PRICE_FEED_KEEPER_ADDRESS= +export KEEPER_PRIVATE_KEY= +export UPDATE_INTERVAL=30 +``` + +### Optional Variables + +```bash +# Chainlink +export LINK_TOKEN_ADDRESS= +export KEEPER_REGISTRY_ADDRESS= +export UPKEEP_INTERVAL=30 +export GAS_LIMIT=500000 +export FUNDING_AMOUNT=10 + +# Gelato +export GELATO_OPS= +export EXECUTION_INTERVAL=30 +export FUNDING_AMOUNT=0.1 + +# Monitoring +export ALERT_WEBHOOK= +export CHECK_INTERVAL=60 +export ALERT_THRESHOLD=3 +``` + +--- + +## File Structure + +``` +contracts/reserve/ +├── PriceFeedKeeper.sol # Core keeper +├── ChainlinkKeeperCompatible.sol # Chainlink wrapper +└── GelatoKeeperCompatible.sol # Gelato wrapper + +script/reserve/ +├── DeployKeeper.s.sol # Deploy keeper +├── DeployChainlinkKeeper.s.sol # Deploy Chainlink wrapper +├── DeployGelatoKeeper.s.sol # Deploy Gelato wrapper +├── PerformUpkeep.s.sol # Manual upkeep +└── CheckUpkeep.s.sol # Check status + +scripts/reserve/ +├── keeper-service.js # Node.js service +├── keeper-service.sh # Bash service +├── chainlink-keeper-setup.js # Chainlink setup +├── gelato-keeper-setup.js # Gelato setup +├── monitor-keeper.js # Monitoring +└── deploy-all.sh # Deployment automation + +systemd/ +└── price-feed-keeper.service # Systemd service + +docker/ +├── docker-compose.keeper.yml # Docker Compose +└── Dockerfile.keeper # Docker image + +docs/integration/ +├── KEEPER_SETUP.md # Setup guide +├── KEEPER_COMPLETE.md # Completion summary +└── KEEPER_INTEGRATION_COMPLETE.md # Full integration guide +``` + +--- + +## Documentation + +- **[KEEPER_SETUP.md](./docs/integration/KEEPER_SETUP.md)** - Detailed setup guide +- **[KEEPER_INTEGRATION_COMPLETE.md](./docs/integration/KEEPER_INTEGRATION_COMPLETE.md)** - Complete integration guide +- **[KEEPER_COMPLETE.md](./docs/integration/KEEPER_COMPLETE.md)** - Completion summary + +--- + +## Support + +For issues or questions: +1. Check [KEEPER_SETUP.md](./docs/integration/KEEPER_SETUP.md) troubleshooting section +2. Review [KEEPER_INTEGRATION_COMPLETE.md](./docs/integration/KEEPER_INTEGRATION_COMPLETE.md) +3. Check keeper logs: `journalctl -u price-feed-keeper -f` + +--- + +## Status + +✅ **ALL INTEGRATION OPTIONS COMPLETE** + +- ✅ Standalone Service +- ✅ Chainlink Keepers +- ✅ Gelato Network +- ✅ Systemd Service +- ✅ Docker Container +- ✅ Monitoring & Alerting +- ✅ Deployment Automation + +**Ready for production deployment on ChainID 138** + diff --git a/docs/ccip/archive-import/TESTING_GUIDE.md b/docs/ccip/archive-import/TESTING_GUIDE.md new file mode 100644 index 0000000..3018bbe --- /dev/null +++ b/docs/ccip/archive-import/TESTING_GUIDE.md @@ -0,0 +1,194 @@ +# CCIP Testing Guide for ChainID 138 + +**Date**: 2025-01-27 +**Network**: ChainID 138 (DeFi Oracle Meta Mainnet) + +--- + +## Overview + +This guide provides testing procedures and examples for CCIP infrastructure on ChainID 138. + +--- + +## Test Categories + +### 1. Unit Tests + +Test individual contract functions in isolation. + +**Files**: +- `test/CCIPWETH9Bridge.t.sol` +- `test/CCIPWETH10Bridge.t.sol` +- `test/ccip/CCIPIntegration.t.sol` +- `test/ccip/CCIPErrorHandling.t.sol` +- `test/ccip/CCIPFees.t.sol` + +### 2. Integration Tests + +Test end-to-end cross-chain flows. + +**Files**: +- `test/ccip/CCIPIntegration.t.sol` + +### 3. Functional Tests + +Test real-world usage scenarios. + +--- + +## Running Tests + +### Run All CCIP Tests + +```bash +forge test --match-path "test/ccip/**" -vvv +forge test --match-path "test/CCIP*.t.sol" -vvv +``` + +### Run Specific Test File + +```bash +forge test --match-path "test/CCIPWETH9Bridge.t.sol" -vvv +``` + +### Run Specific Test Function + +```bash +forge test --match-test "testSendCrossChain" -vvv +``` + +--- + +## Test Scenarios + +### Router Tests + +```solidity +function testRouterMessageSending() public { + // Test sending message via router + IRouterClient.EVM2AnyMessage memory message = ...; + (bytes32 messageId, uint256 fee) = router.ccipSend(destinationSelector, message); + assertTrue(messageId != bytes32(0)); +} + +function testRouterFeeCalculation() public { + // Test fee calculation + uint256 fee = router.getFee(destinationSelector, message); + assertTrue(fee > 0); +} +``` + +### Bridge Tests + +```solidity +function testBridgeTransfer() public { + // Approve bridge + weth9.approve(address(bridge), amount); + + // Send cross-chain + bytes32 messageId = bridge.sendCrossChain(destinationSelector, recipient, amount); + + // Verify + assertTrue(messageId != bytes32(0)); +} + +function testBridgeFeeCalculation() public { + uint256 fee = bridge.calculateFee(destinationSelector, amount); + assertTrue(fee > 0); +} +``` + +### Integration Tests + +```solidity +function testEndToEndTransfer() public { + // 1. Lock tokens on source chain + // 2. Send cross-chain message + // 3. Verify unlock on destination chain + // 4. Verify balances +} +``` + +--- + +## Test Data + +### Test Addresses + +```solidity +address constant TEST_USER = address(0x1111); +address constant TEST_RECIPIENT = address(0x2222); +address constant TEST_ADMIN = address(0x3333); +``` + +### Test Amounts + +```solidity +uint256 constant TEST_AMOUNT = 1 ether; +uint256 constant TEST_FEE = 0.001 ether; +``` + +### Test Chain Selectors + +```solidity +uint64 constant CHAIN138_SELECTOR = 138; +uint64 constant ETH_MAINNET_SELECTOR = 5009297550715157269; +``` + +--- + +## Mock Contracts + +For testing without actual cross-chain connectivity: + +```solidity +contract MockRouter is IRouterClient { + function ccipSend(...) external payable returns (bytes32, uint256) { + // Mock implementation + } + + function getFee(...) external view returns (uint256) { + // Mock fee calculation + } +} +``` + +--- + +## Test Coverage Goals + +- **Unit Tests**: >90% coverage +- **Integration Tests**: All critical paths +- **Error Handling**: All error cases +- **Edge Cases**: Boundary conditions + +--- + +## Continuous Integration + +### GitHub Actions Example + +```yaml +name: CCIP Tests +on: [push, pull_request] +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: foundry-actions/setup-foundry@v1 + - run: forge test --match-path "test/ccip/**" +``` + +--- + +## Related Documentation + +- [Deployment Guide](DEPLOYMENT_GUIDE_CHAIN138.md) +- [Developer Integration Guide](../developer-guides/CCIP_INTEGRATION_GUIDE.md) + +--- + +**Last Updated**: 2025-01-27 + diff --git a/docs/ccip/archive-import/developer-guides/CCIP_INTEGRATION_GUIDE.md b/docs/ccip/archive-import/developer-guides/CCIP_INTEGRATION_GUIDE.md new file mode 100644 index 0000000..1e5a687 --- /dev/null +++ b/docs/ccip/archive-import/developer-guides/CCIP_INTEGRATION_GUIDE.md @@ -0,0 +1,319 @@ +# CCIP Integration Guide for Developers + +**Date**: 2025-01-27 +**Network**: ChainID 138 (DeFi Oracle Meta Mainnet) + +--- + +## Overview + +This guide provides technical details for developers integrating with CCIP infrastructure on ChainID 138. + +--- + +## Architecture + +### Components + +1. **CCIP Router**: Routes messages between chains +2. **CCIP Bridges**: Handle token transfers +3. **CCIP Sender/Receiver**: Handle oracle data transmission + +### Message Flow + +``` +Source Chain → CCIP Router → Destination Chain → CCIP Router → Receiver +``` + +--- + +## Integration Patterns + +### Pattern 1: Token Bridge Integration + +```solidity +// Import bridge interface +import "./IC CIPWETH9Bridge.sol"; + +contract MyContract { + CCIPWETH9Bridge public bridge; + + function transferCrossChain( + uint64 destinationSelector, + address recipient, + uint256 amount + ) external { + // Approve bridge + weth9.approve(address(bridge), amount); + + // Send cross-chain + bytes32 messageId = bridge.sendCrossChain( + destinationSelector, + recipient, + amount + ); + + emit TransferInitiated(messageId, destinationSelector, amount); + } +} +``` + +### Pattern 2: Oracle Data Integration + +```solidity +import "./CCIPSender.sol"; +import "./CCIPReceiver.sol"; + +contract MyOracleContract { + CCIPSender public sender; + CCIPReceiver public receiver; + + function sendOracleUpdate( + uint64 destinationSelector, + uint256 answer, + uint256 roundId, + uint256 timestamp + ) external payable { + bytes32 messageId = sender.sendOracleUpdate{value: msg.value}( + destinationSelector, + answer, + roundId, + timestamp + ); + } + + function ccipReceive( + IRouterClient.Any2EVMMessage calldata message + ) external { + // Process received oracle data + (uint256 answer, uint256 roundId, uint256 timestamp) = + abi.decode(message.data, (uint256, uint256, uint256)); + + // Update oracle + updateOracle(answer, roundId, timestamp); + } +} +``` + +### Pattern 3: Custom Message Sending + +```solidity +import "./IRouterClient.sol"; + +contract MyCustomContract { + IRouterClient public router; + + function sendCustomMessage( + uint64 destinationSelector, + address receiver, + bytes memory data + ) external payable { + IRouterClient.EVM2AnyMessage memory message = IRouterClient.EVM2AnyMessage({ + receiver: abi.encode(receiver), + data: data, + tokenAmounts: new IRouterClient.TokenAmount[](0), + feeToken: address(0), // Native ETH + extraArgs: "" + }); + + uint256 fee = router.getFee(destinationSelector, message); + + (bytes32 messageId, ) = router.ccipSend{value: fee}( + destinationSelector, + message + ); + + emit MessageSent(messageId, destinationSelector); + } +} +``` + +--- + +## Interfaces + +### IRouterClient + +```solidity +interface IRouterClient { + function ccipSend( + uint64 destinationChainSelector, + EVM2AnyMessage memory message + ) external payable returns (bytes32 messageId, uint256 fees); + + function getFee( + uint64 destinationChainSelector, + EVM2AnyMessage memory message + ) external view returns (uint256 fee); +} +``` + +### CCIPWETH9Bridge / CCIPWETH10Bridge + +```solidity +interface ICCIPBridge { + function sendCrossChain( + uint64 destinationChainSelector, + address recipient, + uint256 amount + ) external returns (bytes32 messageId); + + function calculateFee( + uint64 destinationChainSelector, + uint256 amount + ) external view returns (uint256 fee); + + function ccipReceive( + IRouterClient.Any2EVMMessage calldata message + ) external; +} +``` + +--- + +## Event Monitoring + +### Router Events + +```solidity +event MessageSent( + bytes32 indexed messageId, + uint64 indexed destinationChainSelector, + address indexed sender, + bytes receiver, + bytes data, + TokenAmount[] tokenAmounts, + address feeToken, + bytes extraArgs +); + +event MessageReceived( + bytes32 indexed messageId, + uint64 indexed sourceChainSelector, + address indexed sender, + bytes data, + TokenAmount[] tokenAmounts +); +``` + +### Bridge Events + +```solidity +event CrossChainTransferInitiated( + bytes32 indexed messageId, + address indexed sender, + uint64 indexed destinationChainSelector, + address recipient, + uint256 amount, + uint256 nonce +); + +event CrossChainTransferCompleted( + bytes32 indexed messageId, + uint64 indexed sourceChainSelector, + address indexed recipient, + uint256 amount +); +``` + +--- + +## Error Handling + +### Common Errors + +```solidity +// Router errors +"CCIPRouter: chain not supported" +"CCIPRouter: insufficient native token fee" +"CCIPRouter: duplicate message" + +// Bridge errors +"CCIPWETH9Bridge: destination not enabled" +"CCIPWETH9Bridge: transfer failed" +"CCIPWETH9Bridge: transfer already processed" +``` + +### Error Handling Pattern + +```solidity +try bridge.sendCrossChain(selector, recipient, amount) returns (bytes32 messageId) { + emit TransferSuccess(messageId); +} catch Error(string memory reason) { + emit TransferFailed(reason); +} catch (bytes memory lowLevelData) { + emit TransferFailed("Low-level error"); +} +``` + +--- + +## Testing + +### Unit Tests + +```solidity +function testCrossChainTransfer() public { + // Setup + uint256 amount = 1 ether; + uint64 destSelector = 5009297550715157269; // Ethereum Mainnet + + // Approve + weth9.approve(address(bridge), amount); + + // Send + bytes32 messageId = bridge.sendCrossChain(destSelector, recipient, amount); + + // Verify + assertTrue(messageId != bytes32(0)); + emit TransferInitiated(messageId); +} +``` + +### Integration Tests + +Test end-to-end flow: +1. Send message on source chain +2. Verify message received on destination +3. Verify state changes +4. Test error cases + +--- + +## Gas Optimization + +### Tips + +1. **Batch Operations**: Group multiple operations when possible +2. **Optimize Data**: Minimize message data size +3. **Cache Values**: Cache frequently accessed values +4. **Use Events**: Emit events instead of storage for logging + +### Gas Estimates + +- **Router Message**: ~50,000 - 100,000 gas +- **Bridge Transfer**: ~100,000 - 200,000 gas +- **Fee Calculation**: ~5,000 gas (view function) + +--- + +## Best Practices + +1. **Always Calculate Fees**: Don't hardcode fee amounts +2. **Handle Errors**: Implement comprehensive error handling +3. **Monitor Events**: Track all CCIP events +4. **Verify Addresses**: Always verify contract addresses +5. **Test Thoroughly**: Test on testnet before mainnet + +--- + +## Related Documentation + +- [CCIP Deployment Guide](../ccip/DEPLOYMENT_GUIDE_CHAIN138.md) +- [User Guide](../user-guides/CCIP_BRIDGE_USER_GUIDE.md) +- [CCIP Review](../CCIP_CHAIN138_REVIEW.md) + +--- + +**Last Updated**: 2025-01-27 + diff --git a/docs/ccip/archive-import/docs/AWS_DEPLOYMENT_GUIDE.md b/docs/ccip/archive-import/docs/AWS_DEPLOYMENT_GUIDE.md new file mode 100644 index 0000000..caaeb46 --- /dev/null +++ b/docs/ccip/archive-import/docs/AWS_DEPLOYMENT_GUIDE.md @@ -0,0 +1,837 @@ +# AWS Deployment Guide + +**Last Updated**: 2025-01-27 +**Network**: ChainID 138 (DeFi Oracle Meta Mainnet) +**Target**: Amazon Web Services (AWS) + +## Overview + +This guide explains what is needed to deploy the DeFi Oracle Meta Mainnet blockchain network to AWS. The project currently supports Azure as the primary cloud provider, but includes multi-cloud infrastructure support that can be extended for AWS. + +## Current AWS Support Status + +| Component | Status | Notes | +|-----------|--------|-------| +| **Terraform Multi-Cloud Framework** | ✅ Partial | Basic AWS module exists | +| **EKS Cluster** | ✅ Partial | Basic cluster creation supported | +| **VPC & Networking** | ✅ Partial | VPC, subnets, security groups created | +| **IAM Roles** | ✅ Partial | EKS cluster and node roles configured | +| **Application Load Balancer** | ❌ Missing | Need ALB with WAF (replaces Azure Application Gateway) | +| **Secrets Management** | ❌ Missing | Need AWS Secrets Manager integration | +| **Storage** | ❌ Missing | Need S3 buckets and EBS storage classes | +| **DNS** | ❌ Missing | Need Route53 configuration | +| **SSL/TLS Certificates** | ❌ Missing | Need ACM (Certificate Manager) integration | +| **Monitoring** | ❌ Missing | Need CloudWatch integration | +| **Backup & Restore** | ❌ Missing | Need S3-based backup solution | + +## Required AWS Services & Resources + +### 1. Compute & Orchestration + +| Service | Purpose | Required | +|---------|---------|----------| +| **Amazon EKS** | Kubernetes cluster for running Besu nodes | ✅ Yes | +| **EC2 Instance Types** | Worker nodes for EKS | ✅ Yes | +| **Auto Scaling Groups** | Dynamic node scaling | ✅ Recommended | + +**Current Implementation**: ✅ Basic EKS cluster with node groups + +### 2. Networking + +| Service | Purpose | Required | +|---------|---------|----------| +| **VPC** | Virtual network for resources | ✅ Yes | +| **Subnets** | Network segmentation (public/private) | ✅ Yes | +| **Internet Gateway** | Internet access | ✅ Yes | +| **NAT Gateway** | Outbound internet for private subnets | ✅ Recommended | +| **Security Groups** | Firewall rules | ✅ Yes | +| **Route Tables** | Network routing | ✅ Yes | +| **Application Load Balancer (ALB)** | Load balancing and SSL termination | ✅ Required | +| **AWS WAF** | Web Application Firewall | ✅ Required | +| **Route53** | DNS management | ✅ Required | +| **ACM** | SSL/TLS certificates | ✅ Required | + +**Current Implementation**: ✅ VPC, subnets, security groups, IGW +**Missing**: ❌ ALB, WAF, Route53, ACM, NAT Gateway + +### 3. Storage + +| Service | Purpose | Required | +|---------|---------|----------| +| **EBS Volumes** | Persistent storage for Besu nodes | ✅ Yes | +| **EBS CSI Driver** | Kubernetes storage integration | ✅ Required | +| **S3 Buckets** | Backup storage, configuration files | ✅ Required | +| **S3 Lifecycle Policies** | Backup retention and cost optimization | ✅ Recommended | + +**Current Implementation**: ❌ None +**Missing**: ❌ All storage components + +### 4. Security & Secrets + +| Service | Purpose | Required | +|---------|---------|----------| +| **AWS Secrets Manager** | Store validator keys, RPC endpoints | ✅ Required | +| **AWS KMS** | Key encryption for secrets | ✅ Required | +| **IAM Roles** | Access control | ✅ Yes (partial) | +| **IAM Policies** | Permission management | ✅ Required | +| **Security Groups** | Network security | ✅ Yes | + +**Current Implementation**: ✅ Basic IAM roles for EKS +**Missing**: ❌ Secrets Manager, KMS, IAM policies for services + +### 5. Monitoring & Observability + +| Service | Purpose | Required | +|---------|---------|----------| +| **CloudWatch Logs** | Centralized logging | ✅ Required | +| **CloudWatch Metrics** | Performance metrics | ✅ Required | +| **CloudWatch Alarms** | Alerting | ✅ Required | +| **CloudWatch Container Insights** | EKS metrics | ✅ Recommended | +| **X-Ray** | Distributed tracing | ⚠️ Optional | +| **Prometheus** | Metrics collection (self-hosted) | ✅ Yes | +| **Grafana** | Visualization (self-hosted) | ✅ Yes | + +**Current Implementation**: ✅ CloudWatch log group for EKS +**Missing**: ❌ Metrics, alarms, container insights + +### 6. Database (for Blockscout) + +| Service | Purpose | Required | +|---------|---------|----------| +| **RDS PostgreSQL** | Blockscout database | ✅ Required | +| **RDS Read Replicas** | High availability | ⚠️ Optional | +| **RDS Automated Backups** | Database backups | ✅ Recommended | + +**Current Implementation**: ❌ None +**Missing**: ❌ RDS PostgreSQL for Blockscout + +### 7. Additional Services + +| Service | Purpose | Required | +|---------|---------|----------| +| **CloudFront** | CDN for static content | ⚠️ Optional | +| **ElastiCache** | Redis cache (if needed) | ⚠️ Optional | +| **AWS Systems Manager** | Parameter Store | ⚠️ Optional | + +## AWS Infrastructure Requirements + +### Minimum Resource Requirements + +#### EKS Cluster +- **Kubernetes Version**: 1.28+ (matches Azure AKS) +- **Node Groups**: + - **System Nodes**: 1-3 nodes (t3.medium or larger) + - **Validator Nodes**: 4+ nodes (t3.xlarge or larger) - 512Gi storage each + - **Sentry Nodes**: 3-5 nodes (t3.large or larger) - 256Gi storage each + - **RPC Nodes**: 3-5 nodes (t3.xlarge or larger) - 256Gi storage each + +#### Network Architecture +``` +VPC (10.0.0.0/16) +├── Public Subnets +│ ├── EKS Control Plane (10.0.1.0/24) +│ ├── RPC Nodes (10.0.4.0/24) +│ └── ALB (10.0.5.0/24) +└── Private Subnets + ├── Validators (10.0.2.0/24) + └── Sentries (10.0.3.0/24) +``` + +#### Storage Requirements +- **EBS Storage Classes**: + - `gp3` for validator nodes (512Gi per node, IOPS: 3000) + - `gp3` for sentry nodes (256Gi per node, IOPS: 3000) + - `gp3` for RPC nodes (256Gi per node, IOPS: 3000) +- **S3 Buckets**: + - `besu-chaindata-backups` - Chain data backups + - `besu-config-backups` - Configuration backups + - `blockscout-assets` - Blockscout static assets (optional) + +## Prerequisites + +### 1. AWS Account Setup + +```bash +# Install AWS CLI +curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" +unzip awscliv2.zip +sudo ./aws/install + +# Configure AWS credentials +aws configure +# Enter: +# - AWS Access Key ID +# - AWS Secret Access Key +# - Default region (e.g., us-west-2) +# - Default output format (json) +``` + +### 2. Required AWS Permissions + +Your AWS IAM user/role needs permissions for: +- EKS (cluster creation, node groups) +- EC2 (VPC, subnets, security groups, instances) +- IAM (role creation for EKS) +- S3 (bucket creation, lifecycle policies) +- Secrets Manager (secret creation) +- KMS (key creation) +- Route53 (DNS zone management) +- ACM (certificate management) +- ALB/WAF (load balancer creation) +- CloudWatch (logs, metrics, alarms) +- RDS (if using managed PostgreSQL) + +**Minimum IAM Policy**: AdministratorAccess or equivalent permissions for the above services. + +### 3. Tools Installation + +```bash +# Terraform (>= 1.0) +wget https://releases.hashicorp.com/terraform/1.6.0/terraform_1.6.0_linux_amd64.zip +unzip terraform_1.6.0_linux_amd64.zip +sudo mv terraform /usr/local/bin/ + +# kubectl +curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" +sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl + +# Helm (3.x) +curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash + +# AWS EKS CLI (eksctl) - Optional but recommended +curl --silent --location "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp +sudo mv /tmp/eksctl /usr/local/bin +``` + +### 4. Environment Variables + +Create a `.env` file or export environment variables: + +```bash +# AWS Credentials +export AWS_ACCESS_KEY_ID="your-access-key" +export AWS_SECRET_ACCESS_KEY="your-secret-key" +export AWS_DEFAULT_REGION="us-west-2" + +# Terraform Variables (or use terraform.tfvars) +export TF_VAR_environment="prod" +export TF_VAR_aws_default_region="us-west-2" + +# Optional: AWS Profile +export AWS_PROFILE="your-profile-name" +``` + +## Configuration + +### 1. Update environments.yaml + +Add AWS environment configuration to `config/environments.yaml`: + +```yaml +environments: + # AWS Workload Environment + - name: workload-aws-us-west-2 + role: workload + provider: aws + type: cloud + region: us-west-2 + location: "US West (Oregon)" + enabled: true + + components: + - validators + - sentries + - rpc + - monitoring + - blockscout + + infrastructure: + kubernetes: + provider: eks + version: "1.28" + node_pools: + system: + count: 3 + instance_type: "t3.medium" + validators: + count: 4 + instance_type: "t3.xlarge" + sentries: + count: 3 + instance_type: "t3.large" + rpc: + count: 3 + instance_type: "t3.xlarge" + + networking: + vpc_cidr: "10.0.0.0/16" + subnets: + - name: eks + cidr: "10.0.1.0/24" + - name: validators + cidr: "10.0.2.0/24" + - name: sentries + cidr: "10.0.3.0/24" + - name: rpc + cidr: "10.0.4.0/24" + - name: alb + cidr: "10.0.5.0/24" + + storage: + type: "gp3" + validator_storage_size: 512 + sentry_storage_size: 256 + rpc_storage_size: 256 + + aws: + account_id: "${AWS_ACCOUNT_ID}" + region: "us-west-2" + vpc_id: "" # Leave empty for new VPC + + secrets: + provider: aws-secrets-manager + kms_key_id: "${AWS_KMS_KEY_ID}" + + dns: + provider: route53 + hosted_zone: "your-domain.com" + rpc_domain: "rpc.your-domain.com" + explorer_domain: "explorer.your-domain.com" +``` + +### 2. Terraform Variables + +Create `terraform/multi-cloud/terraform.tfvars`: + +```hcl +environment = "prod" + +tags = { + Environment = "production" + Project = "DeFi Oracle Meta Mainnet" + ChainID = "138" + ManagedBy = "Terraform" + CostCenter = "Blockchain" + Owner = "DevOps Team" +} + +# AWS Configuration +aws_default_region = "us-west-2" + +# Enable features +enable_azure_arc = false # Disable if not using Azure +enable_service_mesh = true +service_mesh_provider = "istio" + +# Secrets Management +secrets_provider = "aws-secrets-manager" +``` + +## Deployment Steps + +### Step 1: Complete AWS Terraform Module + +The current AWS module is basic. You need to enhance it with: + +1. **Application Load Balancer (ALB)** + - Internet-facing ALB + - WAF integration + - SSL/TLS termination + - Target groups for RPC nodes and Blockscout + +2. **Storage Resources** + - EBS CSI driver installation + - Storage classes for gp3 + - S3 buckets for backups + +3. **Secrets Manager Integration** + - KMS key creation + - Secrets Manager secrets for validator keys + +4. **Route53 & ACM** + - Route53 hosted zone (or use existing) + - ACM certificate request + - DNS record creation + +5. **RDS PostgreSQL** + - RDS instance for Blockscout + - Security group for database access + - Backup configuration + +6. **CloudWatch Integration** + - CloudWatch log groups + - CloudWatch alarms + - Container Insights + +### Step 2: Deploy Infrastructure + +```bash +cd terraform/multi-cloud + +# Initialize Terraform +terraform init + +# Review plan +terraform plan -var-file=terraform.tfvars + +# Apply infrastructure +terraform apply -var-file=terraform.tfvars +``` + +### Step 3: Configure kubectl + +After EKS cluster is created: + +```bash +# Get kubeconfig +aws eks update-kubeconfig --name --region us-west-2 + +# Verify access +kubectl get nodes +``` + +### Step 4: Install EBS CSI Driver + +Required for persistent volumes: + +```bash +# Install EBS CSI driver +kubectl apply -k "github.com/kubernetes-sigs/aws-ebs-csi-driver/deploy/kubernetes/overlays/stable/?ref=release-1.28" + +# Create StorageClass +kubectl apply -f - < + +# Store RPC endpoint +aws secretsmanager create-secret \ + --name besu/rpc/endpoint \ + --secret-string "https://rpc.your-domain.com" \ + --kms-key-id +``` + +### Step 8: Configure DNS + +Create Route53 records: + +```bash +# Get ALB DNS name +ALB_DNS=$(aws elbv2 describe-load-balancers \ + --query 'LoadBalancers[?contains(LoadBalancerName, `besu`)].DNSName' \ + --output text) + +# Create Route53 record +aws route53 change-resource-record-sets \ + --hosted-zone-id \ + --change-batch '{ + "Changes": [{ + "Action": "UPSERT", + "ResourceRecordSet": { + "Name": "rpc.your-domain.com", + "Type": "CNAME", + "TTL": 300, + "ResourceRecords": [{"Value": "'$ALB_DNS'"}] + } + }] + }' +``` + +### Step 9: Deploy Blockscout + +```bash +# Deploy Blockscout (requires RDS PostgreSQL) +kubectl apply -f k8s/blockscout/ + +# Update database connection string to use RDS endpoint +kubectl set env deployment/blockscout \ + -n besu-network \ + DATABASE_URL="postgresql://blockscout:password@:5432/blockscout" +``` + +### Step 10: Deploy Monitoring Stack + +```bash +# Deploy Prometheus, Grafana, etc. +kubectl apply -f monitoring/k8s/ + +# Configure CloudWatch exporter for Prometheus (optional) +kubectl apply -f monitoring/cloudwatch/ +``` + +## Key Differences from Azure Deployment + +| Aspect | Azure | AWS | Notes | +|--------|-------|-----|-------| +| **Kubernetes** | AKS | EKS | Both managed, similar APIs | +| **Load Balancer** | Application Gateway + WAF | ALB + WAF | Both support SSL termination | +| **Secrets** | Key Vault | Secrets Manager | Both support KMS encryption | +| **Storage** | Managed Disks | EBS | Both support persistent volumes | +| **Backup Storage** | Blob Storage | S3 | Both object storage | +| **DNS** | Azure DNS | Route53 | Both support DNS management | +| **Certificates** | Key Vault Certificates | ACM | Both auto-renewal | +| **Monitoring** | Azure Monitor | CloudWatch | Both comprehensive | + +## What Needs to Be Added to AWS Module + +### 1. Application Load Balancer (Priority: High) + +```hcl +# terraform/multi-cloud/modules/aws/alb.tf (new file) +resource "aws_lb" "main" { + name = "${local.name_prefix}-alb" + internal = false + load_balancer_type = "application" + security_groups = [aws_security_group.alb.id] + subnets = [for s in aws_subnet.alb : s.id] + + enable_deletion_protection = var.environment == "prod" + + tags = merge(var.tags, { + Name = "${local.name_prefix}-alb" + }) +} + +resource "aws_wafv2_web_acl" "main" { + name = "${local.name_prefix}-waf" + scope = "REGIONAL" + + default_action { + allow {} + } + + rule { + name = "AWSManagedRulesCommonRuleSet" + priority = 1 + override_action { + none {} + } + statement { + managed_rule_group_statement { + name = "AWSManagedRulesCommonRuleSet" + vendor_name = "AWS" + } + } + visibility_config { + cloudwatch_metrics_enabled = true + metric_name = "CommonRuleSetMetric" + sampled_requests_enabled = true + } + } +} +``` + +### 2. Storage Resources (Priority: High) + +```hcl +# terraform/multi-cloud/modules/aws/storage.tf (new file) +resource "aws_s3_bucket" "backups" { + bucket = "${local.name_prefix}-backups" + + tags = merge(var.tags, { + Name = "${local.name_prefix}-backups" + }) +} + +resource "aws_s3_bucket_lifecycle_configuration" "backups" { + bucket = aws_s3_bucket.backups.id + + rule { + id = "transition-to-ia" + status = "Enabled" + + transition { + days = 30 + storage_class = "STANDARD_IA" + } + } + + rule { + id = "transition-to-glacier" + status = "Enabled" + + transition { + days = 90 + storage_class = "GLACIER" + } + } +} +``` + +### 3. Secrets Manager (Priority: High) + +```hcl +# terraform/multi-cloud/modules/aws/secrets.tf (new file) +resource "aws_kms_key" "secrets" { + description = "KMS key for Secrets Manager" + deletion_window_in_days = 30 + + tags = merge(var.tags, { + Name = "${local.name_prefix}-secrets-kms" + }) +} + +resource "aws_kms_alias" "secrets" { + name = "alias/${local.name_prefix}-secrets" + target_key_id = aws_kms_key.secrets.key_id +} +``` + +### 4. RDS PostgreSQL (Priority: Medium) + +```hcl +# terraform/multi-cloud/modules/aws/rds.tf (new file) +resource "aws_db_instance" "blockscout" { + identifier = "${local.name_prefix}-blockscout-db" + + engine = "postgres" + engine_version = "15.4" + instance_class = "db.t3.medium" + + allocated_storage = 100 + max_allocated_storage = 500 + storage_type = "gp3" + storage_encrypted = true + + db_name = "blockscout" + username = "blockscout" + password = var.db_password + + vpc_security_group_ids = [aws_security_group.rds.id] + db_subnet_group_name = aws_db_subnet_group.main.name + + backup_retention_period = 7 + backup_window = "03:00-04:00" + maintenance_window = "mon:04:00-mon:05:00" + + skip_final_snapshot = var.environment != "prod" + + tags = merge(var.tags, { + Name = "${local.name_prefix}-blockscout-db" + }) +} +``` + +### 5. Route53 & ACM (Priority: Medium) + +```hcl +# terraform/multi-cloud/modules/aws/dns.tf (new file) +resource "aws_acm_certificate" "main" { + domain_name = var.domain_name + validation_method = "DNS" + + subject_alternative_names = [ + "*.${var.domain_name}" + ] + + lifecycle { + create_before_destroy = true + } + + tags = merge(var.tags, { + Name = "${local.name_prefix}-cert" + }) +} + +resource "aws_route53_record" "rpc" { + zone_id = var.hosted_zone_id + name = "rpc.${var.domain_name}" + type = "CNAME" + ttl = 300 + records = [aws_lb.main.dns_name] +} +``` + +## Cost Estimation + +### Monthly Cost Estimate (us-west-2, production) + +| Service | Configuration | Monthly Cost (USD) | +|---------|--------------|-------------------| +| **EKS Cluster** | Managed cluster | $73 | +| **EC2 Instances** | 4x t3.xlarge + 3x t3.large + 3x t3.xlarge | ~$600 | +| **EBS Storage** | 2TB gp3 (512GB x4 + 256GB x6) | ~$160 | +| **S3 Storage** | 500GB backups | ~$12 | +| **ALB** | Application Load Balancer | ~$25 | +| **WAF** | AWS WAF | ~$5 | +| **RDS PostgreSQL** | db.t3.medium | ~$100 | +| **NAT Gateway** | 2 NAT Gateways | ~$65 | +| **Data Transfer** | 500GB outbound | ~$45 | +| **CloudWatch** | Logs and metrics | ~$30 | +| **Route53** | Hosted zone + queries | ~$1 | +| **ACM** | Certificate | $0 | +| **Total** | | **~$1,116/month** | + +**Note**: Costs vary based on usage, region, and instance sizes. Use AWS Cost Calculator for accurate estimates. + +## Security Considerations + +### 1. Network Security +- ✅ Use private subnets for validators +- ✅ Implement security groups with least privilege +- ✅ Enable VPC Flow Logs +- ✅ Use WAF for public-facing endpoints + +### 2. Secrets Management +- ✅ Use AWS Secrets Manager with KMS encryption +- ✅ Rotate secrets regularly +- ✅ Use IAM roles instead of access keys where possible + +### 3. Access Control +- ✅ Use IAM roles for EKS pods (IRSA) +- ✅ Enable RBAC in Kubernetes +- ✅ Use least privilege IAM policies + +### 4. Monitoring & Compliance +- ✅ Enable CloudTrail for audit logging +- ✅ Enable GuardDuty for threat detection +- ✅ Set up CloudWatch alarms +- ✅ Use AWS Config for compliance checking + +## Troubleshooting + +### Common Issues + +#### 1. EKS Node Group Fails to Join Cluster + +**Solution**: Verify IAM roles and policies are correctly attached: + +```bash +# Check node group IAM role +aws eks describe-nodegroup \ + --cluster-name \ + --nodegroup-name \ + --query 'nodegroup.nodeRole' + +# Verify IAM policies are attached +aws iam list-attached-role-policies --role-name +``` + +#### 2. Persistent Volumes Not Creating + +**Solution**: Install and configure EBS CSI driver: + +```bash +# Verify EBS CSI driver is running +kubectl get pods -n kube-system | grep ebs-csi + +# Check StorageClass +kubectl get storageclass gp3 +``` + +#### 3. ALB Not Routing Traffic + +**Solution**: Check ALB target group health: + +```bash +# Get target group ARN +TG_ARN=$(aws elbv2 describe-target-groups \ + --query 'TargetGroups[?contains(TargetGroupName, `besu`)].TargetGroupArn' \ + --output text) + +# Check target health +aws elbv2 describe-target-health --target-group-arn $TG_ARN +``` + +## Next Steps + +1. **Enhance AWS Terraform Module**: Add ALB, storage, secrets, RDS, DNS +2. **Update Kubernetes Manifests**: Change storage classes, add ALB annotations +3. **Configure Monitoring**: Set up CloudWatch integration +4. **Implement Backup Strategy**: S3-based backups for chain data +5. **Security Hardening**: WAF rules, security groups, IAM policies +6. **Documentation**: Update deployment docs with AWS-specific steps +7. **Testing**: Test deployment in dev environment first + +## Additional Resources + +- [AWS EKS Documentation](https://docs.aws.amazon.com/eks/) +- [EBS CSI Driver](https://github.com/kubernetes-sigs/aws-ebs-csi-driver) +- [AWS Load Balancer Controller](https://kubernetes-sigs.github.io/aws-load-balancer-controller/) +- [AWS Secrets Manager](https://docs.aws.amazon.com/secretsmanager/) +- [Terraform AWS Provider](https://registry.terraform.io/providers/hashicorp/aws/latest/docs) + +## Summary + +To deploy this project to AWS, you need: + +1. ✅ **Basic Infrastructure** (Partially Complete) + - EKS cluster + - VPC, subnets, security groups + - IAM roles + +2. ❌ **Missing Critical Components** + - Application Load Balancer with WAF + - AWS Secrets Manager integration + - Storage (EBS CSI driver, S3 buckets) + - Route53 DNS configuration + - ACM certificates + - RDS PostgreSQL for Blockscout + - CloudWatch integration + +3. ⚠️ **Configuration Updates Needed** + - Update Kubernetes manifests for AWS storage classes + - Configure ALB Ingress Controller + - Update Helm values for AWS + - Update service annotations for ALB + +4. 📝 **Documentation Updates** + - AWS-specific deployment guide + - Troubleshooting guide for AWS + - Cost optimization guide + +The multi-cloud Terraform framework provides a good foundation, but the AWS module needs significant enhancements to match the Azure deployment capabilities. + diff --git a/docs/ccip/archive-import/docs/CCIP_CHAIN138_QUICK_REFERENCE.md b/docs/ccip/archive-import/docs/CCIP_CHAIN138_QUICK_REFERENCE.md new file mode 100644 index 0000000..05bf492 --- /dev/null +++ b/docs/ccip/archive-import/docs/CCIP_CHAIN138_QUICK_REFERENCE.md @@ -0,0 +1,126 @@ +# CCIP ChainID 138 - Quick Reference + +**Status**: ⚠️ **NOT FULLY ENABLED** - Deployment Required + +--- + +## 🎯 Quick Status + +| Component | Status | Action Required | +|-----------|--------|-----------------| +| **CCIP Router** | ❌ Not Deployed | Deploy `CCIPRouter` contract | +| **LINK Token** | ❌ Not Deployed | Deploy LINK or use native ETH | +| **CCIP Chain Selector** | ✅ Calculated | `138` (or `0x000000000000008a`) | +| **CCIPWETH9Bridge** | ❌ Not Deployed | Deploy bridge contract | +| **CCIPWETH10Bridge** | ❌ Not Deployed | Deploy bridge contract | +| **WETH9** | ✅ Pre-deployed | Already in genesis | +| **WETH10** | ✅ Pre-deployed | Already in genesis | + +--- + +## 📋 Deployment Order + +1. **Calculate CCIP Chain Selector** (✅ Script ready) +2. **Deploy CCIPRouter** (or use native ETH fees) +3. **Deploy LINK Token** (optional - can use native ETH) +4. **Deploy CCIPWETH9Bridge** +5. **Deploy CCIPWETH10Bridge** +6. **Configure Bridges** with destination chains + +**Or use the complete deployment script:** +```bash +./scripts/deployment/deploy-ccip-chain138-complete.sh +``` + +--- + +## 🚀 Quick Deployment Commands + +### 1. Deploy CCIPRouter + +```bash +# Set environment variables +export CCIP_FEE_TOKEN=0x0000000000000000000000000000000000000000 # Use native ETH +export CCIP_BASE_FEE=1000000000000000 # 0.001 ETH +export CCIP_DATA_FEE_PER_BYTE=100000000 # 0.1 gwei per byte + +# Deploy +forge script script/DeployCCIPRouter.s.sol \ + --rpc-url $RPC_URL_138 \ + --broadcast \ + --private-key $PRIVATE_KEY +``` + +### 2. Deploy CCIPWETH9Bridge + +```bash +# Set environment variables +export CCIP_ROUTER= +export CCIP_FEE_TOKEN=0x0000000000000000000000000000000000000000 # Or LINK address + +# Deploy +forge script script/DeployCCIPWETH9Bridge.s.sol \ + --rpc-url $RPC_URL_138 \ + --broadcast \ + --private-key $PRIVATE_KEY +``` + +### 3. Deploy CCIPWETH10Bridge + +```bash +# Set environment variables (same as above) +export CCIP_ROUTER= +export CCIP_FEE_TOKEN=0x0000000000000000000000000000000000000000 + +# Deploy +forge script script/DeployCCIPWETH10Bridge.s.sol \ + --rpc-url $RPC_URL_138 \ + --broadcast \ + --private-key $PRIVATE_KEY +``` + +--- + +## ⚙️ Configuration + +### Update Environment Variables + +After deployment, update `.env`: + +```bash +# CCIP Infrastructure +CCIP_CHAIN138_ROUTER= +CCIP_CHAIN138_LINK_TOKEN= +CHAIN138_SELECTOR= + +# Bridges +CCIPWETH9_BRIDGE_CHAIN138= +CCIPWETH10_BRIDGE_CHAIN138= +``` + +### Configure Bridge Destinations + +```bash +# Add Ethereum Mainnet as destination +cast send $CCIPWETH9_BRIDGE_CHAIN138 \ + "addDestination(uint64,address)" \ + 5009297550715157269 \ + $CCIPWETH9_BRIDGE_MAINNET \ + --rpc-url $RPC_URL_138 \ + --private-key $PRIVATE_KEY +``` + +--- + +## 📚 Full Documentation + +- **Complete Review**: [`docs/CCIP_CHAIN138_REVIEW.md`](CCIP_CHAIN138_REVIEW.md) +- **Implementation Summary**: [`docs/ccip/IMPLEMENTATION_SUMMARY.md`](ccip/IMPLEMENTATION_SUMMARY.md) +- **Deployment Guide**: [`docs/ccip/DEPLOYMENT_GUIDE_CHAIN138.md`](ccip/DEPLOYMENT_GUIDE_CHAIN138.md) +- **Chain Selector**: [`docs/ccip/CHAIN_SELECTOR_CALCULATION.md`](ccip/CHAIN_SELECTOR_CALCULATION.md) +- **Main Guide**: [`docs/ETH_WETH_CHAINLINK_GUIDE.md`](ETH_WETH_CHAINLINK_GUIDE.md) + +--- + +**Last Updated**: 2025-01-27 + diff --git a/docs/ccip/archive-import/docs/CCIP_CHAIN138_REVIEW.md b/docs/ccip/archive-import/docs/CCIP_CHAIN138_REVIEW.md new file mode 100644 index 0000000..2826d9e --- /dev/null +++ b/docs/ccip/archive-import/docs/CCIP_CHAIN138_REVIEW.md @@ -0,0 +1,347 @@ +# CCIP Enablement Review for ChainID 138 + +**Date**: 2025-01-27 +**Reviewer**: AI Assistant +**Status**: ✅ **IMPLEMENTATION COMPLETE** - Ready for Deployment + +--- + +## Executive Summary + +ChainID 138 (DeFi Oracle Meta Mainnet) has **all CCIP infrastructure, scripts, and documentation implemented**. The project is **ready for deployment** when network access is available. All deployment scripts, configuration tools, verification scripts, and comprehensive documentation have been created. + +--- + +## ✅ What's Complete + +### 1. CCIP Smart Contracts +- ✅ **CCIPWETH9Bridge.sol** - Cross-chain WETH9 bridge contract +- ✅ **CCIPWETH10Bridge.sol** - Cross-chain WETH10 bridge contract +- ✅ **CCIPSender.sol** - Oracle data sender via CCIP +- ✅ **CCIPReceiver.sol** - Oracle data receiver via CCIP +- ✅ **CCIPRouter.sol** - Custom CCIP router implementation +- ✅ **CCIPRouterOptimized.sol** - Optimized router variant +- ✅ **CCIPMessageValidator.sol** - Message validation utilities +- ✅ **IRouterClient.sol** - CCIP router interface + +### 2. Deployment Scripts +- ✅ `script/DeployCCIPWETH9Bridge.s.sol` +- ✅ `script/DeployCCIPWETH10Bridge.s.sol` +- ✅ `script/DeployCCIPRouter.s.sol` +- ✅ `script/DeployCCIPSender.s.sol` +- ✅ `script/DeployCCIPReceiver.s.sol` +- ✅ `script/DeployWETHWithCCIP.s.sol` + +### 3. Supporting Infrastructure +- ✅ WETH9 pre-deployed in genesis.json (`0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2`) +- ✅ WETH10 pre-deployed in genesis.json (`0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f`) +- ✅ Deployment automation scripts +- ✅ Bridge configuration scripts +- ✅ Documentation structure + +--- + +## ❌ What's Missing (Critical Gaps) + +### 1. CCIP Router Deployment +**Status**: ❌ **NOT DEPLOYED** + +- **Issue**: The `CCIPRouter` contract exists but is not deployed on ChainID 138 +- **Current State**: + - Environment variable `CCIP_CHAIN138_ROUTER` points to Ethereum Mainnet router address (`0x80226fc0Ee2b096224EeAc085Bb9a8cba1146f7D`) + - This is incorrect - ChainID 138 needs its own router deployment +- **Required Action**: + 1. Deploy `CCIPRouter` contract to ChainID 138 + 2. Configure fee token (LINK or native ETH) + 3. Set base fee and data fee per byte + 4. Update `CCIP_CHAIN138_ROUTER` environment variable + 5. Register supported destination chains + +**Deployment Command**: +```bash +forge script script/DeployCCIPRouter.s.sol \ + --rpc-url $RPC_URL_138 \ + --broadcast \ + --private-key $PRIVATE_KEY +``` + +**Configuration Required**: +- `CCIP_FEE_TOKEN`: LINK token address (or `address(0)` for native ETH) +- `CCIP_BASE_FEE`: Base fee amount +- `CCIP_DATA_FEE_PER_BYTE`: Fee per byte of message data + +### 2. LINK Token Deployment +**Status**: ❌ **NOT DEPLOYED** + +- **Issue**: No LINK token contract deployed on ChainID 138 +- **Impact**: CCIP bridges require LINK token for fee payments (unless using native ETH) +- **Current State**: No LINK token address configured for ChainID 138 +- **Required Action**: + 1. Deploy LINK token contract (or use native ETH for fees) + 2. If using LINK: Deploy ERC-20 LINK token compatible with Chainlink's LINK + 3. Update `CCIP_CHAIN138_LINK_TOKEN` environment variable + 4. Fund bridges with LINK tokens for operations + +**Alternative**: Use native ETH for fees by setting `feeToken = address(0)` in CCIPRouter + +### 3. CCIP Chain Selector +**Status**: ⚠️ **PLACEHOLDER VALUE** + +- **Issue**: Chain selector was set to placeholder value `0x000000000000008a` (138 in hex) +- **Current State**: + - Selector calculated and documented: `138` (decimal) or `0x000000000000008a` (hex) + - Calculation method documented in `docs/ccip/CHAIN_SELECTOR_CALCULATION.md` + - Calculation script available: `scripts/ccip/calculate-chain-selector.sh` +- **Status**: ✅ **RESOLVED** + - Selector calculated using simple chainId method (recommended for custom CCIP) + - All documentation updated with calculated selector + - Scripts configured to use selector `138` + +**Note**: For custom CCIP router implementations, using chainId directly as selector is the recommended approach. If integrating with Chainlink's official CCIP network, you may need to register the chain and use their assigned selector. + +### 4. CCIP Bridge Deployments +**Status**: ❌ **NOT DEPLOYED** + +- **Issue**: CCIPWETH9Bridge and CCIPWETH10Bridge are not deployed on ChainID 138 +- **Current State**: + - Documentation shows status as "Deployable" or "Pending" + - No deployed addresses in environment variables +- **Required Action**: + 1. Deploy `CCIPWETH9Bridge` to ChainID 138 + 2. Deploy `CCIPWETH10Bridge` to ChainID 138 + 3. Configure bridges with: + - CCIP Router address (from step 1) + - WETH9/WETH10 addresses (already in genesis) + - LINK token address (from step 2) + 4. Update environment variables: + - `CCIPWETH9_BRIDGE_CHAIN138` + - `CCIPWETH10_BRIDGE_CHAIN138` + +**Deployment Commands**: +```bash +# Deploy WETH9 Bridge +forge script script/DeployCCIPWETH9Bridge.s.sol \ + --rpc-url $RPC_URL_138 \ + --broadcast \ + --private-key $PRIVATE_KEY + +# Deploy WETH10 Bridge +forge script script/DeployCCIPWETH10Bridge.s.sol \ + --rpc-url $RPC_URL_138 \ + --broadcast \ + --private-key $PRIVATE_KEY +``` + +### 5. Bridge Configuration +**Status**: ❌ **NOT CONFIGURED** + +- **Issue**: Bridges need destination chain selectors configured +- **Required Action**: + 1. Configure CCIPWETH9Bridge with destination chains: + - Add Ethereum Mainnet as destination + - Add other supported chains (BSC, Polygon, etc.) + 2. Configure CCIPWETH10Bridge with destination chains + 3. Configure corresponding bridges on other chains to point back to ChainID 138 + +**Configuration Example**: +```bash +# Add Ethereum Mainnet as destination +cast send $CCIPWETH9_BRIDGE_CHAIN138 \ + "addDestination(uint64,address)" \ + $ETH_MAINNET_SELECTOR \ + $CCIPWETH9_BRIDGE_MAINNET \ + --rpc-url $RPC_URL_138 \ + --private-key $PRIVATE_KEY +``` + +### 6. CCIP Infrastructure Documentation +**Status**: ⚠️ **INCOMPLETE** + +- **Issue**: Documentation shows ChainID 138 as "Pending" or "TBD" for CCIP components +- **Required Updates**: + 1. Update `docs/ETH_WETH_CHAINLINK_GUIDE.md`: + - Add ChainID 138 CCIP Router address (after deployment) + - Add ChainID 138 LINK token address + - Add ChainID 138 CCIP chain selector (calculated value) + - Add ChainID 138 bridge addresses + - Update status from "Pending" to "Deployed" + 2. Update `docs/deployment/ENV_EXAMPLE_CONTENT.md`: + - Add `CCIP_CHAIN138_LINK_TOKEN` variable + - Update `CCIP_CHAIN138_ROUTER` with actual deployed address + - Update `CHAIN138_SELECTOR` with calculated value + 3. Create deployment guide for ChainID 138 CCIP setup + +--- + +## 📋 Deployment Checklist + +### Phase 1: Core Infrastructure +- [ ] Deploy LINK token (or configure native ETH fees) +- [ ] Deploy CCIPRouter contract +- [ ] Configure CCIPRouter with fee settings +- [ ] Register supported destination chains in router +- [ ] Calculate and document CCIP chain selector + +### Phase 2: Bridge Deployment +- [ ] Deploy CCIPWETH9Bridge +- [ ] Deploy CCIPWETH10Bridge +- [ ] Configure bridges with router, WETH, and LINK addresses +- [ ] Verify bridge contracts on explorer + +### Phase 3: Bridge Configuration +- [ ] Configure CCIPWETH9Bridge destinations +- [ ] Configure CCIPWETH10Bridge destinations +- [ ] Configure corresponding bridges on other chains +- [ ] Test bidirectional bridge connectivity + +### Phase 4: Documentation & Testing +- [ ] Update all documentation with deployed addresses +- [ ] Update environment variable examples +- [ ] Create deployment verification script +- [ ] Test cross-chain message sending +- [ ] Test cross-chain token transfers + +--- + +## 🔧 Configuration Requirements + +### Environment Variables Needed + +```bash +# ChainID 138 CCIP Configuration +CCIP_CHAIN138_ROUTER= +CCIP_CHAIN138_LINK_TOKEN= +CHAIN138_SELECTOR= +CCIPWETH9_BRIDGE_CHAIN138= +CCIPWETH10_BRIDGE_CHAIN138= + +# CCIP Router Configuration +CCIP_BASE_FEE= +CCIP_DATA_FEE_PER_BYTE= +``` + +### CCIP Router Constructor Parameters + +```solidity +CCIPRouter( + address _feeToken, // LINK token or address(0) for native ETH + uint256 _baseFee, // Base fee in feeToken units + uint256 _dataFeePerByte // Fee per byte of message data +) +``` + +### Bridge Constructor Parameters + +```solidity +// CCIPWETH9Bridge +CCIPWETH9Bridge( + address _ccipRouter, // Deployed CCIPRouter address + address _weth9, // 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 (from genesis) + address _feeToken // LINK token or address(0) +) + +// CCIPWETH10Bridge +CCIPWETH10Bridge( + address _ccipRouter, // Deployed CCIPRouter address + address _weth10, // 0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f (from genesis) + address _feeToken // LINK token or address(0) +) +``` + +--- + +## 🔗 Cross-Chain Integration + +### Connecting to Ethereum Mainnet + +1. **On Ethereum Mainnet**: + - CCIPWETH9Bridge: `0x3304b747E565a97ec8AC220b0B6A1f6ffDB837e6` ✅ Deployed + - CCIPWETH10Bridge: `0x8078A09637e47Fa5Ed34F626046Ea2094a5CDE5e` ✅ Deployed + - CCIP Router: `0x80226fc0Ee2b096224EeAc085Bb9a8cba1146f7D` ✅ Official Chainlink + +2. **On ChainID 138** (After Deployment): + - Deploy CCIPWETH9Bridge + - Deploy CCIPWETH10Bridge + - Deploy CCIPRouter (custom or connect to Chainlink) + +3. **Configuration**: + - Add ChainID 138 as destination on Mainnet bridges + - Add Ethereum Mainnet as destination on ChainID 138 bridges + - Use correct chain selectors for each chain + +--- + +## 📊 Current Status Summary + +| Component | Status | Address | Notes | +|-----------|--------|---------|-------| +| **CCIP Router** | ❌ Not Deployed | - | ✅ Script ready - Ready to deploy | +| **LINK Token** | ❌ Not Deployed | - | Optional - Can use native ETH | +| **CCIP Chain Selector** | ✅ Calculated | `138` (or `0x000000000000008a`) | ✅ Calculation complete | +| **CCIPWETH9Bridge** | ❌ Not Deployed | - | ✅ Script ready - Ready to deploy | +| **CCIPWETH10Bridge** | ❌ Not Deployed | - | ✅ Script ready - Ready to deploy | +| **WETH9** | ✅ Pre-deployed | `0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2` | In genesis.json | +| **WETH10** | ✅ Pre-deployed | `0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f` | In genesis.json | + +--- + +## 🚀 Next Steps + +1. **Immediate Actions**: + - Deploy CCIPRouter to ChainID 138 + - Decide on fee token (LINK or native ETH) + - Calculate proper CCIP chain selector + - Deploy CCIP bridges + +2. **Configuration**: + - Configure router with supported chains + - Configure bridges with destinations + - Update all documentation + +3. **Testing**: + - Test router message sending + - Test bridge token transfers + - Verify cross-chain connectivity + +4. **Documentation**: + - Update deployment guides + - Document all addresses + - Create operational runbooks + +--- + +## 📝 Notes + +- **Custom vs Official CCIP**: The project includes a custom `CCIPRouter` implementation. If using Chainlink's official CCIP, you would need to use their router addresses instead. + +- **Native ETH Fees**: The CCIPRouter supports native ETH fees by setting `feeToken = address(0)`. This eliminates the need for LINK token deployment. + +- **Chain Selector Calculation**: CCIP chain selectors are typically calculated using a deterministic method. For custom chains, you may define your own format, but it should be consistent across all integrations. + +- **Bridge Reciprocity**: For bidirectional transfers, bridges on both chains must be configured with each other's addresses and chain selectors. + +--- + +**Last Updated**: 2025-01-27 +**Review Status**: ✅ **IMPLEMENTATION COMPLETE** - Ready for Deployment + +--- + +## Implementation Status + +All required infrastructure, scripts, and documentation have been implemented: + +- ✅ Chain selector calculation script and documentation +- ✅ Enhanced deployment scripts for ChainID 138 +- ✅ Router configuration script +- ✅ Bridge configuration scripts (updated with correct selectors) +- ✅ Deployment verification script +- ✅ Complete deployment guide +- ✅ User and developer guides +- ✅ Monitoring and operational documentation +- ✅ Security documentation + +**See**: [Implementation Summary](ccip/IMPLEMENTATION_SUMMARY.md) for complete details. + +**Next Step**: Deploy contracts when network is ready using the provided scripts. + diff --git a/docs/ccip/archive-import/docs/ETH_WETH_CHAINLINK_GUIDE.md b/docs/ccip/archive-import/docs/ETH_WETH_CHAINLINK_GUIDE.md new file mode 100644 index 0000000..ac01f2c --- /dev/null +++ b/docs/ccip/archive-import/docs/ETH_WETH_CHAINLINK_GUIDE.md @@ -0,0 +1,743 @@ +# Native ETH, WETH9, WETH10, Chainlink Bridges and Oracles - Complete Guide + +**Last Updated**: 2025-01-27 +**Network**: ChainID 138 (DeFi Oracle Meta Mainnet) & Ethereum Mainnet + +--- + +## Table of Contents + +1. [Native ETH](#native-eth) +2. [WETH9](#weth9) +3. [WETH10](#weth10) +4. [Chainlink CCIP Bridges](#chainlink-ccip-bridges) +5. [Chainlink Oracles](#chainlink-oracles) +6. [Contract Addresses Reference](#contract-addresses-reference) + +--- + +## Native ETH + +### Overview + +**Native ETH** (Ether) is the native cryptocurrency of the Ethereum blockchain and EVM-compatible chains. It serves as the base currency for transaction fees (gas) and can be used directly in smart contracts without wrapping. + +### Key Characteristics + +- **Type**: Native currency (not an ERC-20 token) +- **Decimals**: 18 +- **Symbol**: ETH +- **Network**: ChainID 138 (DeFi Oracle Meta Mainnet) +- **Usage**: + - Paying transaction fees (gas) + - Direct value transfers + - Native contract interactions + - Can be wrapped to WETH for ERC-20 compatibility + +### Technical Details + +- Native ETH is sent via `msg.value` in Solidity +- Received through `payable` functions or `receive()` fallback +- Cannot be transferred using standard ERC-20 methods +- Must be wrapped to WETH for use in DeFi protocols that require ERC-20 tokens + +### Contract Address + +Native ETH does not have a contract address as it is the native currency of the blockchain. + +--- + +## WETH9 + +### Overview + +**WETH9** (Wrapped Ether version 9) is the canonical ERC-20 representation of native ETH. It allows ETH to be used in DeFi protocols that require ERC-20 token standards. + +### Key Characteristics + +- **Standard**: ERC-20 compatible +- **Decimals**: 18 +- **Symbol**: WETH +- **Name**: Wrapped Ether +- **Purpose**: Enable ETH to be used as an ERC-20 token + +### Core Functions + +1. **`deposit()`**: Wrap native ETH to WETH9 + - Sends ETH to contract + - Mints equivalent WETH9 tokens + - Emits `Deposit` event + +2. **`withdraw(uint256 wad)`**: Unwrap WETH9 to native ETH + - Burns WETH9 tokens + - Sends equivalent ETH to caller + - Emits `Withdrawal` event + +3. **`transfer()` / `transferFrom()`**: Standard ERC-20 transfers + +4. **`approve()`**: Standard ERC-20 approvals + +### Implementation Details + +- **Total Supply**: Equals the contract's ETH balance +- **Automatic Wrapping**: `receive()` function automatically wraps ETH sent directly to contract +- **No Flash Loans**: WETH9 does not support flash loans + +### Contract Addresses + +#### Ethereum Mainnet (ChainID 1) +- **Address**: `0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2` +- **Status**: ✅ Canonical (Pre-deployed) +- **Etherscan**: [View on Etherscan](https://etherscan.io/address/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2) +- **Verified**: ✅ Yes + +#### ChainID 138 (DeFi Oracle Meta Mainnet) +- **Status**: Deployable (custom implementation available) +- **Contract File**: `contracts/tokens/WETH.sol` +- **Deployment Script**: `script/DeployWETH.s.sol` + +### Usage Example + +```solidity +// Wrap ETH to WETH9 +weth9.deposit{value: 1 ether}(); + +// Unwrap WETH9 to ETH +weth9.withdraw(1 ether); + +// Transfer WETH9 +weth9.transfer(recipient, amount); +``` + +--- + +## WETH10 + +### Overview + +**WETH10** is an enhanced version of WETH that includes ERC-3156 flash loan functionality and additional quality-of-life features. It maintains full backward compatibility with WETH9 while adding advanced capabilities. + +### Key Characteristics + +- **Standard**: ERC-20 + ERC-3156 Flash Loans +- **Decimals**: 18 +- **Symbol**: WETH +- **Name**: Wrapped Ether +- **Flash Loan Fee**: 0 (no fee) + +### Enhanced Features + +1. **ERC-3156 Flash Loans** + - `flashLoan()`: Borrow WETH10 without collateral + - `maxFlashLoan()`: Get maximum flash loan amount + - `flashFee()`: Get flash loan fee (0 for WETH10) + - Requires callback implementation: `onFlashLoan()` + +2. **Backward Compatibility** + - All WETH9 functions work identically + - Same `deposit()` and `withdraw()` interface + - Standard ERC-20 transfer/approve functions + +### Core Functions + +#### Standard WETH Functions +- `deposit()`: Wrap native ETH to WETH10 +- `withdraw(uint256 wad)`: Unwrap WETH10 to native ETH +- `transfer()` / `transferFrom()`: Standard ERC-20 transfers +- `approve()`: Standard ERC-20 approvals + +#### Flash Loan Functions +- `flashLoan(IERC3156FlashBorrower receiver, address token, uint256 amount, bytes calldata data)`: Execute flash loan +- `maxFlashLoan(address token)`: Get maximum flash loan amount +- `flashFee(address token, uint256 amount)`: Get flash loan fee + +### Implementation Details + +- **Flash Loan Fee**: 0 (no fee) +- **Flash Loan Callback**: Must return `FLASH_LOAN_CALLBACK_SUCCESS` +- **Repayment**: Must repay `amount + fee` within the same transaction +- **Total Supply**: Equals the contract's ETH balance + +### Contract Addresses + +#### Ethereum Mainnet (ChainID 1) +- **Address**: `0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f` +- **Status**: ✅ Canonical (Pre-deployed) +- **Etherscan**: [View on Etherscan](https://etherscan.io/address/0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f) +- **Verified**: ✅ Yes + +#### ChainID 138 (DeFi Oracle Meta Mainnet) +- **Status**: Deployable (custom implementation available) +- **Contract File**: `contracts/tokens/WETH10.sol` +- **Deployment Script**: Available via Foundry + +### Usage Example + +```solidity +// Standard WETH operations +weth10.deposit{value: 1 ether}(); +weth10.withdraw(1 ether); + +// Flash loan +weth10.flashLoan( + flashBorrower, + address(weth10), + 100 ether, + data +); + +// Flash loan callback (in receiver contract) +function onFlashLoan( + address initiator, + address token, + uint256 amount, + uint256 fee, + bytes calldata data +) external returns (bytes32) { + // Use borrowed funds + // ... perform operations ... + + // Repay loan + weth10.transfer(address(weth10), amount + fee); + + return WETH10.FLASH_LOAN_CALLBACK_SUCCESS; +} +``` + +### Differences from WETH9 + +| Feature | WETH9 | WETH10 | +|---------|-------|--------| +| Flash Loans | ❌ No | ✅ Yes (ERC-3156) | +| Flash Loan Fee | N/A | 0 | +| ERC-20 Compatibility | ✅ Yes | ✅ Yes | +| Backward Compatible | N/A | ✅ Yes | + +--- + +## Chainlink CCIP Bridges + +### Overview + +**Chainlink Cross-Chain Interoperability Protocol (CCIP)** bridges enable secure cross-chain token transfers. The project implements two CCIP bridges for WETH9 and WETH10 tokens. + +### CCIPWETH9Bridge + +Cross-chain bridge for WETH9 tokens using Chainlink CCIP. + +#### Features + +- **Cross-Chain Transfers**: Send WETH9 tokens between chains +- **Replay Protection**: Nonce-based and message ID tracking +- **Fee Management**: LINK token for CCIP fees +- **Admin Controls**: Configurable destination chains +- **Event Tracking**: Comprehensive event logging + +#### Key Functions + +1. **`sendCrossChain(uint64 destinationChainSelector, address recipient, uint256 amount)`** + - Locks WETH9 on source chain + - Sends CCIP message with WETH9 tokens + - Returns message ID for tracking + +2. **`ccipReceive(Any2EVMMessage calldata message)`** + - Receives CCIP message from router + - Validates and processes transfer + - Unlocks WETH9 on destination chain + +3. **`calculateFee(uint64 destinationChainSelector, uint256 amount)`** + - Estimates CCIP fee for transfer + - Returns required LINK amount + +#### Contract Addresses + +##### Ethereum Mainnet (ChainID 1) +- **Address**: `0x3304b747E565a97ec8AC220b0B6A1f6ffDB837e6` +- **Status**: ✅ Deployed & Verified +- **Etherscan**: [View on Etherscan](https://etherscan.io/address/0x3304b747E565a97ec8AC220b0B6A1f6ffDB837e6) +- **Contract File**: `contracts/ccip/CCIPWETH9Bridge.sol` + +##### Constructor Parameters +- **CCIP Router**: `0x80226fc0Ee2b096224EeAc085Bb9a8cba1146f7D` +- **WETH9**: `0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2` +- **LINK Token**: `0x514910771AF9Ca656af840dff83E8264EcF986CA` + +### CCIPWETH10Bridge + +Cross-chain bridge for WETH10 tokens using Chainlink CCIP. + +#### Features + +- **Cross-Chain Transfers**: Send WETH10 tokens between chains +- **Replay Protection**: Nonce-based and message ID tracking +- **Fee Management**: LINK token for CCIP fees +- **Admin Controls**: Configurable destination chains +- **Event Tracking**: Comprehensive event logging + +#### Key Functions + +1. **`sendCrossChain(uint64 destinationChainSelector, address recipient, uint256 amount)`** + - Locks WETH10 on source chain + - Sends CCIP message with WETH10 tokens + - Returns message ID for tracking + +2. **`ccipReceive(Any2EVMMessage calldata message)`** + - Receives CCIP message from router + - Validates and processes transfer + - Unlocks WETH10 on destination chain + +3. **`calculateFee(uint64 destinationChainSelector, uint256 amount)`** + - Estimates CCIP fee for transfer + - Returns required LINK amount + +#### Contract Addresses + +##### Ethereum Mainnet (ChainID 1) +- **Address**: `0x8078A09637e47Fa5Ed34F626046Ea2094a5CDE5e` +- **Status**: ✅ Deployed & Verified +- **Etherscan**: [View on Etherscan](https://etherscan.io/address/0x8078A09637e47Fa5Ed34F626046Ea2094a5CDE5e) +- **Contract File**: `contracts/ccip/CCIPWETH10Bridge.sol` + +##### Constructor Parameters +- **CCIP Router**: `0x80226fc0Ee2b096224EeAc085Bb9a8cba1146f7D` +- **WETH10**: `0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f` +- **LINK Token**: `0x514910771AF9Ca656af840dff83E8264EcF986CA` + +### CCIP Infrastructure + +#### CCIP Router (Chainlink Official) + +The CCIP Router is the core infrastructure component that routes messages between chains. + +##### Ethereum Mainnet (ChainID 1) +- **Address**: `0x80226fc0Ee2b096224EeAc085Bb9a8cba1146f7D` +- **Type**: Chainlink CCIP Router +- **Status**: ✅ Official Chainlink Deployment +- **Etherscan**: [View on Etherscan](https://etherscan.io/address/0x80226fc0Ee2b096224EeAc085Bb9a8cba1146f7D) +- **Used By**: CCIPWETH9Bridge, CCIPWETH10Bridge + +#### LINK Token (Chainlink Official) + +LINK token is used to pay CCIP fees for cross-chain transfers. + +##### Ethereum Mainnet (ChainID 1) +- **Address**: `0x514910771AF9Ca656af840dff83E8264EcF986CA` +- **Type**: ERC-20 Token (LINK) +- **Status**: ✅ Official Chainlink Deployment +- **Etherscan**: [View on Etherscan](https://etherscan.io/address/0x514910771AF9Ca656af840dff83E8264EcF986CA) +- **Used By**: CCIPWETH9Bridge, CCIPWETH10Bridge (for CCIP fees) + +### Bridge Usage Flow + +1. **User Approval**: Approve bridge to spend WETH9/WETH10 +2. **Approve LINK**: Approve bridge to spend LINK for fees +3. **Send Cross-Chain**: Call `sendCrossChain()` with destination and amount +4. **CCIP Processing**: CCIP Router handles cross-chain message +5. **Receive on Destination**: Bridge receives message and unlocks tokens + +### Security Features + +- **Replay Protection**: Message ID and nonce tracking +- **Access Control**: Admin-only configuration functions +- **Router Validation**: Only CCIP Router can call `ccipReceive()` +- **Token Validation**: Validates token addresses in messages +- **Zero Address Checks**: Prevents invalid recipient addresses + +--- + +## Chainlink Oracles + +### Overview + +Chainlink oracles provide reliable, decentralized price feeds and data for smart contracts. The project implements Chainlink-compatible oracle aggregators for price feeds. + +### Oracle Aggregator + +The `Aggregator` contract implements a Chainlink-compatible oracle aggregator interface for price feeds. + +#### Features + +- **Chainlink-Compatible Interface**: Implements `IAggregator` interface +- **Round-Based Updates**: Tracks price updates by round +- **Access Control**: Admin and transmitter roles +- **Heartbeat**: Configurable update frequency +- **Deviation Threshold**: Updates only when price moves significantly +- **Pause Functionality**: Emergency pause capability + +#### Key Functions + +1. **`updateAnswer(uint256 answer)`** + - Updates price feed answer + - Only callable by transmitters + - Creates new round if heartbeat or deviation threshold met + +2. **`latestAnswer()`** + - Returns latest price as `int256` + - Chainlink-compatible interface + +3. **`latestRoundData()`** + - Returns complete round data + - Includes round ID, answer, timestamps + - Chainlink-compatible interface + +4. **`getRoundData(uint80 _roundId)`** + - Returns data for specific round + - Historical price data access + +#### Configuration + +- **Decimals**: 8 (Chainlink standard) +- **Heartbeat**: Configurable (default: 60 seconds) +- **Deviation Threshold**: Configurable (default: 50 basis points = 0.5%) +- **Version**: 1 + +#### Access Control + +- **Admin**: Can add/remove transmitters, update config, pause +- **Transmitters**: Can update price answers +- **Public**: Can read price data + +#### Contract Files + +- **Aggregator**: `contracts/oracle/Aggregator.sol` +- **Proxy**: `contracts/oracle/Proxy.sol` +- **Interface**: `contracts/interfaces/IAggregator.sol` +- **Deployment Script**: `script/DeployOracle.s.sol` + +#### Deployment + +The oracle aggregator is deployed per price feed (e.g., ETH/USD, BTC/USD). Each deployment requires: + +- **Description**: Price feed description (e.g., "ETH/USD Price Feed") +- **Admin**: Admin address for configuration +- **Heartbeat**: Update frequency in seconds +- **Deviation Threshold**: Price change threshold in basis points + +#### Usage Example + +```solidity +// Read latest price +int256 price = aggregator.latestAnswer(); + +// Read latest round data +( + uint80 roundId, + int256 answer, + uint256 startedAt, + uint256 updatedAt, + uint80 answeredInRound +) = aggregator.latestRoundData(); + +// Read historical round +( + uint80 roundId, + int256 answer, + uint256 startedAt, + uint256 updatedAt, + uint80 answeredInRound +) = aggregator.getRoundData(roundId); + +// Update price (transmitter only) +aggregator.updateAnswer(newPrice); +``` + +### Oracle Proxy + +The `Proxy` contract provides upgradeability for the oracle aggregator, allowing implementation updates while maintaining the same address. + +#### Features + +- **Upgradeability**: Can update aggregator implementation +- **Admin Control**: Only admin can upgrade +- **Delegation**: Forwards calls to implementation + +#### Contract Addresses + +Oracle contracts are deployed per network and per price feed. Addresses are determined at deployment time. + +**ChainID 138 (DeFi Oracle Meta Mainnet)** +- Deployable via `script/DeployOracle.s.sol` +- Each price feed has its own aggregator and proxy + +### Chainlink Price Feed Addresses (Ethereum Mainnet Reference) + +For reference, here are some official Chainlink price feed addresses on Ethereum Mainnet: + +#### ETH/USD +- **Address**: `0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419` +- **Decimals**: 8 +- **Etherscan**: [View on Etherscan](https://etherscan.io/address/0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419) + +#### BTC/USD +- **Address**: `0xF4030086522a5bEEa4988F8cA5B36dbC97BeE88c` +- **Decimals**: 8 +- **Etherscan**: [View on Etherscan](https://etherscan.io/address/0xF4030086522a5bEEa4988F8cA5B36dbC97BeE88c) + +#### LINK/USD +- **Address**: `0x2c1d072e956AFFC0D435Cb1AC137Fc48C0F4775F` +- **Decimals**: 8 +- **Etherscan**: [View on Etherscan](https://etherscan.io/address/0x2c1d072e956AFFC0D435Cb1AC137Fc48C0F4775F) + +> **Note**: For a complete list of Chainlink price feeds, visit [Chainlink Data Feeds](https://docs.chain.link/data-feeds/price-feeds) + +--- + +## Contract Addresses Reference + +### Ethereum Mainnet (ChainID 1) + +#### WETH Contracts + +| Contract | Address | Status | Etherscan | +|----------|---------|--------|-----------| +| **WETH9** | `0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2` | ✅ Canonical | [View](https://etherscan.io/address/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2) | +| **WETH10** | `0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f` | ✅ Canonical | [View](https://etherscan.io/address/0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f) | + +#### CCIP Bridges + +| Contract | Address | Status | Etherscan | +|----------|---------|--------|-----------| +| **CCIPWETH9Bridge** | `0x3304b747E565a97ec8AC220b0B6A1f6ffDB837e6` | ✅ Deployed & Verified | [View](https://etherscan.io/address/0x3304b747E565a97ec8AC220b0B6A1f6ffDB837e6) | +| **CCIPWETH10Bridge** | `0x8078A09637e47Fa5Ed34F626046Ea2094a5CDE5e` | ✅ Deployed & Verified | [View](https://etherscan.io/address/0x8078A09637e47Fa5Ed34F626046Ea2094a5CDE5e) | + +#### CCIP Infrastructure + +| Contract | Address | Status | Etherscan | +|----------|---------|--------|-----------| +| **CCIP Router** | `0x80226fc0Ee2b096224EeAc085Bb9a8cba1146f7D` | ✅ Official Chainlink | [View](https://etherscan.io/address/0x80226fc0Ee2b096224EeAc085Bb9a8cba1146f7D) | +| **LINK Token** | `0x514910771AF9Ca656af840dff83E8264EcF986CA` | ✅ Official Chainlink | [View](https://etherscan.io/address/0x514910771AF9Ca656af840dff83E8264EcF986CA) | + +#### Chainlink Price Feeds (Reference) + +| Price Feed | Address | Decimals | Etherscan | +|------------|---------|----------|-----------| +| **ETH/USD** | `0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419` | 8 | [View](https://etherscan.io/address/0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419) | +| **BTC/USD** | `0xF4030086522a5bEEa4988F8cA5B36dbC97BeE88c` | 8 | [View](https://etherscan.io/address/0xF4030086522a5bEEa4988F8cA5B36dbC97BeE88c) | +| **LINK/USD** | `0x2c1d072e956AFFC0D435Cb1AC137Fc48C0F4775F` | 8 | [View](https://etherscan.io/address/0x2c1d072e956AFFC0D435Cb1AC137Fc48C0F4775F) | + +### ChainID 138 (DeFi Oracle Meta Mainnet) + +#### WETH Contracts + +| Contract | Status | Contract File | Deployment Script | +|----------|--------|---------------|-------------------| +| **WETH9** | Deployable | `contracts/tokens/WETH.sol` | `script/DeployWETH.s.sol` | +| **WETH10** | Deployable | `contracts/tokens/WETH10.sol` | Available via Foundry | + +#### Oracle Contracts + +| Contract | Status | Contract File | Deployment Script | +|----------|--------|---------------|-------------------| +| **Aggregator** | Deployable | `contracts/oracle/Aggregator.sol` | `script/DeployOracle.s.sol` | +| **Proxy** | Deployable | `contracts/oracle/Proxy.sol` | `script/DeployOracle.s.sol` | + +> **Note**: Contract addresses on ChainID 138 are determined at deployment time. Use deployment scripts to deploy and record addresses. + +--- + +## Complete Address Reference - All Networks + +### All WETH Addresses by Network + +| Network | Chain ID | WETH9 Address | WETH10 Address | Status | +|---------|----------|---------------|----------------|--------| +| **Ethereum Mainnet** | 1 | `0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2` | `0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f` | ✅ Canonical | +| **BSC** | 56 | `0x99b3511a2d315a497c8112c1fdd8d508d4b1e506` | `0x3304b747e565a97ec8ac220b0b6a1f6ffdb837e6` | ✅ Deployed | +| **Polygon** | 137 | `0xe0e93247376aa097db308b92e6ba36ba015535d0` | `0xab57bf30f1354ca0590af22d8974c7f24db2dbd7` | ✅ Deployed | +| **Avalanche** | 43114 | `0x99b3511a2d315a497c8112c1fdd8d508d4b1e506` | `0x3304b747e565a97ec8ac220b0b6a1f6ffdb837e6` | ✅ Deployed | +| **Base** | 8453 | `0x99b3511a2d315a497c8112c1fdd8d508d4b1e506` | `0x3304b747e565a97ec8ac220b0b6a1f6ffdb837e6` | ✅ Deployed | +| **Arbitrum** | 42161 | `0x99b3511a2d315a497c8112c1fdd8d508d4b1e506` | `0x3304b747e565a97ec8ac220b0b6a1f6ffdb837e6` | ✅ Deployed | +| **Optimism** | 10 | `0x99b3511a2d315a497c8112c1fdd8d508d4b1e506` | `0x3304b747e565a97ec8ac220b0b6a1f6ffdb837e6` | ✅ Deployed | +| **ChainID 138** | 138 | ✅ Pre-deployed | ✅ Pre-deployed | ✅ In Genesis | + +### All CCIP Bridge Addresses by Network + +| Network | Chain ID | CCIPWETH9Bridge | CCIPWETH10Bridge | Status | +|---------|----------|-----------------|------------------|--------| +| **Ethereum Mainnet** | 1 | `0x3304b747E565a97ec8AC220b0B6A1f6ffDB837e6` | `0x8078A09637e47Fa5Ed34F626046Ea2094a5CDE5e` | ✅ Verified | +| **BSC** | 56 | `0x8078a09637e47fa5ed34f626046ea2094a5cde5e` | `0x105f8a15b819948a89153505762444ee9f324684` | ✅ Verified | +| **Polygon** | 137 | `0xa780ef19a041745d353c9432f2a7f5a241335ffe` | `0xdab0591e5e89295ffad75a71dcfc30c5625c4fa2` | ✅ Verified | +| **Avalanche** | 43114 | `0x8078a09637e47fa5ed34f626046ea2094a5cde5e` | `0x105f8a15b819948a89153505762444ee9f324684` | ✅ Verified | +| **Base** | 8453 | `0x8078a09637e47fa5ed34f626046ea2094a5cde5e` | `0x105f8a15b819948a89153505762444ee9f324684` | ✅ Verified | +| **Arbitrum** | 42161 | `0x8078a09637e47fa5ed34f626046ea2094a5cde5e` | `0x105f8a15b819948a89153505762444ee9f324684` | ✅ Verified | +| **Optimism** | 10 | `0x8078a09637e47fa5ed34f626046ea2094a5cde5e` | `0x105f8a15b819948a89153505762444ee9f324684` | ✅ Verified | +| **ChainID 138** | 138 | ❌ Not Deployed | ❌ Not Deployed | ⚠️ **See [CCIP Review](CCIP_CHAIN138_REVIEW.md)** | + +### CCIP Infrastructure Addresses + +#### CCIP Router Addresses (Official Chainlink) + +| Network | Chain ID | CCIP Router Address | Status | +|---------|----------|---------------------|--------| +| **Ethereum Mainnet** | 1 | `0x80226fc0Ee2b096224EeAc085Bb9a8cba1146f7D` | ✅ Official | +| **BSC** | 56 | Check [Chainlink Docs](https://docs.chain.link/ccip/supported-networks) | ✅ Official | +| **Polygon** | 137 | Check [Chainlink Docs](https://docs.chain.link/ccip/supported-networks) | ✅ Official | +| **Avalanche** | 43114 | Check [Chainlink Docs](https://docs.chain.link/ccip/supported-networks) | ✅ Official | +| **Base** | 8453 | Check [Chainlink Docs](https://docs.chain.link/ccip/supported-networks) | ✅ Official | +| **Arbitrum** | 42161 | Check [Chainlink Docs](https://docs.chain.link/ccip/supported-networks) | ✅ Official | +| **Optimism** | 10 | Check [Chainlink Docs](https://docs.chain.link/ccip/supported-networks) | ✅ Official | +| **ChainID 138** | 138 | ❌ Not Deployed | ⚠️ **See [CCIP Review](CCIP_CHAIN138_REVIEW.md)** | + +#### LINK Token Addresses (Official Chainlink) + +| Network | Chain ID | LINK Token Address | Status | +|---------|----------|-------------------|--------| +| **Ethereum Mainnet** | 1 | `0x514910771AF9Ca656af840dff83E8264EcF986CA` | ✅ Official | +| **BSC** | 56 | Check [Chainlink Docs](https://docs.chain.link/ccip/supported-networks) | ✅ Official | +| **Polygon** | 137 | Check [Chainlink Docs](https://docs.chain.link/ccip/supported-networks) | ✅ Official | +| **Avalanche** | 43114 | Check [Chainlink Docs](https://docs.chain.link/ccip/supported-networks) | ✅ Official | +| **Base** | 8453 | Check [Chainlink Docs](https://docs.chain.link/ccip/supported-networks) | ✅ Official | +| **Arbitrum** | 42161 | Check [Chainlink Docs](https://docs.chain.link/ccip/supported-networks) | ✅ Official | +| **Optimism** | 10 | Check [Chainlink Docs](https://docs.chain.link/ccip/supported-networks) | ✅ Official | +| **ChainID 138** | 138 | ❌ Not Deployed | ⚠️ **Or use native ETH fees** | + +### Blockchain Networks Summary + +| Network Name | Chain ID | Type | Explorer | Status | +|--------------|----------|------|----------|--------| +| **Ethereum Mainnet** | 1 | Mainnet | [Etherscan](https://etherscan.io) | ✅ Active | +| **BSC (Binance Smart Chain)** | 56 | Mainnet | [BscScan](https://bscscan.com) | ✅ Active | +| **Polygon** | 137 | Mainnet | [Polygonscan](https://polygonscan.com) | ✅ Active | +| **Avalanche** | 43114 | Mainnet | [Snowtrace](https://snowtrace.io) | ✅ Active | +| **Base** | 8453 | Mainnet | [Basescan](https://basescan.org) | ✅ Active | +| **Arbitrum** | 42161 | Mainnet | [Arbiscan](https://arbiscan.io) | ✅ Active | +| **Optimism** | 10 | Mainnet | [Optimistic Etherscan](https://optimistic.etherscan.io) | ✅ Active | +| **DeFi Oracle Meta Mainnet** | 138 | Mainnet | [Blockscout](https://explorer.d-bis.org) | ✅ Active | + +### CCIP Chain Selectors + +| Network | Chain ID | CCIP Chain Selector | +|---------|----------|-------------------| +| **Ethereum Mainnet** | 1 | `5009297550715157269` | +| **BSC** | 56 | `11344663589394136015` | +| **Polygon** | 137 | `4051577828743386545` | +| **Avalanche** | 43114 | `6433500567565415381` | +| **Base** | 8453 | `15971525489660198786` | +| **Arbitrum** | 42161 | `4949039107694359620` | +| **Optimism** | 10 | `3734403246176062136` | +| **ChainID 138** | 138 | **`138`** (or `0x000000000000008a`) - See [Chain Selector Calculation](ccip/CHAIN_SELECTOR_CALCULATION.md) | + +--- + +## Environment Variables + +For easy reference, add these to your `.env` file: + +```bash +# ============================================ +# Ethereum Mainnet (ChainID 1) +# ============================================ +WETH9_MAINNET=0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 +WETH10_MAINNET=0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f +CCIPWETH9BRIDGE_MAINNET=0x3304b747E565a97ec8AC220b0B6A1f6ffDB837e6 +CCIPWETH10BRIDGE_MAINNET=0x8078A09637e47Fa5Ed34F626046Ea2094a5CDE5e +CCIP_MAINNET_ROUTER=0x80226fc0Ee2b096224EeAc085Bb9a8cba1146f7D +CCIP_MAINNET_LINK_TOKEN=0x514910771AF9Ca656af840dff83E8264EcF986CA + +# Chainlink Price Feeds (Ethereum Mainnet) +CHAINLINK_ETH_USD=0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419 +CHAINLINK_BTC_USD=0xF4030086522a5bEEa4988F8cA5B36dbC97BeE88c +CHAINLINK_LINK_USD=0x2c1d072e956AFFC0D435Cb1AC137Fc48C0F4775F + +# ============================================ +# BSC (ChainID 56) +# ============================================ +WETH9_BSC=0x99b3511a2d315a497c8112c1fdd8d508d4b1e506 +WETH10_BSC=0x3304b747e565a97ec8ac220b0b6a1f6ffdb837e6 +CCIPWETH9BRIDGE_BSC=0x8078a09637e47fa5ed34f626046ea2094a5cde5e +CCIPWETH10BRIDGE_BSC=0x105f8a15b819948a89153505762444ee9f324684 + +# ============================================ +# Polygon (ChainID 137) +# ============================================ +WETH9_POLYGON=0xe0e93247376aa097db308b92e6ba36ba015535d0 +WETH10_POLYGON=0xab57bf30f1354ca0590af22d8974c7f24db2dbd7 +CCIPWETH9BRIDGE_POLYGON=0xa780ef19a041745d353c9432f2a7f5a241335ffe +CCIPWETH10BRIDGE_POLYGON=0xdab0591e5e89295ffad75a71dcfc30c5625c4fa2 + +# ============================================ +# Avalanche (ChainID 43114) +# ============================================ +WETH9_AVALANCHE=0x99b3511a2d315a497c8112c1fdd8d508d4b1e506 +WETH10_AVALANCHE=0x3304b747e565a97ec8ac220b0b6a1f6ffdb837e6 +CCIPWETH9BRIDGE_AVALANCHE=0x8078a09637e47fa5ed34f626046ea2094a5cde5e +CCIPWETH10BRIDGE_AVALANCHE=0x105f8a15b819948a89153505762444ee9f324684 + +# ============================================ +# Base (ChainID 8453) +# ============================================ +WETH9_BASE=0x99b3511a2d315a497c8112c1fdd8d508d4b1e506 +WETH10_BASE=0x3304b747e565a97ec8ac220b0b6a1f6ffdb837e6 +CCIPWETH9BRIDGE_BASE=0x8078a09637e47fa5ed34f626046ea2094a5cde5e +CCIPWETH10BRIDGE_BASE=0x105f8a15b819948a89153505762444ee9f324684 + +# ============================================ +# Arbitrum (ChainID 42161) +# ============================================ +WETH9_ARBITRUM=0x99b3511a2d315a497c8112c1fdd8d508d4b1e506 +WETH10_ARBITRUM=0x3304b747e565a97ec8ac220b0b6a1f6ffdb837e6 +CCIPWETH9BRIDGE_ARBITRUM=0x8078a09637e47fa5ed34f626046ea2094a5cde5e +CCIPWETH10BRIDGE_ARBITRUM=0x105f8a15b819948a89153505762444ee9f324684 + +# ============================================ +# Optimism (ChainID 10) +# ============================================ +WETH9_OPTIMISM=0x99b3511a2d315a497c8112c1fdd8d508d4b1e506 +WETH10_OPTIMISM=0x3304b747e565a97ec8ac220b0b6a1f6ffdb837e6 +CCIPWETH9BRIDGE_OPTIMISM=0x8078a09637e47fa5ed34f626046ea2094a5cde5e +CCIPWETH10BRIDGE_OPTIMISM=0x105f8a15b819948a89153505762444ee9f324684 + +# ============================================ +# ChainID 138 (DeFi Oracle Meta Mainnet) +# ============================================ +# ⚠️ CCIP NOT FULLY ENABLED - See docs/CCIP_CHAIN138_REVIEW.md +# +# WETH9 and WETH10 are pre-deployed in genesis.json: +WETH9_CHAIN138=0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 +WETH10_CHAIN138=0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f + +# CCIP Infrastructure (TO BE DEPLOYED): +# CCIP_CHAIN138_ROUTER= +# CCIP_CHAIN138_LINK_TOKEN= +# CHAIN138_SELECTOR= +# CCIPWETH9_BRIDGE_CHAIN138= +# CCIPWETH10_BRIDGE_CHAIN138= +``` + +--- + +## Additional Resources + +### Documentation + +- [Chainlink CCIP Documentation](https://docs.chain.link/ccip) +- [Chainlink Data Feeds](https://docs.chain.link/data-feeds/price-feeds) +- [WETH9 Specification](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md) +- [WETH10 Specification](https://github.com/WETH10/WETH10) +- [ERC-3156 Flash Loans](https://eips.ethereum.org/EIPS/eip-3156) + +### Contract Verification + +- **Etherscan Verification**: [Verify Contracts](https://etherscan.io/myverify_address) +- **CCIPWETH9Bridge**: Verified ✅ +- **CCIPWETH10Bridge**: Verified ✅ + +### Related Files + +- `contracts/tokens/WETH.sol` - WETH9 implementation +- `contracts/tokens/WETH10.sol` - WETH10 implementation +- `contracts/ccip/CCIPWETH9Bridge.sol` - WETH9 bridge +- `contracts/ccip/CCIPWETH10Bridge.sol` - WETH10 bridge +- `contracts/oracle/Aggregator.sol` - Oracle aggregator +- `contracts/oracle/Proxy.sol` - Oracle proxy +- `docs/deployment/MAINNET_CONTRACTS_LIST.md` - Complete contract list +- `docs/CCIP_CHAIN138_REVIEW.md` - CCIP Enablement Review for ChainID 138 +- `docs/ccip/CHAIN_SELECTOR_CALCULATION.md` - Chain selector calculation guide +- `docs/ccip/DEPLOYMENT_GUIDE_CHAIN138.md` - Complete deployment guide +- `docs/user-guides/CCIP_BRIDGE_USER_GUIDE.md` - User guide for bridge usage +- `docs/developer-guides/CCIP_INTEGRATION_GUIDE.md` - Developer integration guide + +--- + +**Last Updated**: 2025-01-27 + diff --git a/docs/ccip/archive-import/docs/integration/KEEPER_DEPLOYMENT_COMPLETE.md b/docs/ccip/archive-import/docs/integration/KEEPER_DEPLOYMENT_COMPLETE.md new file mode 100644 index 0000000..d06525f --- /dev/null +++ b/docs/ccip/archive-import/docs/integration/KEEPER_DEPLOYMENT_COMPLETE.md @@ -0,0 +1,211 @@ +# Keeper Deployment - ALL OPTIONS COMPLETE ✅ + +**Date**: 2025-01-27 +**Status**: ✅ **ALL INTEGRATION OPTIONS DEPLOYED** + +--- + +## Summary + +All integration options for the automated price feed keeper have been implemented, tested, and are ready for deployment. Complete deployment automation and monitoring systems are in place. + +--- + +## ✅ Completed Components + +### Contracts (3) + +1. **PriceFeedKeeper.sol** ✅ + - Core keeper contract + - Asset tracking + - Batch updates + - Configurable intervals + +2. **ChainlinkKeeperCompatible.sol** ✅ + - Chainlink Automation wrapper + - Implements AutomationCompatibleInterface + - Compatible with Chainlink KeeperRegistry + +3. **GelatoKeeperCompatible.sol** ✅ + - Gelato Network wrapper + - Task execution pattern + - Compatible with Gelato Ops + +### Scripts (8) + +1. **DeployKeeper.s.sol** ✅ - Deploy core keeper +2. **DeployChainlinkKeeper.s.sol** ✅ - Deploy Chainlink wrapper +3. **DeployGelatoKeeper.s.sol** ✅ - Deploy Gelato wrapper +4. **PerformUpkeep.s.sol** ✅ - Manual upkeep execution +5. **CheckUpkeep.s.sol** ✅ - Check upkeep status +6. **keeper-service.js** ✅ - Node.js keeper service +7. **keeper-service.sh** ✅ - Bash keeper service +8. **deploy-all.sh** ✅ - Complete deployment automation + +### Integration Scripts (3) + +1. **chainlink-keeper-setup.js** ✅ - Chainlink registration +2. **gelato-keeper-setup.js** ✅ - Gelato task creation +3. **monitor-keeper.js** ✅ - Monitoring service + +### Infrastructure (3) + +1. **systemd/price-feed-keeper.service** ✅ - Systemd service file +2. **docker/docker-compose.keeper.yml** ✅ - Docker Compose config +3. **docker/Dockerfile.keeper** ✅ - Docker image + +### Documentation (4) + +1. **KEEPER_SETUP.md** ✅ - Detailed setup guide +2. **KEEPER_COMPLETE.md** ✅ - Completion summary +3. **KEEPER_INTEGRATION_COMPLETE.md** ✅ - Full integration guide +4. **README_KEEPER.md** ✅ - Quick reference guide + +--- + +## Deployment Options + +### Option 1: Quick Deploy (Standalone) + +```bash +# Deploy keeper +forge script script/reserve/DeployKeeper.s.sol:DeployKeeper \ + --rpc-url chain138 --broadcast + +# Start service +export KEEPER_PRIVATE_KEY= +export PRICE_FEED_KEEPER_ADDRESS=
+node scripts/reserve/keeper-service.js +``` + +### Option 2: Complete Deploy (All Options) + +```bash +# Install dependencies +npm install + +# Deploy everything +./scripts/reserve/deploy-all.sh +``` + +### Option 3: Individual Integrations + +**Chainlink**: +```bash +forge script script/reserve/DeployChainlinkKeeper.s.sol:DeployChainlinkKeeper \ + --rpc-url chain138 --broadcast +node scripts/reserve/chainlink-keeper-setup.js +``` + +**Gelato**: +```bash +forge script script/reserve/DeployGelatoKeeper.s.sol:DeployGelatoKeeper \ + --rpc-url chain138 --broadcast +node scripts/reserve/gelato-keeper-setup.js +``` + +**Systemd**: +```bash +sudo cp systemd/price-feed-keeper.service /etc/systemd/system/ +sudo systemctl enable price-feed-keeper +sudo systemctl start price-feed-keeper +``` + +**Docker**: +```bash +docker-compose -f docker/docker-compose.keeper.yml up -d +``` + +--- + +## Monitoring Setup + +### Start Monitor + +```bash +export PRICE_FEED_KEEPER_ADDRESS=
+export ALERT_WEBHOOK= # Optional +node scripts/reserve/monitor-keeper.js +``` + +### Health Checks + +```bash +# Health endpoint +curl http://localhost:3000/health + +# Statistics +curl http://localhost:3000/stats +``` + +--- + +## File Summary + +**Total Files Created**: 20+ + +- **Contracts**: 3 +- **Deployment Scripts**: 5 +- **Service Scripts**: 3 +- **Integration Scripts**: 3 +- **Infrastructure**: 3 +- **Documentation**: 4 + +--- + +## Next Steps + +### Immediate Actions + +1. ✅ **Deploy Keeper Contract** + ```bash + forge script script/reserve/DeployKeeper.s.sol:DeployKeeper --rpc-url chain138 --broadcast + ``` + +2. ✅ **Choose Integration** + - Standalone (simplest) + - Chainlink (decentralized) + - Gelato (cost-effective) + - Systemd (production) + - Docker (containerized) + +3. ✅ **Start Monitoring** + ```bash + node scripts/reserve/monitor-keeper.js + ``` + +### Production Checklist + +- [ ] Deploy keeper contract to ChainID 138 +- [ ] Configure assets to track +- [ ] Set up chosen integration(s) +- [ ] Configure monitoring and alerts +- [ ] Test failure scenarios +- [ ] Set up backup keeper (optional) +- [ ] Document deployment details +- [ ] Set up monitoring dashboards + +--- + +## Status + +✅ **ALL INTEGRATION OPTIONS COMPLETE** + +- ✅ Standalone Service +- ✅ Chainlink Keepers +- ✅ Gelato Network +- ✅ Systemd Service +- ✅ Docker Container +- ✅ Monitoring & Alerting +- ✅ Deployment Automation + +**Ready for production deployment on ChainID 138** + +--- + +## References + +- [KEEPER_SETUP.md](./KEEPER_SETUP.md) - Detailed setup guide +- [KEEPER_INTEGRATION_COMPLETE.md](./KEEPER_INTEGRATION_COMPLETE.md) - Full integration guide +- [README_KEEPER.md](../../README_KEEPER.md) - Quick reference + diff --git a/docs/ccip/archive-import/docs/integration/KEEPER_INTEGRATION_COMPLETE.md b/docs/ccip/archive-import/docs/integration/KEEPER_INTEGRATION_COMPLETE.md new file mode 100644 index 0000000..6ecf7fb --- /dev/null +++ b/docs/ccip/archive-import/docs/integration/KEEPER_INTEGRATION_COMPLETE.md @@ -0,0 +1,497 @@ +# Automated Price Feed Keeper - ALL INTEGRATION OPTIONS COMPLETE ✅ + +**Date**: 2025-01-27 +**Status**: ✅ **ALL INTEGRATIONS COMPLETE** + +--- + +## Summary + +All integration options for the automated price feed keeper have been implemented and are ready for deployment. The system supports multiple deployment and execution methods. + +--- + +## ✅ Integration Options Implemented + +### 1. Standalone Keeper Service ✅ + +**Node.js Service**: `scripts/reserve/keeper-service.js` +- ✅ Automatic price feed updates +- ✅ Retry logic with configurable attempts +- ✅ Error handling and recovery +- ✅ Statistics tracking +- ✅ Graceful shutdown +- ✅ Event parsing and logging + +**Bash Service**: `scripts/reserve/keeper-service.sh` +- ✅ Simple bash implementation +- ✅ Uses Foundry scripts +- ✅ Basic error handling +- ✅ Configurable intervals + +**Usage**: +```bash +# Node.js +node scripts/reserve/keeper-service.js + +# Bash +./scripts/reserve/keeper-service.sh +``` + +--- + +### 2. Chainlink Keepers Integration ✅ + +**Contract**: `ChainlinkKeeperCompatible.sol` +- ✅ Implements `AutomationCompatibleInterface` +- ✅ Wraps `PriceFeedKeeper` for Chainlink Automation +- ✅ Compatible with Chainlink KeeperRegistry + +**Setup Script**: `scripts/reserve/chainlink-keeper-setup.js` +- ✅ Registers upkeep with Chainlink +- ✅ Funds upkeep with LINK +- ✅ Configures gas limits +- ✅ Event parsing + +**Deployment Script**: `script/reserve/DeployChainlinkKeeper.s.sol` +- ✅ Deploys ChainlinkKeeperCompatible contract +- ✅ Links to PriceFeedKeeper + +**Usage**: +```bash +# Deploy compatible contract +forge script script/reserve/DeployChainlinkKeeper.s.sol:DeployChainlinkKeeper \ + --rpc-url chain138 \ + --broadcast + +# Register with Chainlink +node scripts/reserve/chainlink-keeper-setup.js +``` + +--- + +### 3. Gelato Network Integration ✅ + +**Contract**: `GelatoKeeperCompatible.sol` +- ✅ Implements Gelato task execution pattern +- ✅ Wraps `PriceFeedKeeper` for Gelato Network +- ✅ Compatible with Gelato Ops + +**Setup Script**: `scripts/reserve/gelato-keeper-setup.js` +- ✅ Creates task with Gelato +- ✅ Funds task with native token +- ✅ Configures execution interval +- ✅ Event parsing + +**Deployment Script**: `script/reserve/DeployGelatoKeeper.s.sol` +- ✅ Deploys GelatoKeeperCompatible contract +- ✅ Links to PriceFeedKeeper and Gelato Ops + +**Usage**: +```bash +# Deploy compatible contract +forge script script/reserve/DeployGelatoKeeper.s.sol:DeployGelatoKeeper \ + --rpc-url chain138 \ + --broadcast + +# Create task with Gelato +node scripts/reserve/gelato-keeper-setup.js +``` + +--- + +### 4. Systemd Service ✅ + +**Service File**: `systemd/price-feed-keeper.service` +- ✅ Systemd unit file +- ✅ Automatic restart +- ✅ Environment variable support +- ✅ Logging configuration +- ✅ Security hardening +- ✅ Resource limits + +**Usage**: +```bash +# Install service +sudo cp systemd/price-feed-keeper.service /etc/systemd/system/ +sudo systemctl daemon-reload + +# Enable and start +sudo systemctl enable price-feed-keeper +sudo systemctl start price-feed-keeper + +# Check status +sudo systemctl status price-feed-keeper + +# View logs +sudo journalctl -u price-feed-keeper -f +``` + +--- + +### 5. Docker Container ✅ + +**Docker Compose**: `docker/docker-compose.keeper.yml` +- ✅ Keeper service container +- ✅ Monitor service container +- ✅ Health checks +- ✅ Logging configuration +- ✅ Volume mounts +- ✅ Network configuration + +**Dockerfile**: `docker/Dockerfile.keeper` +- ✅ Node.js 18 Alpine base +- ✅ Non-root user +- ✅ Health check endpoint +- ✅ Production optimizations + +**Usage**: +```bash +# Build and start +docker-compose -f docker/docker-compose.keeper.yml up -d + +# View logs +docker-compose -f docker/docker-compose.keeper.yml logs -f + +# Stop +docker-compose -f docker/docker-compose.keeper.yml down +``` + +--- + +### 6. Monitoring and Alerting ✅ + +**Monitor Service**: `scripts/reserve/monitor-keeper.js` +- ✅ Continuous monitoring +- ✅ Stale asset detection +- ✅ Failure tracking +- ✅ Alert threshold configuration +- ✅ Webhook notifications +- ✅ Health endpoint +- ✅ Statistics tracking + +**Features**: +- Monitors keeper performance +- Detects stale assets +- Tracks consecutive failures +- Sends alerts via webhook +- Provides health endpoint +- Tracks statistics + +**Usage**: +```bash +# Start monitor +node scripts/reserve/monitor-keeper.js + +# Health check +curl http://localhost:3000/health + +# Statistics +curl http://localhost:3000/stats +``` + +--- + +### 7. Deployment Automation ✅ + +**Deployment Script**: `scripts/reserve/deploy-all.sh` +- ✅ Complete deployment automation +- ✅ Sequential deployment steps +- ✅ Environment variable management +- ✅ Verification steps +- ✅ Next steps guidance + +**Usage**: +```bash +# Full deployment +./scripts/reserve/deploy-all.sh + +# With Chainlink +DEPLOY_CHAINLINK=true ./scripts/reserve/deploy-all.sh + +# With Gelato +DEPLOY_GELATO=true ./scripts/reserve/deploy-all.sh +``` + +--- + +## Complete File Structure + +``` +contracts/reserve/ +├── PriceFeedKeeper.sol # Core keeper contract +├── ChainlinkKeeperCompatible.sol # Chainlink integration +└── GelatoKeeperCompatible.sol # Gelato integration + +script/reserve/ +├── DeployKeeper.s.sol # Deploy keeper +├── DeployChainlinkKeeper.s.sol # Deploy Chainlink wrapper +├── DeployGelatoKeeper.s.sol # Deploy Gelato wrapper +├── PerformUpkeep.s.sol # Manual upkeep +└── CheckUpkeep.s.sol # Check status + +scripts/reserve/ +├── keeper-service.js # Node.js keeper service +├── keeper-service.sh # Bash keeper service +├── chainlink-keeper-setup.js # Chainlink setup +├── gelato-keeper-setup.js # Gelato setup +├── monitor-keeper.js # Monitoring service +└── deploy-all.sh # Deployment automation + +systemd/ +└── price-feed-keeper.service # Systemd service file + +docker/ +├── docker-compose.keeper.yml # Docker Compose config +└── Dockerfile.keeper # Docker image + +docs/integration/ +├── KEEPER_SETUP.md # Setup guide +├── KEEPER_COMPLETE.md # Completion summary +└── KEEPER_INTEGRATION_COMPLETE.md # This document +``` + +--- + +## Quick Start Guide + +### Option 1: Standalone Service + +```bash +# Deploy keeper +forge script script/reserve/DeployKeeper.s.sol:DeployKeeper \ + --rpc-url chain138 --broadcast + +# Start service +export KEEPER_PRIVATE_KEY= +export PRICE_FEED_KEEPER_ADDRESS=
+node scripts/reserve/keeper-service.js +``` + +### Option 2: Chainlink Keepers + +```bash +# Deploy compatible contract +forge script script/reserve/DeployChainlinkKeeper.s.sol:DeployChainlinkKeeper \ + --rpc-url chain138 --broadcast + +# Register upkeep +export LINK_TOKEN_ADDRESS= +export KEEPER_REGISTRY_ADDRESS= +node scripts/reserve/chainlink-keeper-setup.js +``` + +### Option 3: Gelato Network + +```bash +# Deploy compatible contract +forge script script/reserve/DeployGelatoKeeper.s.sol:DeployGelatoKeeper \ + --rpc-url chain138 --broadcast + +# Create task +export GELATO_OPS= +node scripts/reserve/gelato-keeper-setup.js +``` + +### Option 4: Systemd Service + +```bash +# Install service +sudo cp systemd/price-feed-keeper.service /etc/systemd/system/ +sudo systemctl enable price-feed-keeper +sudo systemctl start price-feed-keeper +``` + +### Option 5: Docker + +```bash +# Start containers +docker-compose -f docker/docker-compose.keeper.yml up -d +``` + +### Option 6: Complete Deployment + +```bash +# Deploy everything +./scripts/reserve/deploy-all.sh +``` + +--- + +## Monitoring Setup + +### Start Monitor Service + +```bash +export PRICE_FEED_KEEPER_ADDRESS=
+export ALERT_WEBHOOK= # Optional +node scripts/reserve/monitor-keeper.js +``` + +### Health Checks + +```bash +# Health endpoint +curl http://localhost:3000/health + +# Statistics +curl http://localhost:3000/stats +``` + +--- + +## Configuration + +### Environment Variables + +**Required**: +- `RPC_URL_138` - ChainID 138 RPC endpoint +- `PRIVATE_KEY` - Deployer private key +- `PRICE_FEED_KEEPER_ADDRESS` - Keeper contract address + +**Keeper Service**: +- `KEEPER_PRIVATE_KEY` - Keeper wallet private key +- `UPDATE_INTERVAL` - Update interval in seconds (default: 30) + +**Chainlink**: +- `KEEPER_REGISTRY_ADDRESS` - Chainlink KeeperRegistry +- `LINK_TOKEN_ADDRESS` - LINK token address +- `UPKEEP_INTERVAL` - Upkeep interval (default: 30) +- `GAS_LIMIT` - Gas limit (default: 500000) +- `FUNDING_AMOUNT` - LINK amount (default: 10) + +**Gelato**: +- `GELATO_OPS` - Gelato Ops address +- `EXECUTION_INTERVAL` - Execution interval (default: 30) +- `FUNDING_AMOUNT` - Native token amount (default: 0.1 ETH) + +**Monitoring**: +- `ALERT_WEBHOOK` - Webhook URL for alerts +- `CHECK_INTERVAL` - Check interval (default: 60) +- `ALERT_THRESHOLD` - Failure threshold (default: 3) + +--- + +## Security Considerations + +### Access Control +- ✅ Role-based access control +- ✅ Keeper role separation +- ✅ Admin role protection + +### Private Key Security +- ✅ Environment variable storage +- ✅ Non-root user in Docker +- ✅ Systemd security hardening + +### Monitoring +- ✅ Failure detection +- ✅ Alert thresholds +- ✅ Health checks + +--- + +## Cost Estimation + +### Standalone Service +- **Gas per update**: ~100k - 300k per asset +- **Updates per day**: 2,880 (30s interval) +- **Cost**: Variable based on gas prices + +### Chainlink Keepers +- **Registration**: ~500k gas +- **Per upkeep**: ~100k - 300k gas +- **LINK funding**: 10 LINK (recommended) +- **Cost**: LINK token + gas + +### Gelato Network +- **Task creation**: ~200k gas +- **Per execution**: ~100k - 300k gas +- **Native funding**: 0.1 ETH (recommended) +- **Cost**: Native token + gas + +--- + +## Next Steps + +### Immediate Actions + +1. ✅ **Deploy Keeper Contract** + ```bash + forge script script/reserve/DeployKeeper.s.sol:DeployKeeper --rpc-url chain138 --broadcast + ``` + +2. ✅ **Choose Integration Option** + - Standalone service (simplest) + - Chainlink Keepers (decentralized) + - Gelato Network (cost-effective) + - Systemd service (production) + - Docker (containerized) + +3. ✅ **Start Monitoring** + ```bash + node scripts/reserve/monitor-keeper.js + ``` + +### Production Checklist + +- [ ] Deploy keeper contract +- [ ] Configure assets to track +- [ ] Set up integration (choose one or multiple) +- [ ] Configure monitoring and alerts +- [ ] Test failure scenarios +- [ ] Set up backup keeper (optional) +- [ ] Document deployment details +- [ ] Set up monitoring dashboards + +--- + +## Support and Troubleshooting + +### Common Issues + +1. **Keeper not updating** + - Check keeper has `KEEPER_ROLE` + - Verify assets are tracked + - Check update interval + - Verify service is running + +2. **Chainlink registration fails** + - Verify LINK balance + - Check KeeperRegistry address + - Verify gas limits + - Check network compatibility + +3. **Gelato task creation fails** + - Verify native token balance + - Check Gelato Ops address + - Verify network compatibility + - Check task parameters + +### Resources + +- [Keeper Setup Guide](./KEEPER_SETUP.md) +- [Price Feed Setup](./PRICE_FEED_SETUP.md) +- [Chainlink Documentation](https://docs.chain.link/chainlink-automation) +- [Gelato Documentation](https://docs.gelato.network) + +--- + +## Conclusion + +All integration options for the automated price feed keeper have been implemented and are ready for deployment. The system provides flexibility to choose the best integration method based on requirements, budget, and infrastructure. + +**Status**: ✅ **ALL INTEGRATIONS COMPLETE - READY FOR PRODUCTION** + +--- + +## Summary + +- ✅ **5 Integration Options**: Standalone, Chainlink, Gelato, Systemd, Docker +- ✅ **Monitoring System**: Complete monitoring and alerting +- ✅ **Deployment Automation**: One-command deployment +- ✅ **Documentation**: Comprehensive guides +- ✅ **Production Ready**: All components tested and documented + +The keeper system is fully integrated and ready for production deployment on ChainID 138. + diff --git a/docs/ccip/archive-import/docs/operations/ADMIN_KEY_MANAGEMENT.md b/docs/ccip/archive-import/docs/operations/ADMIN_KEY_MANAGEMENT.md new file mode 100644 index 0000000..b6888e8 --- /dev/null +++ b/docs/ccip/archive-import/docs/operations/ADMIN_KEY_MANAGEMENT.md @@ -0,0 +1,231 @@ +# Admin Key Management for CCIP Contracts + +**Date**: 2025-01-27 +**Network**: ChainID 138 (DeFi Oracle Meta Mainnet) + +--- + +## Overview + +This document outlines best practices for managing admin keys for CCIP contracts on ChainID 138. + +--- + +## Admin Functions + +### CCIP Router Admin Functions + +- `addSupportedChain(uint64 chainSelector)` +- `removeSupportedChain(uint64 chainSelector)` +- `addSupportedToken(uint64 chainSelector, address token)` +- `updateFees(uint256 baseFee, uint256 dataFeePerByte)` +- `changeAdmin(address newAdmin)` +- `withdrawFees(uint256 amount)` +- `withdrawNativeFees()` + +### Bridge Admin Functions + +- `addDestination(uint64 chainSelector, address receiverBridge)` +- `removeDestination(uint64 chainSelector)` +- `updateDestination(uint64 chainSelector, address receiverBridge)` +- `updateFeeToken(address newFeeToken)` +- `changeAdmin(address newAdmin)` + +--- + +## Key Management Best Practices + +### 1. Key Storage + +**DO**: +- Use hardware wallets (Ledger, Trezor) +- Use secure key management systems (HSM, AWS KMS, Azure Key Vault) +- Store keys in encrypted format +- Use separate keys for different environments (testnet/mainnet) +- Implement key rotation procedures + +**DON'T**: +- Store keys in plain text files +- Commit keys to version control +- Share keys via insecure channels +- Use same key for multiple purposes +- Store keys on shared systems + +### 2. Access Control + +**DO**: +- Implement multi-sig for admin functions +- Use role-based access control +- Require multiple approvals for critical changes +- Log all admin actions +- Monitor for unauthorized access + +**DON'T**: +- Grant admin access to untrusted parties +- Skip approval processes +- Ignore access logs +- Allow unmonitored admin access + +### 3. Key Rotation + +**Procedure**: + +1. **Generate New Key** + - Create new key pair + - Store securely + - Verify key works + +2. **Transfer Admin** + ```bash + cast send $CONTRACT \ + "changeAdmin(address)" \ + $NEW_ADMIN \ + --rpc-url $RPC_URL \ + --private-key $OLD_ADMIN_KEY + ``` + +3. **Verify Transfer** + ```bash + cast call $CONTRACT "admin()" --rpc-url $RPC_URL + ``` + +4. **Revoke Old Key** + - Securely delete old key + - Update documentation + - Notify team + +### 4. Emergency Procedures + +**If Key is Compromised**: + +1. **Immediate Actions**: + - Transfer admin to new secure key + - Review recent transactions + - Check for unauthorized changes + - Notify team and stakeholders + +2. **Investigation**: + - Analyze access logs + - Identify compromise source + - Document incident + +3. **Recovery**: + - Restore from backup if needed + - Revert unauthorized changes + - Implement additional security + +--- + +## Multi-Sig Setup + +### Recommended: Use Multi-Sig Wallet + +For production deployments, use a multi-sig wallet: + +1. **Deploy Multi-Sig** + - Use OpenZeppelin's MultiSigWallet + - Set required confirmations (e.g., 2 of 3) + - Add trusted signers + +2. **Set Multi-Sig as Admin** + ```bash + cast send $CONTRACT \ + "changeAdmin(address)" \ + $MULTISIG_ADDRESS \ + --rpc-url $RPC_URL \ + --private-key $DEPLOYER_KEY + ``` + +3. **Use Multi-Sig for Admin Functions** + - Submit transactions through multi-sig + - Require multiple approvals + - Track all proposals + +--- + +## Key Rotation Schedule + +### Recommended Schedule + +- **Quarterly**: Review key security +- **Annually**: Rotate keys (if no issues) +- **Immediately**: Rotate if compromised +- **After Incidents**: Rotate as part of recovery + +--- + +## Monitoring + +### Monitor Admin Actions + +Track all admin function calls: + +```bash +# Monitor admin changes +cast logs --address $CONTRACT \ + "AdminChanged(address,address)" \ + --rpc-url $RPC_URL + +# Monitor configuration changes +cast logs --address $CONTRACT \ + "DestinationAdded(uint64,address)" \ + --rpc-url $RPC_URL +``` + +### Alerts + +Set up alerts for: +- Admin changes +- Configuration changes +- Unusual admin activity +- Failed admin operations + +--- + +## Documentation + +### Required Documentation + +1. **Key Inventory**: List all admin keys and their purposes +2. **Access Logs**: Maintain logs of all admin actions +3. **Rotation Records**: Document all key rotations +4. **Incident Reports**: Document security incidents + +### Key Information to Document + +- Key purpose (router admin, bridge admin, etc.) +- Key location (hardware wallet, HSM, etc.) +- Key holders (who has access) +- Last rotation date +- Next rotation date + +--- + +## Compliance + +### Audit Requirements + +- Regular security audits +- Key management reviews +- Access control audits +- Incident response reviews + +### Regulatory Considerations + +- Follow industry best practices +- Maintain audit trails +- Implement proper controls +- Document procedures + +--- + +## Related Documentation + +- [CCIP Security Guide](../security/CCIP_SECURITY.md) +- [CCIP Runbooks](CCIP_RUNBOOKS.md) +- [CCIP Monitoring](CCIP_MONITORING.md) + +--- + +**Last Updated**: 2025-01-27 + diff --git a/docs/ccip/archive-import/operations/CCIP_MONITORING.md b/docs/ccip/archive-import/operations/CCIP_MONITORING.md new file mode 100644 index 0000000..0fd091e --- /dev/null +++ b/docs/ccip/archive-import/operations/CCIP_MONITORING.md @@ -0,0 +1,252 @@ +# CCIP Monitoring Guide for ChainID 138 + +**Date**: 2025-01-27 +**Network**: ChainID 138 (DeFi Oracle Meta Mainnet) + +--- + +## Overview + +This guide provides monitoring setup and best practices for CCIP infrastructure on ChainID 138. + +--- + +## Monitoring Components + +### 1. CCIP Router Monitoring + +#### Events to Monitor + +- `MessageSent`: Track all outgoing messages + - Parameters: `messageId`, `destinationChainSelector`, `sender`, `receiver`, `data`, `tokenAmounts`, `feeToken`, `extraArgs` +- `MessageReceived`: Track all incoming messages + - Parameters: `messageId`, `sourceChainSelector`, `sender`, `data`, `tokenAmounts` + +#### Metrics to Track + +- Message volume (sent/received per hour/day) +- Fee collection amounts +- Average message size +- Success/failure rates +- Destination chain distribution + +#### Alerts + +- High message failure rate (>5%) +- Unusual fee collection patterns +- Router contract errors +- Unsupported chain access attempts + +### 2. Bridge Monitoring + +#### Events to Monitor + +**CCIPWETH9Bridge & CCIPWETH10Bridge**: +- `CrossChainTransferInitiated`: Track outgoing transfers + - Parameters: `messageId`, `sender`, `destinationChainSelector`, `recipient`, `amount`, `nonce` +- `CrossChainTransferCompleted`: Track completed transfers + - Parameters: `messageId`, `sourceChainSelector`, `recipient`, `amount` +- `DestinationAdded`: Track configuration changes +- `DestinationRemoved`: Track configuration changes +- `DestinationUpdated`: Track configuration changes + +#### Metrics to Track + +- Transfer volume (amount and count) +- Average transfer size +- Transfer success rate +- Time to completion +- Fee costs per transfer +- Destination chain usage + +#### Alerts + +- Failed transfers +- Stuck transfers (no completion after X hours) +- Unusual transfer patterns +- Configuration changes +- Insufficient fee errors + +--- + +## Monitoring Setup + +### Option 1: Event Logging Script + +Create a script to monitor events: + +```bash +#!/bin/bash +# Monitor CCIP events + +RPC_URL="${RPC_URL_138:-http://localhost:8545}" +ROUTER="${CCIP_CHAIN138_ROUTER:-}" +BRIDGE9="${CCIPWETH9_BRIDGE_CHAIN138:-}" +BRIDGE10="${CCIPWETH10_BRIDGE_CHAIN138:-}" + +# Monitor router events +cast logs --from-block latest \ + --address "$ROUTER" \ + --rpc-url "$RPC_URL" \ + "MessageSent(bytes32,uint64,address,bytes,tuple[],address,bytes)" + +# Monitor bridge events +cast logs --from-block latest \ + --address "$BRIDGE9" \ + --rpc-url "$RPC_URL" \ + "CrossChainTransferInitiated(bytes32,address,uint64,address,uint256,uint256)" +``` + +### Option 2: Prometheus Integration + +Set up Prometheus to scrape CCIP metrics: + +```yaml +# prometheus.yml +scrape_configs: + - job_name: 'ccip-router' + static_configs: + - targets: ['localhost:9545'] + metrics_path: '/metrics' +``` + +### Option 3: Grafana Dashboards + +Create dashboards for: +- Message volume over time +- Transfer amounts and counts +- Fee collection +- Success/failure rates +- Destination chain distribution + +--- + +## Alerting Rules + +### Critical Alerts + +1. **Router Down**: Router contract becomes unresponsive +2. **Bridge Failure**: Bridge fails to process transfers +3. **High Failure Rate**: >10% message/transfer failures +4. **Configuration Change**: Unauthorized configuration changes + +### Warning Alerts + +1. **High Volume**: Unusual message/transfer volume +2. **Fee Anomaly**: Unusual fee collection patterns +3. **Slow Processing**: Messages taking longer than expected + +--- + +## Logging + +### Recommended Log Levels + +- **INFO**: Normal operations (messages sent/received, transfers) +- **WARN**: Recoverable errors, configuration changes +- **ERROR**: Failed operations, contract errors +- **DEBUG**: Detailed operation logs (for troubleshooting) + +### Log Retention + +- **Event Logs**: Retain for 90 days +- **Error Logs**: Retain for 180 days +- **Audit Logs**: Retain for 1 year + +--- + +## Health Checks + +### Router Health Check + +```bash +# Check router is responsive +cast call "$ROUTER" "feeToken()" --rpc-url "$RPC_URL" + +# Check supported chains +cast call "$ROUTER" "supportedChains(uint64)" "5009297550715157269" --rpc-url "$RPC_URL" +``` + +### Bridge Health Check + +```bash +# Check bridge router connection +cast call "$BRIDGE9" "ccipRouter()" --rpc-url "$RPC_URL" + +# Check destinations +cast call "$BRIDGE9" "destinations(uint64)" "5009297550715157269" --rpc-url "$RPC_URL" +``` + +--- + +## Performance Metrics + +### Key Performance Indicators (KPIs) + +1. **Message Throughput**: Messages per second +2. **Transfer Throughput**: Transfers per hour +3. **Average Latency**: Time from send to receive +4. **Success Rate**: Percentage of successful operations +5. **Fee Efficiency**: Average fee per operation + +### Target Metrics + +- Message success rate: >99% +- Average latency: <5 minutes +- Transfer success rate: >99.5% +- System uptime: >99.9% + +--- + +## Incident Response + +### Escalation Procedures + +1. **Level 1**: Automated alerts → On-call engineer +2. **Level 2**: Critical failures → Team lead +3. **Level 3**: System-wide issues → CTO/Management + +### Response Playbook + +1. **Router Failure**: + - Check contract status + - Verify RPC connectivity + - Review recent transactions + - Check for configuration changes + +2. **Bridge Failure**: + - Verify router connectivity + - Check destination configuration + - Review transfer logs + - Verify fee payment + +3. **High Failure Rate**: + - Analyze failure patterns + - Check network conditions + - Review recent changes + - Escalate if needed + +--- + +## Monitoring Tools + +### Recommended Tools + +- **Prometheus**: Metrics collection +- **Grafana**: Visualization and dashboards +- **ELK Stack**: Log aggregation +- **PagerDuty**: Alerting and on-call +- **Custom Scripts**: Event monitoring + +--- + +## Related Documentation + +- [CCIP Deployment Guide](../ccip/DEPLOYMENT_GUIDE_CHAIN138.md) +- [CCIP Review](../CCIP_CHAIN138_REVIEW.md) +- [Operations Runbooks](CCIP_RUNBOOKS.md) + +--- + +**Last Updated**: 2025-01-27 + diff --git a/docs/ccip/archive-import/operations/CCIP_RUNBOOKS.md b/docs/ccip/archive-import/operations/CCIP_RUNBOOKS.md new file mode 100644 index 0000000..4dd2d20 --- /dev/null +++ b/docs/ccip/archive-import/operations/CCIP_RUNBOOKS.md @@ -0,0 +1,367 @@ +# CCIP Operational Runbooks for ChainID 138 + +**Date**: 2025-01-27 +**Network**: ChainID 138 (DeFi Oracle Meta Mainnet) + +--- + +## Overview + +This document provides operational runbooks for common CCIP operations, troubleshooting, and emergency procedures. + +--- + +## Table of Contents + +1. [Deployment Runbook](#deployment-runbook) +2. [Configuration Runbook](#configuration-runbook) +3. [Troubleshooting Guide](#troubleshooting-guide) +4. [Emergency Response](#emergency-response) + +--- + +## Deployment Runbook + +### Prerequisites Check + +```bash +# 1. Verify network connectivity +cast block-number --rpc-url $RPC_URL_138 + +# 2. Verify account balance +cast balance $DEPLOYER_ADDRESS --rpc-url $RPC_URL_138 + +# 3. Verify environment variables +grep -E "CCIP_CHAIN138|CHAIN138_SELECTOR" .env +``` + +### Deployment Steps + +1. **Calculate Chain Selector** + ```bash + ./scripts/ccip/calculate-chain-selector.sh + ``` + +2. **Deploy CCIP Router** + ```bash + forge script script/DeployCCIPRouter.s.sol \ + --rpc-url $RPC_URL_138 \ + --broadcast \ + --private-key $PRIVATE_KEY + ``` + +3. **Configure Router** + ```bash + ./scripts/deployment/configure-ccip-router.sh + ``` + +4. **Deploy Bridges** + ```bash + forge script script/DeployCCIPWETH9Bridge.s.sol \ + --rpc-url $RPC_URL_138 \ + --broadcast \ + --private-key $PRIVATE_KEY + + forge script script/DeployCCIPWETH10Bridge.s.sol \ + --rpc-url $RPC_URL_138 \ + --broadcast \ + --private-key $PRIVATE_KEY + ``` + +5. **Configure Bridges** + ```bash + ./scripts/deployment/configure-weth9-bridge.sh + ./scripts/deployment/configure-weth10-bridge.sh + ``` + +6. **Verify Deployment** + ```bash + ./scripts/deployment/verify-ccip-deployment.sh + ``` + +--- + +## Configuration Runbook + +### Adding a New Destination Chain + +1. **Get Chain Selector** + - Look up selector from Chainlink docs or calculate + +2. **Add to Router** + ```bash + cast send $CCIP_CHAIN138_ROUTER \ + "addSupportedChain(uint64)" \ + $DESTINATION_SELECTOR \ + --rpc-url $RPC_URL_138 \ + --private-key $PRIVATE_KEY + ``` + +3. **Add Supported Tokens** + ```bash + cast send $CCIP_CHAIN138_ROUTER \ + "addSupportedToken(uint64,address)" \ + $DESTINATION_SELECTOR \ + $TOKEN_ADDRESS \ + --rpc-url $RPC_URL_138 \ + --private-key $PRIVATE_KEY + ``` + +4. **Configure Bridge** + ```bash + cast send $BRIDGE_ADDRESS \ + "addDestination(uint64,address)" \ + $DESTINATION_SELECTOR \ + $DESTINATION_BRIDGE_ADDRESS \ + --rpc-url $RPC_URL_138 \ + --private-key $PRIVATE_KEY + ``` + +### Updating Fee Configuration + +```bash +cast send $CCIP_CHAIN138_ROUTER \ + "updateFees(uint256,uint256)" \ + $NEW_BASE_FEE \ + $NEW_DATA_FEE_PER_BYTE \ + --rpc-url $RPC_URL_138 \ + --private-key $PRIVATE_KEY +``` + +### Changing Admin + +```bash +# Router +cast send $CCIP_CHAIN138_ROUTER \ + "changeAdmin(address)" \ + $NEW_ADMIN \ + --rpc-url $RPC_URL_138 \ + --private-key $PRIVATE_KEY + +# Bridge +cast send $BRIDGE_ADDRESS \ + "changeAdmin(address)" \ + $NEW_ADMIN \ + --rpc-url $RPC_URL_138 \ + --private-key $PRIVATE_KEY +``` + +--- + +## Troubleshooting Guide + +### Issue: Router Not Responding + +**Symptoms**: +- Cannot send messages +- Contract calls fail + +**Diagnosis**: +```bash +# Check contract code +cast code $CCIP_CHAIN138_ROUTER --rpc-url $RPC_URL_138 + +# Check recent transactions +cast tx $LAST_TX_HASH --rpc-url $RPC_URL_138 +``` + +**Solutions**: +1. Verify RPC connectivity +2. Check contract is deployed +3. Verify network is synced +4. Check for contract upgrades + +### Issue: Bridge Transfer Fails + +**Symptoms**: +- Transfer initiated but not completed +- Error messages in logs + +**Diagnosis**: +```bash +# Check bridge configuration +cast call $BRIDGE "destinations(uint64)" $DEST_SELECTOR --rpc-url $RPC_URL_138 + +# Check router connection +cast call $BRIDGE "ccipRouter()" --rpc-url $RPC_URL_138 + +# Check message status +cast logs --address $BRIDGE "CrossChainTransferInitiated" --rpc-url $RPC_URL_138 +``` + +**Solutions**: +1. Verify destination is configured +2. Check router is accessible +3. Verify sufficient fees +4. Check destination chain status + +### Issue: High Failure Rate + +**Symptoms**: +- Many failed messages/transfers +- Error events in logs + +**Diagnosis**: +```bash +# Analyze failure patterns +cast logs --address $ROUTER "MessageSent" --rpc-url $RPC_URL_138 | grep -i error + +# Check fee configuration +cast call $ROUTER "baseFee()" --rpc-url $RPC_URL_138 +``` + +**Solutions**: +1. Review error logs +2. Check fee configuration +3. Verify destination chains +4. Check network conditions + +### Issue: Configuration Changes Not Applied + +**Symptoms**: +- Configuration calls succeed but changes not visible + +**Diagnosis**: +```bash +# Verify current configuration +cast call $CONTRACT "destinations(uint64)" $SELECTOR --rpc-url $RPC_URL_138 + +# Check transaction status +cast tx $TX_HASH --rpc-url $RPC_URL_138 +``` + +**Solutions**: +1. Verify transaction was mined +2. Check correct contract address +3. Verify admin permissions +4. Check for event emissions + +--- + +## Emergency Response + +### Emergency Pause (if implemented) + +If contracts have pause functionality: + +```bash +# Pause router (if function exists) +cast send $ROUTER "pause()" --rpc-url $RPC_URL_138 --private-key $PRIVATE_KEY + +# Pause bridge +cast send $BRIDGE "pause()" --rpc-url $RPC_URL_138 --private-key $PRIVATE_KEY +``` + +### Disable Destination Chain + +```bash +# Remove destination from bridge +cast send $BRIDGE \ + "removeDestination(uint64)" \ + $PROBLEMATIC_SELECTOR \ + --rpc-url $RPC_URL_138 \ + --private-key $PRIVATE_KEY + +# Remove from router +cast send $ROUTER \ + "removeSupportedChain(uint64)" \ + $PROBLEMATIC_SELECTOR \ + --rpc-url $RPC_URL_138 \ + --private-key $PRIVATE_KEY +``` + +### Withdraw Fees (Emergency) + +```bash +# Withdraw native ETH fees +cast send $ROUTER \ + "withdrawNativeFees()" \ + --rpc-url $RPC_URL_138 \ + --private-key $PRIVATE_KEY + +# Withdraw ERC20 fees +cast send $ROUTER \ + "withdrawFees(uint256)" \ + $AMOUNT \ + --rpc-url $RPC_URL_138 \ + --private-key $PRIVATE_KEY +``` + +### Incident Response Checklist + +1. **Identify Issue** + - Check monitoring alerts + - Review recent logs + - Verify contract status + +2. **Assess Impact** + - How many users affected? + - What operations are failing? + - Is data at risk? + +3. **Contain Issue** + - Disable affected destinations + - Pause operations if needed + - Notify stakeholders + +4. **Resolve Issue** + - Apply fixes + - Verify resolution + - Monitor for recurrence + +5. **Post-Incident** + - Document incident + - Review root cause + - Update procedures + +--- + +## Common Operations + +### Check Contract Status + +```bash +# Router status +cast call $ROUTER "feeToken()" --rpc-url $RPC_URL_138 +cast call $ROUTER "baseFee()" --rpc-url $RPC_URL_138 +cast call $ROUTER "supportedChains(uint64)" $SELECTOR --rpc-url $RPC_URL_138 + +# Bridge status +cast call $BRIDGE "ccipRouter()" --rpc-url $RPC_URL_138 +cast call $BRIDGE "destinations(uint64)" $SELECTOR --rpc-url $RPC_URL_138 +cast call $BRIDGE "getDestinationChains()" --rpc-url $RPC_URL_138 +``` + +### View Recent Events + +```bash +# Router events +cast logs --address $ROUTER --from-block latest --rpc-url $RPC_URL_138 + +# Bridge events +cast logs --address $BRIDGE --from-block latest --rpc-url $RPC_URL_138 +``` + +### Calculate Fees + +```bash +# Estimate fee for message +cast call $ROUTER \ + "getFee(uint64,tuple)" \ + $DEST_SELECTOR \ + $MESSAGE \ + --rpc-url $RPC_URL_138 +``` + +--- + +## Related Documentation + +- [CCIP Deployment Guide](../ccip/DEPLOYMENT_GUIDE_CHAIN138.md) +- [CCIP Monitoring](CCIP_MONITORING.md) +- [CCIP Review](../CCIP_CHAIN138_REVIEW.md) + +--- + +**Last Updated**: 2025-01-27 + diff --git a/docs/ccip/archive-import/security/CCIP_SECURITY.md b/docs/ccip/archive-import/security/CCIP_SECURITY.md new file mode 100644 index 0000000..d90eea1 --- /dev/null +++ b/docs/ccip/archive-import/security/CCIP_SECURITY.md @@ -0,0 +1,256 @@ +# CCIP Security Guide for ChainID 138 + +**Date**: 2025-01-27 +**Network**: ChainID 138 (DeFi Oracle Meta Mainnet) + +--- + +## Overview + +This document outlines security measures, best practices, and audit considerations for CCIP infrastructure on ChainID 138. + +--- + +## Security Architecture + +### Access Control + +#### Admin Functions + +All CCIP contracts implement admin-only functions: + +- **Router**: `addSupportedChain()`, `removeSupportedChain()`, `updateFees()`, `changeAdmin()` +- **Bridges**: `addDestination()`, `removeDestination()`, `updateDestination()`, `changeAdmin()` + +**Security Measures**: +- Admin address is set at deployment +- Only admin can modify configuration +- Admin can be transferred (with proper verification) + +#### Oracle Functions + +- **CCIPSender**: Only oracle aggregator can send updates +- **CCIPReceiver**: Only router can call `ccipReceive()` + +### Replay Protection + +#### Message Replay Protection + +- **Message ID Tracking**: Each message has unique ID +- **Processed Messages Mapping**: Prevents duplicate processing +- **Nonce Tracking**: Per-user nonces for additional protection + +#### Transfer Replay Protection + +- **Message ID Validation**: Checks if transfer already processed +- **Nonce Validation**: Ensures ordered processing +- **Source Chain Validation**: Verifies message source + +--- + +## Security Best Practices + +### 1. Admin Key Management + +**DO**: +- Use hardware wallets for admin keys +- Implement multi-sig for admin functions +- Store keys securely (HSM, secure enclave) +- Rotate keys periodically +- Use separate keys for different functions + +**DON'T**: +- Store private keys in plain text +- Use same key for multiple purposes +- Share admin keys +- Leave keys in version control + +### 2. Configuration Security + +**DO**: +- Verify all configuration changes +- Use testnet for testing changes +- Document all configuration changes +- Review changes before applying +- Monitor for unauthorized changes + +**DON'T**: +- Make changes without verification +- Skip testing on testnet +- Allow unverified addresses +- Ignore configuration change events + +### 3. Fee Management + +**DO**: +- Monitor fee collection +- Set appropriate fee levels +- Withdraw fees regularly +- Document fee changes +- Alert on unusual patterns + +**DON'T**: +- Set fees too low (risk of spam) +- Set fees too high (user impact) +- Ignore fee anomalies +- Leave fees uncollected + +### 4. Destination Chain Security + +**DO**: +- Verify destination chain selectors +- Validate receiver addresses +- Test destinations before enabling +- Monitor destination chain status +- Disable problematic destinations + +**DON'T**: +- Add unverified destinations +- Use placeholder addresses +- Skip destination validation +- Ignore destination errors + +--- + +## Common Vulnerabilities + +### 1. Reentrancy + +**Protection**: +- Contracts use checks-effects-interactions pattern +- No external calls before state updates +- Replay protection prevents duplicate processing + +### 2. Access Control + +**Protection**: +- Admin-only modifiers on sensitive functions +- Router-only modifier on `ccipReceive()` +- Aggregator-only modifier on sender functions + +### 3. Integer Overflow/Underflow + +**Protection**: +- Solidity 0.8.19 has built-in overflow protection +- Safe math operations +- Input validation + +### 4. Front-running + +**Protection**: +- Nonce-based ordering +- Message ID uniqueness +- Transaction ordering protection (network-level) + +--- + +## Audit Checklist + +### Contract Security + +- [ ] Access control properly implemented +- [ ] Replay protection in place +- [ ] Input validation on all functions +- [ ] Error handling comprehensive +- [ ] No reentrancy vulnerabilities +- [ ] Integer overflow protection +- [ ] Event emissions for all state changes + +### Configuration Security + +- [ ] Admin key management secure +- [ ] Configuration change procedures documented +- [ ] Emergency procedures in place +- [ ] Monitoring and alerting configured +- [ ] Access logs maintained + +### Operational Security + +- [ ] Deployment procedures documented +- [ ] Testing procedures in place +- [ ] Incident response plan ready +- [ ] Backup and recovery procedures +- [ ] Regular security reviews scheduled + +--- + +## Security Monitoring + +### Events to Monitor + +1. **Configuration Changes** + - `DestinationAdded` + - `DestinationRemoved` + - `DestinationUpdated` + - `AdminChanged` + +2. **Unusual Activity** + - High volume of failed messages + - Unusual fee patterns + - Configuration changes outside business hours + - Access from unknown addresses + +### Alerts + +- **Critical**: Unauthorized configuration changes +- **High**: High failure rate +- **Medium**: Unusual activity patterns +- **Low**: Configuration changes (informational) + +--- + +## Incident Response + +### Security Incident Types + +1. **Unauthorized Access** + - Detect: Monitor admin function calls + - Respond: Revoke access, investigate + - Recover: Restore from backup if needed + +2. **Configuration Tampering** + - Detect: Monitor configuration events + - Respond: Revert changes, investigate + - Recover: Restore correct configuration + +3. **Exploit Attempt** + - Detect: Monitor for unusual patterns + - Respond: Disable affected functions + - Recover: Patch and redeploy if needed + +### Response Procedures + +1. **Immediate**: Contain the threat +2. **Short-term**: Investigate and document +3. **Long-term**: Implement fixes and improvements + +--- + +## Compliance + +### Documentation Requirements + +- Security architecture documentation +- Access control procedures +- Incident response procedures +- Audit logs and records + +### Regular Reviews + +- Quarterly security reviews +- Annual comprehensive audits +- Post-incident reviews +- Configuration change reviews + +--- + +## Related Documentation + +- [CCIP Deployment Guide](../ccip/DEPLOYMENT_GUIDE_CHAIN138.md) +- [CCIP Monitoring](../operations/CCIP_MONITORING.md) +- [CCIP Runbooks](../operations/CCIP_RUNBOOKS.md) + +--- + +**Last Updated**: 2025-01-27 + diff --git a/docs/ccip/archive-import/user-guides/CCIP_BRIDGE_USER_GUIDE.md b/docs/ccip/archive-import/user-guides/CCIP_BRIDGE_USER_GUIDE.md new file mode 100644 index 0000000..b2b0621 --- /dev/null +++ b/docs/ccip/archive-import/user-guides/CCIP_BRIDGE_USER_GUIDE.md @@ -0,0 +1,282 @@ +# CCIP Bridge User Guide + +**Date**: 2025-01-27 +**Network**: ChainID 138 (DeFi Oracle Meta Mainnet) + +--- + +## Overview + +This guide explains how to use the CCIP bridges to transfer WETH9 and WETH10 tokens between ChainID 138 and other supported chains. + +--- + +## Prerequisites + +- Wallet connected to ChainID 138 +- WETH9 or WETH10 tokens in your wallet +- LINK tokens (if using LINK for fees) or native ETH (if using native fees) +- Sufficient balance for gas fees + +--- + +## Bridge Addresses + +### ChainID 138 + +- **CCIPWETH9Bridge**: See `.env` or documentation for deployed address +- **CCIPWETH10Bridge**: See `.env` or documentation for deployed address + +### Ethereum Mainnet + +- **CCIPWETH9Bridge**: `0x3304b747E565a97ec8AC220b0B6A1f6ffDB837e6` +- **CCIPWETH10Bridge**: `0x8078A09637e47Fa5Ed34F626046Ea2094a5CDE5e` + +--- + +## Step-by-Step Guide + +### Step 1: Prepare Tokens + +#### Option A: You have native ETH + +Wrap ETH to WETH: + +```solidity +// For WETH9 +weth9.deposit{value: amount}(); + +// For WETH10 +weth10.deposit{value: amount}(); +``` + +#### Option B: You already have WETH + +Ensure you have sufficient WETH balance. + +### Step 2: Approve Bridge + +Approve the bridge to spend your tokens: + +```solidity +// For WETH9 +weth9.approve(bridgeAddress, amount); + +// For WETH10 +weth10.approve(bridgeAddress, amount); +``` + +### Step 3: Calculate Fees + +Estimate the CCIP fee: + +```solidity +uint256 fee = bridge.calculateFee(destinationChainSelector, amount); +``` + +### Step 4: Approve Fee Token + +If using LINK for fees: + +```solidity +linkToken.approve(bridgeAddress, fee); +``` + +If using native ETH, ensure you have sufficient balance. + +### Step 5: Send Cross-Chain + +Send tokens to destination chain: + +```solidity +bytes32 messageId = bridge.sendCrossChain( + destinationChainSelector, // e.g., 5009297550715157269 for Ethereum Mainnet + recipientAddress, // Address on destination chain + amount // Amount to transfer +); +``` + +### Step 6: Monitor Transfer + +Track the transfer using the `messageId`: + +- Check events: `CrossChainTransferInitiated` +- Wait for confirmation on destination chain +- Check events: `CrossChainTransferCompleted` + +--- + +## Example: Transfer WETH9 from ChainID 138 to Ethereum Mainnet + +```solidity +// 1. Wrap ETH to WETH9 +weth9.deposit{value: 1 ether}(); + +// 2. Approve bridge +weth9.approve(bridgeAddress, 1 ether); + +// 3. Calculate fee +uint256 fee = bridge.calculateFee(5009297550715157269, 1 ether); + +// 4. Approve fee (if using LINK) +linkToken.approve(bridgeAddress, fee); + +// 5. Send cross-chain +bytes32 messageId = bridge.sendCrossChain( + 5009297550715157269, // Ethereum Mainnet selector + recipientAddress, // Your address on Ethereum Mainnet + 1 ether +); + +// 6. Monitor transfer +// Check events or use messageId to track +``` + +--- + +## Using with Web3 Libraries + +### ethers.js + +```javascript +const bridge = new ethers.Contract(bridgeAddress, bridgeABI, signer); + +// Approve +await weth9.approve(bridgeAddress, amount); + +// Calculate fee +const fee = await bridge.calculateFee(destinationSelector, amount); + +// Approve fee token (if LINK) +await linkToken.approve(bridgeAddress, fee); + +// Send cross-chain +const tx = await bridge.sendCrossChain( + destinationSelector, + recipientAddress, + amount +); +const receipt = await tx.wait(); +const messageId = receipt.events.find(e => e.event === 'CrossChainTransferInitiated').args.messageId; +``` + +### web3.js + +```javascript +// Approve +await weth9.methods.approve(bridgeAddress, amount).send({ from: account }); + +// Calculate fee +const fee = await bridge.methods.calculateFee(destinationSelector, amount).call(); + +// Approve fee token (if LINK) +await linkToken.methods.approve(bridgeAddress, fee).send({ from: account }); + +// Send cross-chain +const tx = await bridge.methods.sendCrossChain( + destinationSelector, + recipientAddress, + amount +).send({ from: account }); +``` + +--- + +## Supported Destination Chains + +| Network | Chain ID | Chain Selector | +|---------|----------|---------------| +| Ethereum Mainnet | 1 | `5009297550715157269` | +| BSC | 56 | `11344663589394136015` | +| Polygon | 137 | `4051577828743386545` | +| Avalanche | 43114 | `6433500567565415381` | +| Base | 8453 | `15971525489660198786` | +| Arbitrum | 42161 | `4949039107694359620` | +| Optimism | 10 | `3734403246176062136` | + +--- + +## Fees + +### Fee Structure + +- **Base Fee**: Fixed fee per message +- **Data Fee**: Fee per byte of message data +- **Token Fee**: Percentage of token amount (if applicable) + +### Fee Payment + +- **Native ETH**: Fees paid in native token (if configured) +- **LINK Token**: Fees paid in LINK token (if configured) + +### Estimating Fees + +Always calculate fees before sending: + +```solidity +uint256 fee = bridge.calculateFee(destinationSelector, amount); +``` + +--- + +## Troubleshooting + +### Issue: Transfer Fails + +**Possible Causes**: +- Insufficient token balance +- Insufficient fee balance +- Destination not configured +- Invalid recipient address + +**Solutions**: +1. Check token and fee balances +2. Verify destination is enabled +3. Verify recipient address is valid +4. Check recent bridge events + +### Issue: Transfer Stuck + +**Possible Causes**: +- Destination chain issues +- Router problems +- Network congestion + +**Solutions**: +1. Check destination chain status +2. Monitor bridge events +3. Contact support if persistent + +### Issue: High Fees + +**Possible Causes**: +- Large transfer amount +- Network congestion +- Fee configuration + +**Solutions**: +1. Check fee calculation +2. Consider smaller amounts +3. Wait for lower network activity + +--- + +## Security Considerations + +1. **Verify Addresses**: Always verify bridge and token addresses +2. **Check Fees**: Verify fee calculations before sending +3. **Monitor Transfers**: Track your transfers using messageId +4. **Use Official Sources**: Only use addresses from official documentation + +--- + +## Related Documentation + +- [CCIP Deployment Guide](../ccip/DEPLOYMENT_GUIDE_CHAIN138.md) +- [CCIP Review](../CCIP_CHAIN138_REVIEW.md) +- [Main Guide](../ETH_WETH_CHAINLINK_GUIDE.md) + +--- + +**Last Updated**: 2025-01-27 + diff --git a/script/DeployCCIPLoggerChain138.s.sol b/script/DeployCCIPLoggerChain138.s.sol new file mode 100644 index 0000000..cbffc2b --- /dev/null +++ b/script/DeployCCIPLoggerChain138.s.sol @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {Script, console} from "forge-std/Script.sol"; + +/** + * @title DeployCCIPLoggerChain138 - Deploy CCIPLogger to ChainID 138 + * @notice This script deploys CCIPLogger to ChainID 138 + * @dev CCIPLogger logs CCIP messages for monitoring and debugging + */ +contract DeployCCIPLoggerChain138 is Script { + uint256 constant CHAIN138 = 138; + + function run() external { + uint256 chainId = block.chainid; + require(chainId == CHAIN138, "This script is only for ChainID 138"); + + uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + address deployer = vm.addr(deployerPrivateKey); + + // Load CCIP Router address + address ccipRouter = vm.envAddress("CCIP_ROUTER_ADDRESS"); + require(ccipRouter != address(0), "CCIP_ROUTER_ADDRESS not set"); + + console.log("=========================================="); + console.log("CCIPLogger Deployment - ChainID 138"); + console.log("=========================================="); + console.log("Chain ID:", chainId); + console.log("Deployer:", deployer); + console.log("Deployer Balance:", deployer.balance / 1e18, "ETH"); + console.log("CCIP Router:", ccipRouter); + console.log(""); + + vm.startBroadcast(deployerPrivateKey); + + // Note: CCIPLogger contract needs to be available + // If CCIPLogger.sol doesn't exist, this will fail at compilation + // For now, we'll create a simple logger contract inline + + // Deploy a simple CCIP Logger contract + CCIPLogger logger = new CCIPLogger(ccipRouter); + + console.log("CCIPLogger deployed at:", address(logger)); + console.log("CCIP Router:", ccipRouter); + + vm.stopBroadcast(); + + console.log("\n=== Deployment Summary ==="); + console.log("CCIPLogger:", address(logger)); + console.log("CCIP Router:", ccipRouter); + } +} + +// Simple CCIP Logger contract +contract CCIPLogger { + address public immutable router; + + event MessageLogged( + bytes32 indexed messageId, + uint64 indexed sourceChainSelector, + address sender, + bytes data, + uint256 timestamp + ); + + constructor(address _router) { + require(_router != address(0), "CCIPLogger: zero router"); + router = _router; + } + + function logMessage( + bytes32 messageId, + uint64 sourceChainSelector, + address sender, + bytes calldata data + ) external { + emit MessageLogged(messageId, sourceChainSelector, sender, data, block.timestamp); + } +} + diff --git a/script/DeployGovernanceToken.s.sol b/script/DeployGovernanceToken.s.sol new file mode 100644 index 0000000..7295393 --- /dev/null +++ b/script/DeployGovernanceToken.s.sol @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {Script} from "forge-std/Script.sol"; +import {console} from "forge-std/console.sol"; +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; +import "@openzeppelin/contracts/security/Pausable.sol"; + +/** + * @title Governance Token + * @notice ERC20 token for DAO governance and protocol incentives + * @dev Supports minting for rewards and burning for deflation + */ +contract GovernanceToken is ERC20, Ownable, Pausable { + uint256 public constant MAX_SUPPLY = 1_000_000_000 * 10**18; // 1 billion tokens + uint256 public totalMinted; + + constructor( + address initialOwner, + string memory name, + string memory symbol + ) ERC20(name, symbol) { + _transferOwnership(initialOwner); + } + + /** + * @notice Mint new tokens (only owner) + * @param to Address to mint to + * @param amount Amount to mint + */ + function mint(address to, uint256 amount) external onlyOwner { + require(totalMinted + amount <= MAX_SUPPLY, "GovernanceToken: exceeds max supply"); + totalMinted += amount; + _mint(to, amount); + } + + /** + * @notice Burn tokens from caller + * @param amount Amount to burn + */ + function burn(uint256 amount) external { + _burn(msg.sender, amount); + } + + /** + * @notice Burn tokens from specified address (only owner) + * @param from Address to burn from + * @param amount Amount to burn + */ + function burnFrom(address from, uint256 amount) external onlyOwner { + _burn(from, amount); + } + + /** + * @notice Pause token transfers (only owner) + */ + function pause() external onlyOwner { + _pause(); + } + + /** + * @notice Unpause token transfers (only owner) + */ + function unpause() external onlyOwner { + _unpause(); + } + + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal override whenNotPaused { + super._beforeTokenTransfer(from, to, amount); + } +} + +/** + * @title DeployGovernanceToken + * @notice Deployment script for governance token + */ +contract DeployGovernanceToken is Script { + function run() external { + address deployer = msg.sender; + address owner = vm.envOr("GOV_TOKEN_OWNER", deployer); + string memory name = vm.envOr("GOV_TOKEN_NAME", string("DBIS Token")); + string memory symbol = vm.envOr("GOV_TOKEN_SYMBOL", string("DBIS")); + uint256 initialSupply = vm.envOr("GOV_TOKEN_INITIAL_SUPPLY", uint256(0)); + + console.log("Deploying Governance Token..."); + console.log("Deployer:", vm.toString(deployer)); + console.log("Owner:", vm.toString(owner)); + console.log("Name:", name); + console.log("Symbol:", symbol); + console.log("Initial Supply:", initialSupply); + + vm.startBroadcast(); + + GovernanceToken token = new GovernanceToken(owner, name, symbol); + + if (initialSupply > 0) { + token.mint(owner, initialSupply); + } + + vm.stopBroadcast(); + + console.log("Governance Token deployed at:", vm.toString(address(token))); + console.log("Name:", token.name()); + console.log("Symbol:", token.symbol()); + console.log("Decimals:", token.decimals()); + console.log("Total Supply:", token.totalSupply()); + console.log("Max Supply:", token.MAX_SUPPLY()); + } +} + diff --git a/script/DeployUSDC.s.sol b/script/DeployUSDC.s.sol new file mode 100644 index 0000000..6efa4c8 --- /dev/null +++ b/script/DeployUSDC.s.sol @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {Script} from "forge-std/Script.sol"; +import {console} from "forge-std/console.sol"; +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; +import "@openzeppelin/contracts/security/Pausable.sol"; + +/** + * @title Standard USDC Token + * @notice ERC20 token with pausable and ownable features + * @dev Can be used as native USDC or wrapped USDC depending on deployment strategy + */ +contract StandardUSDC is ERC20, Ownable, Pausable { + uint8 private constant DECIMALS = 6; // USDC standard decimals + + constructor( + address initialOwner, + uint256 initialSupply + ) ERC20("USD Coin", "USDC") { + _transferOwnership(initialOwner); + if (initialSupply > 0) { + _mint(initialOwner, initialSupply); + } + } + + function decimals() public pure override returns (uint8) { + return DECIMALS; + } + + /** + * @notice Mint new tokens (only owner) + * @param to Address to mint to + * @param amount Amount to mint + */ + function mint(address to, uint256 amount) external onlyOwner { + _mint(to, amount); + } + + /** + * @notice Burn tokens (only owner) + * @param from Address to burn from + * @param amount Amount to burn + */ + function burn(address from, uint256 amount) external onlyOwner { + _burn(from, amount); + } + + /** + * @notice Pause token transfers (only owner) + */ + function pause() external onlyOwner { + _pause(); + } + + /** + * @notice Unpause token transfers (only owner) + */ + function unpause() external onlyOwner { + _unpause(); + } + + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal override whenNotPaused { + super._beforeTokenTransfer(from, to, amount); + } +} + +/** + * @title DeployUSDC + * @notice Deployment script for USDC token + */ +contract DeployUSDC is Script { + function run() external { + address deployer = msg.sender; + address owner = vm.envOr("USDC_OWNER", deployer); + uint256 initialSupply = vm.envOr("USDC_INITIAL_SUPPLY", uint256(0)); + + console.log("Deploying USDC Token..."); + console.log("Deployer:", vm.toString(deployer)); + console.log("Owner:", vm.toString(owner)); + console.log("Initial Supply:", initialSupply); + + vm.startBroadcast(); + + StandardUSDC usdc = new StandardUSDC(owner, initialSupply); + + vm.stopBroadcast(); + + console.log("USDC Token deployed at:", vm.toString(address(usdc))); + console.log("Name:", usdc.name()); + console.log("Symbol:", usdc.symbol()); + console.log("Decimals:", usdc.decimals()); + console.log("Total Supply:", usdc.totalSupply()); + } +} + diff --git a/script/DeployUSDT.s.sol b/script/DeployUSDT.s.sol new file mode 100644 index 0000000..08afbcc --- /dev/null +++ b/script/DeployUSDT.s.sol @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {Script} from "forge-std/Script.sol"; +import {console} from "forge-std/console.sol"; +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; +import "@openzeppelin/contracts/security/Pausable.sol"; + +/** + * @title Standard USDT Token + * @notice ERC20 token with pausable and ownable features + * @dev Can be used as native USDT or wrapped USDT depending on deployment strategy + */ +contract StandardUSDT is ERC20, Ownable, Pausable { + uint8 private constant DECIMALS = 6; // USDT standard decimals + + constructor( + address initialOwner, + uint256 initialSupply + ) ERC20("Tether USD", "USDT") { + _transferOwnership(initialOwner); + if (initialSupply > 0) { + _mint(initialOwner, initialSupply); + } + } + + function decimals() public pure override returns (uint8) { + return DECIMALS; + } + + /** + * @notice Mint new tokens (only owner) + * @param to Address to mint to + * @param amount Amount to mint + */ + function mint(address to, uint256 amount) external onlyOwner { + _mint(to, amount); + } + + /** + * @notice Burn tokens (only owner) + * @param from Address to burn from + * @param amount Amount to burn + */ + function burn(address from, uint256 amount) external onlyOwner { + _burn(from, amount); + } + + /** + * @notice Pause token transfers (only owner) + */ + function pause() external onlyOwner { + _pause(); + } + + /** + * @notice Unpause token transfers (only owner) + */ + function unpause() external onlyOwner { + _unpause(); + } + + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal override whenNotPaused { + super._beforeTokenTransfer(from, to, amount); + } +} + +/** + * @title DeployUSDT + * @notice Deployment script for USDT token + */ +contract DeployUSDT is Script { + function run() external { + address deployer = msg.sender; + address owner = vm.envOr("USDT_OWNER", deployer); + uint256 initialSupply = vm.envOr("USDT_INITIAL_SUPPLY", uint256(0)); + + console.log("Deploying USDT Token..."); + console.log("Deployer:", vm.toString(deployer)); + console.log("Owner:", vm.toString(owner)); + console.log("Initial Supply:", initialSupply); + + vm.startBroadcast(); + + StandardUSDT usdt = new StandardUSDT(owner, initialSupply); + + vm.stopBroadcast(); + + console.log("USDT Token deployed at:", vm.toString(address(usdt))); + console.log("Name:", usdt.name()); + console.log("Symbol:", usdt.symbol()); + console.log("Decimals:", usdt.decimals()); + console.log("Total Supply:", usdt.totalSupply()); + } +} + diff --git a/script/helpers/Roles.sol b/script/helpers/Roles.sol new file mode 100644 index 0000000..a543b33 --- /dev/null +++ b/script/helpers/Roles.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +library Roles { + bytes32 public constant GOVERNANCE_ADMIN_ROLE = keccak256("GOVERNANCE_ADMIN_ROLE"); + bytes32 public constant TOKEN_DEPLOYER_ROLE = keccak256("TOKEN_DEPLOYER_ROLE"); + bytes32 public constant POLICY_OPERATOR_ROLE = keccak256("POLICY_OPERATOR_ROLE"); + bytes32 public constant ISSUER_ROLE = keccak256("ISSUER_ROLE"); + bytes32 public constant ENFORCEMENT_ROLE = keccak256("ENFORCEMENT_ROLE"); + bytes32 public constant COMPLIANCE_ROLE = keccak256("COMPLIANCE_ROLE"); + bytes32 public constant DEBT_AUTHORITY_ROLE = keccak256("DEBT_AUTHORITY_ROLE"); + bytes32 public constant BRIDGE_OPERATOR_ROLE = keccak256("BRIDGE_OPERATOR_ROLE"); +} + diff --git a/script/reserve/DeployChainlinkKeeper.s.sol b/script/reserve/DeployChainlinkKeeper.s.sol new file mode 100644 index 0000000..ed52b86 --- /dev/null +++ b/script/reserve/DeployChainlinkKeeper.s.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import "forge-std/Script.sol"; +import "../../contracts/reserve/ChainlinkKeeperCompatible.sol"; +import "../../contracts/reserve/PriceFeedKeeper.sol"; + +/** + * @title DeployChainlinkKeeper + * @notice Deploy ChainlinkKeeperCompatible wrapper for PriceFeedKeeper + */ +contract DeployChainlinkKeeper is Script { + function run() external { + uint256 chainId = block.chainid; + require(chainId == 138, "This script is for ChainID 138 only"); + + uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + vm.startBroadcast(deployerPrivateKey); + + address deployer = vm.addr(deployerPrivateKey); + console.log("=== Deploy Chainlink Keeper Compatible (ChainID 138) ==="); + console.log("Deployer:", deployer); + console.log(""); + + address keeperAddress = vm.envAddress("PRICE_FEED_KEEPER_ADDRESS"); + console.log("PriceFeedKeeper:", keeperAddress); + + console.log("Deploying ChainlinkKeeperCompatible..."); + ChainlinkKeeperCompatible chainlinkKeeper = new ChainlinkKeeperCompatible(keeperAddress); + console.log("ChainlinkKeeperCompatible deployed at:", address(chainlinkKeeper)); + + console.log(""); + console.log("=== Deployment Summary ==="); + console.log("ChainlinkKeeperCompatible:", address(chainlinkKeeper)); + console.log("PriceFeedKeeper:", keeperAddress); + console.log(""); + console.log("=== Next Steps ==="); + console.log("1. Register upkeep with Chainlink KeeperRegistry:"); + console.log(" node scripts/reserve/chainlink-keeper-setup.js"); + console.log("2. Or use Chainlink UI: https://automation.chain.link"); + console.log(""); + console.log("=== Export to .env ==="); + console.log("export CHAINLINK_KEEPER_COMPATIBLE_ADDRESS=", vm.toString(address(chainlinkKeeper))); + + vm.stopBroadcast(); + } +} + diff --git a/script/reserve/DeployGelatoKeeper.s.sol b/script/reserve/DeployGelatoKeeper.s.sol new file mode 100644 index 0000000..ecb855a --- /dev/null +++ b/script/reserve/DeployGelatoKeeper.s.sol @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import "forge-std/Script.sol"; +import "../../contracts/reserve/GelatoKeeperCompatible.sol"; +import "../../contracts/reserve/PriceFeedKeeper.sol"; + +/** + * @title DeployGelatoKeeper + * @notice Deploy GelatoKeeperCompatible wrapper for PriceFeedKeeper + */ +contract DeployGelatoKeeper is Script { + function run() external { + uint256 chainId = block.chainid; + require(chainId == 138, "This script is for ChainID 138 only"); + + uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + vm.startBroadcast(deployerPrivateKey); + + address deployer = vm.addr(deployerPrivateKey); + console.log("=== Deploy Gelato Keeper Compatible (ChainID 138) ==="); + console.log("Deployer:", deployer); + console.log(""); + + address keeperAddress = vm.envAddress("PRICE_FEED_KEEPER_ADDRESS"); + address gelato = vm.envOr("GELATO_OPS", address(0x527a819db1eb0e34426297b03bae11F2f8B3A19E)); // Default Gelato Ops + + console.log("PriceFeedKeeper:", keeperAddress); + console.log("Gelato Ops:", gelato); + + console.log("Deploying GelatoKeeperCompatible..."); + GelatoKeeperCompatible gelatoKeeper = new GelatoKeeperCompatible(keeperAddress, gelato); + console.log("GelatoKeeperCompatible deployed at:", address(gelatoKeeper)); + + console.log(""); + console.log("=== Deployment Summary ==="); + console.log("GelatoKeeperCompatible:", address(gelatoKeeper)); + console.log("PriceFeedKeeper:", keeperAddress); + console.log("Gelato Ops:", gelato); + console.log(""); + console.log("=== Next Steps ==="); + console.log("1. Create task with Gelato:"); + console.log(" node scripts/reserve/gelato-keeper-setup.js"); + console.log("2. Or use Gelato UI: https://app.gelato.network"); + console.log(""); + console.log("=== Export to .env ==="); + console.log("export GELATO_KEEPER_COMPATIBLE_ADDRESS=", vm.toString(address(gelatoKeeper))); + + vm.stopBroadcast(); + } +} + diff --git a/scripts/ccip/calculate-chain-selector.sh b/scripts/ccip/calculate-chain-selector.sh new file mode 100755 index 0000000..fdbc52f --- /dev/null +++ b/scripts/ccip/calculate-chain-selector.sh @@ -0,0 +1,87 @@ +#!/usr/bin/env bash +# Calculate CCIP Chain Selector for ChainID 138 +# +# CCIP chain selectors are typically calculated using a deterministic method. +# For custom chains, we can use a simple format: chainId as uint64 +# However, for compatibility with Chainlink's official CCIP, we should use +# a format that matches their calculation method. + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" + +CHAIN_ID=138 + +echo "Calculating CCIP Chain Selector for ChainID ${CHAIN_ID}..." +echo "" + +# Method 1: Simple chainId as uint64 (for custom CCIP routers) +# This is the simplest approach for custom implementations +SIMPLE_SELECTOR=$CHAIN_ID +echo "Method 1 (Simple): ChainID as uint64" +echo " Selector: ${SIMPLE_SELECTOR}" +echo " Hex: 0x$(printf '%016x' ${SIMPLE_SELECTOR})" +echo "" + +# Method 2: Chainlink-style calculation (if using official CCIP format) +# Chainlink uses: uint64(uint256(keccak256(abi.encodePacked(chainId, "CCIP")))) >> 192 +# For now, we'll use a deterministic calculation based on chainId +# Note: This is a placeholder - actual Chainlink calculation may differ +echo "Method 2 (Chainlink-style): Deterministic hash-based" +echo " Note: For custom CCIP routers, you can define your own format" +echo " Recommended: Use Method 1 (simple chainId) for custom implementations" +echo "" + +# Method 3: Using cast to calculate (if foundry/cast is available) +if command -v cast &> /dev/null; then + echo "Method 3 (Using cast):" + # Calculate using cast: cast keccak "0x$(printf '%064x' ${CHAIN_ID})CCIP" + HASH=$(cast keccak "$(printf '0x%064x' ${CHAIN_ID})CCIP" 2>/dev/null || echo "") + if [ -n "$HASH" ]; then + # Extract first 8 bytes (uint64) from hash + SELECTOR_HEX=$(echo "$HASH" | cut -c3-18) # Skip 0x, take 16 hex chars + SELECTOR_DEC=$(printf '%d' "0x${SELECTOR_HEX}") + echo " Hash: ${HASH}" + echo " Selector (first 8 bytes): ${SELECTOR_DEC}" + echo " Hex: 0x${SELECTOR_HEX}" + fi + echo "" +fi + +# Recommended selector for ChainID 138 +# For custom CCIP routers, using chainId directly is simplest and most compatible +RECOMMENDED_SELECTOR=$CHAIN_ID +RECOMMENDED_SELECTOR_HEX=$(printf '0x%016x' ${CHAIN_ID}) + +echo "==========================================" +echo "RECOMMENDED SELECTOR FOR CHAINID 138:" +echo "==========================================" +echo "Decimal: ${RECOMMENDED_SELECTOR}" +echo "Hex: ${RECOMMENDED_SELECTOR_HEX}" +echo "Hex (padded): 0x000000000000008a" +echo "" +echo "This selector should be used in:" +echo " - Environment variables (CHAIN138_SELECTOR)" +echo " - Bridge destination configuration" +echo " - Router supported chain registration" +echo " - All CCIP message routing" +echo "" +echo "Note: If integrating with Chainlink's official CCIP network," +echo " you may need to register this chain selector with Chainlink" +echo " or use their official selector format." +echo "" + +# Update .env if it exists +if [ -f "$PROJECT_ROOT/.env" ]; then + if grep -q "^CHAIN138_SELECTOR=" "$PROJECT_ROOT/.env"; then + echo "Updating CHAIN138_SELECTOR in .env..." + sed -i.bak "s|^CHAIN138_SELECTOR=.*|CHAIN138_SELECTOR=${RECOMMENDED_SELECTOR_HEX}|" "$PROJECT_ROOT/.env" + echo "✅ Updated .env with selector: ${RECOMMENDED_SELECTOR_HEX}" + else + echo "Adding CHAIN138_SELECTOR to .env..." + echo "CHAIN138_SELECTOR=${RECOMMENDED_SELECTOR_HEX}" >> "$PROJECT_ROOT/.env" + echo "✅ Added CHAIN138_SELECTOR to .env" + fi +fi + diff --git a/scripts/deployment/configure-ccip-router.sh b/scripts/deployment/configure-ccip-router.sh new file mode 100755 index 0000000..8c6d2b4 --- /dev/null +++ b/scripts/deployment/configure-ccip-router.sh @@ -0,0 +1,95 @@ +#!/usr/bin/env bash +# Configure CCIP Router with supported chains and tokens + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/../lib/init.sh" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" + +# Load environment +if [ -f "$PROJECT_ROOT/.env" ]; then + source "$PROJECT_ROOT/.env" +fi + +RPC_URL="${RPC_URL_138:-${CHAIN138_RPC_URL:-http://localhost:8545}}" +PRIVATE_KEY="${PRIVATE_KEY:-}" + +if [ -z "$PRIVATE_KEY" ]; then + log_error "Error: PRIVATE_KEY environment variable not set" + exit 1 +fi + +CCIP_ROUTER="${CCIP_CHAIN138_ROUTER:-${CCIP_ROUTER:-}}" + +if [ -z "$CCIP_ROUTER" ]; then + log_error "Error: CCIP_CHAIN138_ROUTER not set. Deploy router first." + exit 1 +fi + +log_info "Configuring CCIP Router: $CCIP_ROUTER" +log_info "RPC URL: $RPC_URL" + +# Chain selectors +ETH_MAINNET_SELECTOR="${ETH_MAINNET_SELECTOR:-5009297550715157269}" +CHAIN138_SELECTOR="${CHAIN138_SELECTOR:-138}" + +# Token addresses (from genesis) +WETH9_ADDRESS="0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" +WETH10_ADDRESS="0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f" + +log_info "Adding supported chains..." + +# Add Ethereum Mainnet as supported chain +log_info "Adding Ethereum Mainnet (selector: $ETH_MAINNET_SELECTOR)..." +if cast send "$CCIP_ROUTER" "addSupportedChain(uint64)" "$ETH_MAINNET_SELECTOR" \ + --rpc-url "$RPC_URL" \ + --private-key "$PRIVATE_KEY" \ + --legacy 2>&1 | grep -q "Success\|success\|transactionHash"; then + log_success "✅ Ethereum Mainnet added as supported chain" +else + log_warn "⚠️ Failed to add Ethereum Mainnet (may already be added)" +fi + +# Add supported tokens for Ethereum Mainnet +log_info "Adding supported tokens for Ethereum Mainnet..." + +log_info "Adding WETH9 ($WETH9_ADDRESS)..." +if cast send "$CCIP_ROUTER" "addSupportedToken(uint64,address)" "$ETH_MAINNET_SELECTOR" "$WETH9_ADDRESS" \ + --rpc-url "$RPC_URL" \ + --private-key "$PRIVATE_KEY" \ + --legacy 2>&1 | grep -q "Success\|success\|transactionHash"; then + log_success "✅ WETH9 added as supported token" +else + log_warn "⚠️ Failed to add WETH9 (may already be added)" +fi + +log_info "Adding WETH10 ($WETH10_ADDRESS)..." +if cast send "$CCIP_ROUTER" "addSupportedToken(uint64,address)" "$ETH_MAINNET_SELECTOR" "$WETH10_ADDRESS" \ + --rpc-url "$RPC_URL" \ + --private-key "$PRIVATE_KEY" \ + --legacy 2>&1 | grep -q "Success\|success\|transactionHash"; then + log_success "✅ WETH10 added as supported token" +else + log_warn "⚠️ Failed to add WETH10 (may already be added)" +fi + +# Verify configuration +log_info "Verifying configuration..." + +ETH_CHAIN_SUPPORTED=$(cast call "$CCIP_ROUTER" "supportedChains(uint64)" "$ETH_MAINNET_SELECTOR" --rpc-url "$RPC_URL" 2>/dev/null || echo "false") +if [ "$ETH_CHAIN_SUPPORTED" = "true" ]; then + log_success "✅ Ethereum Mainnet is supported" +else + log_warn "⚠️ Ethereum Mainnet support verification failed" +fi + +log_success "✅ CCIP Router configuration complete!" +echo "" +echo "Router Address: $CCIP_ROUTER" +echo "Supported Chains:" +echo " - Ethereum Mainnet ($ETH_MAINNET_SELECTOR)" +echo "Supported Tokens (Ethereum Mainnet):" +echo " - WETH9: $WETH9_ADDRESS" +echo " - WETH10: $WETH10_ADDRESS" + diff --git a/scripts/deployment/deploy-ccip-chain138-complete.sh b/scripts/deployment/deploy-ccip-chain138-complete.sh new file mode 100755 index 0000000..e6b50d7 --- /dev/null +++ b/scripts/deployment/deploy-ccip-chain138-complete.sh @@ -0,0 +1,189 @@ +#!/usr/bin/env bash +# Complete CCIP Deployment Script for ChainID 138 +# This script performs the complete CCIP deployment and configuration + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/../lib/init.sh" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" + +# Load environment +if [ -f "$PROJECT_ROOT/.env" ]; then + source "$PROJECT_ROOT/.env" +fi + +RPC_URL="${RPC_URL_138:-${CHAIN138_RPC_URL:-http://localhost:8545}}" +PRIVATE_KEY="${PRIVATE_KEY:-}" + +if [ -z "$PRIVATE_KEY" ]; then + log_error "Error: PRIVATE_KEY environment variable not set" + exit 1 +fi + +log_info "=== CCIP Complete Deployment for ChainID 138 ===" +echo "RPC URL: $RPC_URL" +echo "" + +# Verify RPC connectivity +if ! cast block-number --rpc-url "$RPC_URL" &>/dev/null; then + log_error "Error: Cannot connect to RPC at $RPC_URL" + exit 1 +fi + +CHAIN_ID=$(cast chain-id --rpc-url "$RPC_URL" 2>/dev/null || echo "unknown") +if [ "$CHAIN_ID" != "138" ]; then + log_warn "⚠️ Warning: Chain ID is $CHAIN_ID, expected 138" + read -p "Continue anyway? (y/N) " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + exit 1 + fi +fi + +echo "Chain ID: $CHAIN_ID" +echo "" + +# Step 1: Calculate Chain Selector +log_info "Step 1: Calculating chain selector..." +if [ -f "$PROJECT_ROOT/scripts/ccip/calculate-chain-selector.sh" ]; then + bash "$PROJECT_ROOT/scripts/ccip/calculate-chain-selector.sh" + log_success "✅ Chain selector calculated" +else + log_warn "⚠️ Chain selector script not found, using default: 138" + CHAIN138_SELECTOR="${CHAIN138_SELECTOR:-138}" +fi + +# Step 2: Deploy CCIP Router +log_info "Step 2: Deploying CCIP Router..." +CCIP_ROUTER="${CCIP_CHAIN138_ROUTER:-}" + +if [ -z "$CCIP_ROUTER" ] || [ "$CCIP_ROUTER" = "" ]; then + log_info "Deploying CCIP Router..." + + # Set default fee configuration if not set + export CCIP_FEE_TOKEN="${CCIP_CHAIN138_LINK_TOKEN:-0x0000000000000000000000000000000000000000}" + export CCIP_BASE_FEE="${CCIP_BASE_FEE:-1000000000000000}" + export CCIP_DATA_FEE_PER_BYTE="${CCIP_DATA_FEE_PER_BYTE:-100000000}" + + ROUTER_OUTPUT=$(forge script script/DeployCCIPRouter.s.sol \ + --rpc-url "$RPC_URL" \ + --broadcast \ + --private-key "$PRIVATE_KEY" 2>&1 || true) + + ROUTER_ADDRESS=$(echo "$ROUTER_OUTPUT" | grep -E "CCIP Router deployed at:|deployed at:" | tail -1 | sed 's/.*at: //' | awk '{print $1}' | tr -d '\n' || echo "") + + if [ -n "$ROUTER_ADDRESS" ] && [ "$ROUTER_ADDRESS" != "" ]; then + CCIP_ROUTER="$ROUTER_ADDRESS" + log_success "✅ CCIP Router deployed at: $CCIP_ROUTER" + + # Update .env + if grep -q "^CCIP_CHAIN138_ROUTER=" "$PROJECT_ROOT/.env" 2>/dev/null; then + sed -i.bak "s|^CCIP_CHAIN138_ROUTER=.*|CCIP_CHAIN138_ROUTER=$CCIP_ROUTER|" "$PROJECT_ROOT/.env" + else + echo "CCIP_CHAIN138_ROUTER=$CCIP_ROUTER" >> "$PROJECT_ROOT/.env" + fi + + # Configure router + log_info "Configuring CCIP Router..." + export CCIP_CHAIN138_ROUTER="$CCIP_ROUTER" + bash "$PROJECT_ROOT/scripts/deployment/configure-ccip-router.sh" || log_warn "⚠️ Router configuration had issues" + else + log_error "❌ Failed to deploy CCIP Router" + exit 1 + fi +else + log_success "✅ CCIP Router already deployed: $CCIP_ROUTER" +fi + +# Step 3: Deploy CCIPWETH9Bridge +log_info "Step 3: Deploying CCIPWETH9Bridge..." +WETH9_BRIDGE="${CCIPWETH9_BRIDGE_CHAIN138:-}" + +if [ -z "$WETH9_BRIDGE" ] || [ "$WETH9_BRIDGE" = "" ]; then + log_info "Deploying CCIPWETH9Bridge..." + + export CCIP_ROUTER="$CCIP_ROUTER" + export CCIP_FEE_TOKEN="${CCIP_CHAIN138_LINK_TOKEN:-0x0000000000000000000000000000000000000000}" + + BRIDGE9_OUTPUT=$(forge script script/DeployCCIPWETH9Bridge.s.sol \ + --rpc-url "$RPC_URL" \ + --broadcast \ + --private-key "$PRIVATE_KEY" 2>&1 || true) + + BRIDGE9_ADDRESS=$(echo "$BRIDGE9_OUTPUT" | grep -E "CCIPWETH9Bridge deployed at:|deployed at:" | tail -1 | sed 's/.*at: //' | awk '{print $1}' | tr -d '\n' || echo "") + + if [ -n "$BRIDGE9_ADDRESS" ] && [ "$BRIDGE9_ADDRESS" != "" ]; then + WETH9_BRIDGE="$BRIDGE9_ADDRESS" + log_success "✅ CCIPWETH9Bridge deployed at: $WETH9_BRIDGE" + + # Update .env + if grep -q "^CCIPWETH9_BRIDGE_CHAIN138=" "$PROJECT_ROOT/.env" 2>/dev/null; then + sed -i.bak "s|^CCIPWETH9_BRIDGE_CHAIN138=.*|CCIPWETH9_BRIDGE_CHAIN138=$WETH9_BRIDGE|" "$PROJECT_ROOT/.env" + else + echo "CCIPWETH9_BRIDGE_CHAIN138=$WETH9_BRIDGE" >> "$PROJECT_ROOT/.env" + fi + else + log_error "❌ Failed to deploy CCIPWETH9Bridge" + exit 1 + fi +else + log_success "✅ CCIPWETH9Bridge already deployed: $WETH9_BRIDGE" +fi + +# Step 4: Deploy CCIPWETH10Bridge +log_info "Step 4: Deploying CCIPWETH10Bridge..." +WETH10_BRIDGE="${CCIPWETH10_BRIDGE_CHAIN138:-}" + +if [ -z "$WETH10_BRIDGE" ] || [ "$WETH10_BRIDGE" = "" ]; then + log_info "Deploying CCIPWETH10Bridge..." + + export CCIP_ROUTER="$CCIP_ROUTER" + export CCIP_FEE_TOKEN="${CCIP_CHAIN138_LINK_TOKEN:-0x0000000000000000000000000000000000000000}" + + BRIDGE10_OUTPUT=$(forge script script/DeployCCIPWETH10Bridge.s.sol \ + --rpc-url "$RPC_URL" \ + --broadcast \ + --private-key "$PRIVATE_KEY" 2>&1 || true) + + BRIDGE10_ADDRESS=$(echo "$BRIDGE10_OUTPUT" | grep -E "CCIPWETH10Bridge deployed at:|deployed at:" | tail -1 | sed 's/.*at: //' | awk '{print $1}' | tr -d '\n' || echo "") + + if [ -n "$BRIDGE10_ADDRESS" ] && [ "$BRIDGE10_ADDRESS" != "" ]; then + WETH10_BRIDGE="$BRIDGE10_ADDRESS" + log_success "✅ CCIPWETH10Bridge deployed at: $WETH10_BRIDGE" + + # Update .env + if grep -q "^CCIPWETH10_BRIDGE_CHAIN138=" "$PROJECT_ROOT/.env" 2>/dev/null; then + sed -i.bak "s|^CCIPWETH10_BRIDGE_CHAIN138=.*|CCIPWETH10_BRIDGE_CHAIN138=$WETH10_BRIDGE|" "$PROJECT_ROOT/.env" + else + echo "CCIPWETH10_BRIDGE_CHAIN138=$WETH10_BRIDGE" >> "$PROJECT_ROOT/.env" + fi + else + log_error "❌ Failed to deploy CCIPWETH10Bridge" + exit 1 + fi +else + log_success "✅ CCIPWETH10Bridge already deployed: $WETH10_BRIDGE" +fi + +# Step 5: Verify Deployment +log_info "Step 5: Verifying deployment..." +bash "$PROJECT_ROOT/scripts/deployment/verify-ccip-deployment.sh" || log_warn "⚠️ Verification had issues" + +# Step 6: Summary +echo "" +log_success "=== Deployment Summary ===" +echo "CCIP Router: $CCIP_ROUTER" +echo "CCIPWETH9Bridge: $WETH9_BRIDGE" +echo "CCIPWETH10Bridge: $WETH10_BRIDGE" +echo "" +echo "Next steps:" +echo "1. Configure bridge destinations:" +echo " ./scripts/deployment/configure-weth9-bridge.sh" +echo " ./scripts/deployment/configure-weth10-bridge.sh" +echo "2. Verify on explorer" +echo "3. Test cross-chain transfers" +echo "4. Update documentation with deployed addresses" + +log_success "✅ CCIP deployment complete!" + diff --git a/scripts/deployment/verify-ccip-deployment.sh b/scripts/deployment/verify-ccip-deployment.sh new file mode 100755 index 0000000..d904a2e --- /dev/null +++ b/scripts/deployment/verify-ccip-deployment.sh @@ -0,0 +1,180 @@ +#!/usr/bin/env bash +# Verify CCIP deployment on ChainID 138 + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/../lib/init.sh" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" + +# Load environment +if [ -f "$PROJECT_ROOT/.env" ]; then + source "$PROJECT_ROOT/.env" +fi + +RPC_URL="${RPC_URL_138:-${CHAIN138_RPC_URL:-http://localhost:8545}}" + +log_info "=== CCIP Deployment Verification for ChainID 138 ===" +echo "RPC URL: $RPC_URL" +echo "" + +# Check if RPC is accessible +if ! cast block-number --rpc-url "$RPC_URL" &>/dev/null; then + log_error "Error: Cannot connect to RPC at $RPC_URL" + exit 1 +fi + +CHAIN_ID=$(cast chain-id --rpc-url "$RPC_URL" 2>/dev/null || echo "unknown") +if [ "$CHAIN_ID" != "138" ]; then + log_warn "⚠️ Warning: Chain ID is $CHAIN_ID, expected 138" +fi + +echo "Chain ID: $CHAIN_ID" +echo "" + +# Required addresses +CCIP_ROUTER="${CCIP_CHAIN138_ROUTER:-}" +LINK_TOKEN="${CCIP_CHAIN138_LINK_TOKEN:-}" +WETH9_BRIDGE="${CCIPWETH9_BRIDGE_CHAIN138:-}" +WETH10_BRIDGE="${CCIPWETH10_BRIDGE_CHAIN138:-}" +CHAIN_SELECTOR="${CHAIN138_SELECTOR:-}" + +# Verification results +VERIFICATION_PASSED=0 +VERIFICATION_FAILED=0 +VERIFICATION_WARNINGS=0 + +check_contract() { + local name=$1 + local address=$2 + local required=${3:-true} + + if [ -z "$address" ] || [ "$address" = "" ]; then + if [ "$required" = "true" ]; then + echo " ❌ $name: Not configured" + ((VERIFICATION_FAILED++)) + else + echo " ⚠️ $name: Not configured (optional)" + ((VERIFICATION_WARNINGS++)) + fi + return 1 + fi + + # Check if address has code + CODE=$(cast code "$address" --rpc-url "$RPC_URL" 2>/dev/null || echo "") + if [ -z "$CODE" ] || [ "$CODE" = "0x" ]; then + echo " ❌ $name: No code at address $address" + ((VERIFICATION_FAILED++)) + return 1 + fi + + echo " ✅ $name: Deployed at $address" + ((VERIFICATION_PASSED++)) + return 0 +} + +verify_router_config() { + local router=$1 + if [ -z "$router" ]; then + return 1 + fi + + echo "" + echo "Router Configuration:" + + # Check supported chains + ETH_SELECTOR="5009297550715157269" + ETH_SUPPORTED=$(cast call "$router" "supportedChains(uint64)" "$ETH_SELECTOR" --rpc-url "$RPC_URL" 2>/dev/null || echo "false") + if [ "$ETH_SUPPORTED" = "true" ]; then + echo " ✅ Ethereum Mainnet is supported" + else + echo " ⚠️ Ethereum Mainnet not configured as supported chain" + ((VERIFICATION_WARNINGS++)) + fi + + # Check fee token + FEE_TOKEN=$(cast call "$router" "feeToken()" --rpc-url "$RPC_URL" 2>/dev/null || echo "") + if [ -n "$FEE_TOKEN" ]; then + if [ "$FEE_TOKEN" = "0x0000000000000000000000000000000000000000" ]; then + echo " ✅ Fee token: Native ETH" + else + echo " ✅ Fee token: $FEE_TOKEN" + fi + fi +} + +verify_bridge_config() { + local bridge=$1 + local name=$2 + if [ -z "$bridge" ]; then + return 1 + fi + + echo "" + echo "$name Configuration:" + + # Check router + BRIDGE_ROUTER=$(cast call "$bridge" "ccipRouter()" --rpc-url "$RPC_URL" 2>/dev/null || echo "") + if [ -n "$BRIDGE_ROUTER" ] && [ "$BRIDGE_ROUTER" != "0x0000000000000000000000000000000000000000" ]; then + echo " ✅ Router: $BRIDGE_ROUTER" + else + echo " ⚠️ Router not configured" + ((VERIFICATION_WARNINGS++)) + fi + + # Check destinations + ETH_SELECTOR="5009297550715157269" + DEST=$(cast call "$bridge" "destinations(uint64)" "$ETH_SELECTOR" --rpc-url "$RPC_URL" 2>/dev/null || echo "") + if [ -n "$DEST" ] && echo "$DEST" | grep -q "0x[0-9a-f]\{40\}"; then + echo " ✅ Ethereum Mainnet destination configured" + else + echo " ⚠️ Ethereum Mainnet destination not configured" + ((VERIFICATION_WARNINGS++)) + fi +} + +echo "=== Contract Deployment Verification ===" +check_contract "CCIP Router" "$CCIP_ROUTER" true +check_contract "LINK Token" "$LINK_TOKEN" false +check_contract "CCIPWETH9Bridge" "$WETH9_BRIDGE" true +check_contract "CCIPWETH10Bridge" "$WETH10_BRIDGE" true + +if [ -n "$CCIP_ROUTER" ]; then + verify_router_config "$CCIP_ROUTER" +fi + +if [ -n "$WETH9_BRIDGE" ]; then + verify_bridge_config "$WETH9_BRIDGE" "CCIPWETH9Bridge" +fi + +if [ -n "$WETH10_BRIDGE" ]; then + verify_bridge_config "$WETH10_BRIDGE" "CCIPWETH10Bridge" +fi + +echo "" +echo "=== Chain Selector ===" +if [ -n "$CHAIN_SELECTOR" ]; then + echo " ✅ Chain Selector: $CHAIN_SELECTOR" +else + echo " ⚠️ Chain Selector: Not configured" + ((VERIFICATION_WARNINGS++)) +fi + +echo "" +echo "=== Verification Summary ===" +echo "✅ Passed: $VERIFICATION_PASSED" +echo "❌ Failed: $VERIFICATION_FAILED" +echo "⚠️ Warnings: $VERIFICATION_WARNINGS" +echo "" + +if [ $VERIFICATION_FAILED -eq 0 ]; then + log_success "✅ All required contracts are deployed!" + if [ $VERIFICATION_WARNINGS -gt 0 ]; then + log_warn "⚠️ Some optional configurations are missing" + fi + exit 0 +else + log_error "❌ Some required contracts are missing or invalid" + exit 1 +fi + diff --git a/scripts/reserve/chainlink-keeper-setup.js b/scripts/reserve/chainlink-keeper-setup.js new file mode 100755 index 0000000..c7a970e --- /dev/null +++ b/scripts/reserve/chainlink-keeper-setup.js @@ -0,0 +1,141 @@ +#!/usr/bin/env node +/** + * Chainlink Keepers Setup Script + * Registers PriceFeedKeeper with Chainlink Automation + * + * Usage: + * node scripts/reserve/chainlink-keeper-setup.js + * + * Environment Variables: + * RPC_URL_138 - ChainID 138 RPC endpoint + * PRIVATE_KEY - Deployer private key + * KEEPER_REGISTRY_ADDRESS - Chainlink KeeperRegistry address + * PRICE_FEED_KEEPER_ADDRESS - PriceFeedKeeper contract address + * LINK_TOKEN_ADDRESS - LINK token address + * UPKEEP_INTERVAL - Upkeep interval in seconds (default: 30) + * GAS_LIMIT - Gas limit for upkeep (default: 500000) + * FUNDING_AMOUNT - LINK amount to fund (default: 10 LINK) + */ + +const { ethers } = require('ethers'); +require('dotenv').config(); + +const CONFIG = { + rpcUrl: process.env.RPC_URL_138 || 'http://localhost:8545', + privateKey: process.env.PRIVATE_KEY, + keeperRegistry: process.env.KEEPER_REGISTRY_ADDRESS, + keeperAddress: process.env.PRICE_FEED_KEEPER_ADDRESS, + linkToken: process.env.LINK_TOKEN_ADDRESS, + upkeepInterval: parseInt(process.env.UPKEEP_INTERVAL || '30'), + gasLimit: parseInt(process.env.GAS_LIMIT || '500000'), + fundingAmount: ethers.parseEther(process.env.FUNDING_AMOUNT || '10'), +}; + +// Chainlink KeeperRegistry ABI (simplified) +const KEEPER_REGISTRY_ABI = [ + "function registerUpkeep(address target, uint32 gasLimit, address admin, bytes calldata checkData, uint96 amount, address source, bytes memory encryptedEmail) external returns (uint256)", + "function getUpkeep(uint256 id) external view returns (address target, uint32 executeGas, bytes memory checkData, uint96 balance, address lastKeeper, uint96 balance, address admin, uint64 maxValidBlocknumber, uint96 amountSpent)", + "function addFunds(uint256 id, uint96 amount) external", + "event UpkeepRegistered(uint256 indexed id, address indexed target, uint32 gasLimit, address admin)", +]; + +// ChainlinkKeeperCompatible ABI +const KEEPER_COMPATIBLE_ABI = [ + "function checkUpkeep(bytes calldata checkData) external view returns (bool upkeepNeeded, bytes memory performData)", + "function performUpkeep(bytes calldata performData) external", +]; + +// LINK Token ABI +const LINK_TOKEN_ABI = [ + "function approve(address spender, uint256 amount) external returns (bool)", + "function transfer(address to, uint256 amount) external returns (bool)", + "function balanceOf(address account) external view returns (uint256)", +]; + +async function main() { + console.log('=== Chainlink Keepers Setup ===\n'); + + // Validate configuration + if (!CONFIG.privateKey) throw new Error('PRIVATE_KEY is required'); + if (!CONFIG.keeperRegistry) throw new Error('KEEPER_REGISTRY_ADDRESS is required'); + if (!CONFIG.keeperAddress) throw new Error('PRICE_FEED_KEEPER_ADDRESS is required'); + if (!CONFIG.linkToken) throw new Error('LINK_TOKEN_ADDRESS is required'); + + const provider = new ethers.JsonRpcProvider(CONFIG.rpcUrl); + const wallet = new ethers.Wallet(CONFIG.privateKey, provider); + + console.log('Network:', CONFIG.rpcUrl); + console.log('Deployer:', wallet.address); + console.log('Keeper Registry:', CONFIG.keeperRegistry); + console.log('Keeper Address:', CONFIG.keeperAddress); + console.log('LINK Token:', CONFIG.linkToken); + console.log('Upkeep Interval:', CONFIG.upkeepInterval, 'seconds'); + console.log('Gas Limit:', CONFIG.gasLimit); + console.log('Funding Amount:', ethers.formatEther(CONFIG.fundingAmount), 'LINK'); + console.log(''); + + // Check LINK balance + const linkToken = new ethers.Contract(CONFIG.linkToken, LINK_TOKEN_ABI, wallet); + const linkBalance = await linkToken.balanceOf(wallet.address); + console.log('LINK Balance:', ethers.formatEther(linkBalance), 'LINK'); + + if (linkBalance < CONFIG.fundingAmount) { + throw new Error(`Insufficient LINK balance. Need ${ethers.formatEther(CONFIG.fundingAmount)} LINK`); + } + + // Approve LINK spending + console.log('\nApproving LINK spending...'); + const approveTx = await linkToken.approve(CONFIG.keeperRegistry, CONFIG.fundingAmount); + await approveTx.wait(); + console.log('✓ LINK approved'); + + // Register upkeep + console.log('\nRegistering upkeep...'); + const keeperRegistry = new ethers.Contract(CONFIG.keeperRegistry, KEEPER_REGISTRY_ABI, wallet); + + const checkData = ethers.toUtf8Bytes(''); // Empty check data + const encryptedEmail = ethers.toUtf8Bytes(''); // Empty email + + const registerTx = await keeperRegistry.registerUpkeep( + CONFIG.keeperAddress, + CONFIG.gasLimit, + wallet.address, // Admin + checkData, + CONFIG.fundingAmount, + wallet.address, // Source + encryptedEmail + ); + + console.log('Transaction sent:', registerTx.hash); + const receipt = await registerTx.wait(); + + // Parse UpkeepRegistered event + const event = receipt.logs.find(log => { + try { + const parsed = keeperRegistry.interface.parseLog(log); + return parsed.name === 'UpkeepRegistered'; + } catch { + return false; + } + }); + + if (event) { + const parsed = keeperRegistry.interface.parseLog(event); + const upkeepId = parsed.args.id; + console.log('✓ Upkeep registered!'); + console.log('Upkeep ID:', upkeepId.toString()); + console.log(''); + console.log('=== Setup Complete ==='); + console.log('Upkeep ID:', upkeepId.toString()); + console.log('Monitor at:', `https://automation.chain.link/${upkeepId}`); + } else { + console.log('⚠ Could not parse UpkeepRegistered event'); + console.log('Check transaction receipt for upkeep ID'); + } +} + +main().catch(error => { + console.error('Error:', error.message); + process.exit(1); +}); + diff --git a/scripts/reserve/deploy-all.sh b/scripts/reserve/deploy-all.sh new file mode 100755 index 0000000..c78ebfd --- /dev/null +++ b/scripts/reserve/deploy-all.sh @@ -0,0 +1,103 @@ +#!/bin/bash +# Complete Keeper Deployment Script +# Deploys all keeper components and sets up monitoring + +set -e + +# Colors +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +RED='\033[0;31m' +NC='\033[0m' + +# Load environment variables +if [ -f .env ]; then + source .env +fi + +# Configuration +RPC_URL="${RPC_URL_138:-https://rpc.d-bis.org}" +PRIVATE_KEY="${PRIVATE_KEY}" +KEEPER_ADDRESS="${PRICE_FEED_KEEPER_ADDRESS}" + +echo -e "${GREEN}=== Complete Keeper Deployment ===${NC}\n" + +# Step 1: Deploy PriceFeedKeeper +echo -e "${YELLOW}Step 1: Deploying PriceFeedKeeper...${NC}" +if [ -z "$KEEPER_ADDRESS" ]; then + forge script script/reserve/DeployKeeper.s.sol:DeployKeeper \ + --rpc-url "$RPC_URL" \ + --broadcast \ + --verify + + # Extract keeper address from output + KEEPER_ADDRESS=$(forge script script/reserve/DeployKeeper.s.sol:DeployKeeper \ + --rpc-url "$RPC_URL" 2>&1 | grep "PriceFeedKeeper deployed at:" | awk '{print $NF}') + + echo "export PRICE_FEED_KEEPER_ADDRESS=$KEEPER_ADDRESS" >> .env + echo -e "${GREEN}✓ PriceFeedKeeper deployed: $KEEPER_ADDRESS${NC}\n" +else + echo -e "${GREEN}✓ PriceFeedKeeper already deployed: $KEEPER_ADDRESS${NC}\n" +fi + +# Step 2: Deploy Chainlink Keeper Compatible (optional) +if [ "$DEPLOY_CHAINLINK" = "true" ]; then + echo -e "${YELLOW}Step 2: Deploying ChainlinkKeeperCompatible...${NC}" + forge script script/reserve/DeployChainlinkKeeper.s.sol:DeployChainlinkKeeper \ + --rpc-url "$RPC_URL" \ + --broadcast \ + --verify + + CHAINLINK_KEEPER=$(forge script script/reserve/DeployChainlinkKeeper.s.sol:DeployChainlinkKeeper \ + --rpc-url "$RPC_URL" 2>&1 | grep "ChainlinkKeeperCompatible deployed at:" | awk '{print $NF}') + + echo "export CHAINLINK_KEEPER_COMPATIBLE_ADDRESS=$CHAINLINK_KEEPER" >> .env + echo -e "${GREEN}✓ ChainlinkKeeperCompatible deployed: $CHAINLINK_KEEPER${NC}\n" + + echo -e "${YELLOW}Next: Register with Chainlink Keepers:${NC}" + echo "node scripts/reserve/chainlink-keeper-setup.js" + echo "" +fi + +# Step 3: Deploy Gelato Keeper Compatible (optional) +if [ "$DEPLOY_GELATO" = "true" ]; then + echo -e "${YELLOW}Step 3: Deploying GelatoKeeperCompatible...${NC}" + forge script script/reserve/DeployGelatoKeeper.s.sol:DeployGelatoKeeper \ + --rpc-url "$RPC_URL" \ + --broadcast \ + --verify + + GELATO_KEEPER=$(forge script script/reserve/DeployGelatoKeeper.s.sol:DeployGelatoKeeper \ + --rpc-url "$RPC_URL" 2>&1 | grep "GelatoKeeperCompatible deployed at:" | awk '{print $NF}') + + echo "export GELATO_KEEPER_COMPATIBLE_ADDRESS=$GELATO_KEEPER" >> .env + echo -e "${GREEN}✓ GelatoKeeperCompatible deployed: $GELATO_KEEPER${NC}\n" + + echo -e "${YELLOW}Next: Create task with Gelato:${NC}" + echo "node scripts/reserve/gelato-keeper-setup.js" + echo "" +fi + +# Step 4: Verify deployment +echo -e "${YELLOW}Step 4: Verifying deployment...${NC}" +forge script script/reserve/CheckUpkeep.s.sol:CheckUpkeep \ + --rpc-url "$RPC_URL" + +echo -e "\n${GREEN}=== Deployment Complete ===${NC}" +echo "" +echo "Keeper Address: $KEEPER_ADDRESS" +echo "" +echo -e "${YELLOW}Next Steps:${NC}" +echo "1. Start keeper service:" +echo " node scripts/reserve/keeper-service.js" +echo "" +echo "2. Start monitor service:" +echo " node scripts/reserve/monitor-keeper.js" +echo "" +echo "3. Or use Docker:" +echo " docker-compose -f docker/docker-compose.keeper.yml up -d" +echo "" +echo "4. Or use systemd:" +echo " sudo systemctl enable price-feed-keeper" +echo " sudo systemctl start price-feed-keeper" + diff --git a/scripts/reserve/gelato-keeper-setup.js b/scripts/reserve/gelato-keeper-setup.js new file mode 100755 index 0000000..876e526 --- /dev/null +++ b/scripts/reserve/gelato-keeper-setup.js @@ -0,0 +1,136 @@ +#!/usr/bin/env node +/** + * Gelato Network Setup Script + * Registers PriceFeedKeeper with Gelato Network + * + * Usage: + * node scripts/reserve/gelato-keeper-setup.js + * + * Environment Variables: + * RPC_URL_138 - ChainID 138 RPC endpoint + * PRIVATE_KEY - Deployer private key + * GELATO_OPS - Gelato Ops contract address + * PRICE_FEED_KEEPER_ADDRESS - PriceFeedKeeper contract address + * EXECUTION_INTERVAL - Execution interval in seconds (default: 30) + * FUNDING_AMOUNT - Native token amount to fund (default: 0.1 ETH) + */ + +const { ethers } = require('ethers'); +require('dotenv').config(); + +const CONFIG = { + rpcUrl: process.env.RPC_URL_138 || 'http://localhost:8545', + privateKey: process.env.PRIVATE_KEY, + gelatoOps: process.env.GELATO_OPS || '0x527a819db1eb0e34426297b03bae11F2f8B3A19E', // Default Gelato Ops + keeperAddress: process.env.PRICE_FEED_KEEPER_ADDRESS, + executionInterval: parseInt(process.env.EXECUTION_INTERVAL || '30'), + fundingAmount: ethers.parseEther(process.env.FUNDING_AMOUNT || '0.1'), +}; + +// Gelato Ops ABI (simplified) +const GELATO_OPS_ABI = [ + "function createTask(address execAddress, bytes4 execSelector, address resolverAddress, bytes calldata resolverData) external returns (bytes32)", + "function getTaskId(address execAddress, bytes4 execSelector, address resolverAddress, bytes calldata resolverData) external view returns (bytes32)", + "function cancelTask(bytes32 taskId) external", + "function depositFunds(address taskCreator, address token, uint256 amount) external payable", + "function getTaskId(address execAddress, bytes4 execSelector, address resolverAddress, bytes calldata resolverData) external view returns (bytes32)", + "event TaskCreated(bytes32 indexed taskId, address indexed execAddress, bytes4 execSelector, address indexed resolverAddress, bytes resolverData)", +]; + +// GelatoKeeperCompatible ABI +const GELATO_KEEPER_ABI = [ + "function executeTask() external", + "function canExec() external view returns (bool canExec, bytes memory execData)", +]; + +async function main() { + console.log('=== Gelato Network Setup ===\n'); + + // Validate configuration + if (!CONFIG.privateKey) throw new Error('PRIVATE_KEY is required'); + if (!CONFIG.keeperAddress) throw new Error('PRICE_FEED_KEEPER_ADDRESS is required'); + + const provider = new ethers.JsonRpcProvider(CONFIG.rpcUrl); + const wallet = new ethers.Wallet(CONFIG.privateKey, provider); + + console.log('Network:', CONFIG.rpcUrl); + console.log('Deployer:', wallet.address); + console.log('Gelato Ops:', CONFIG.gelatoOps); + console.log('Keeper Address:', CONFIG.keeperAddress); + console.log('Execution Interval:', CONFIG.executionInterval, 'seconds'); + console.log('Funding Amount:', ethers.formatEther(CONFIG.fundingAmount), 'ETH'); + console.log(''); + + // Check balance + const balance = await provider.getBalance(wallet.address); + console.log('Balance:', ethers.formatEther(balance), 'ETH'); + + if (balance < CONFIG.fundingAmount) { + throw new Error(`Insufficient balance. Need ${ethers.formatEther(CONFIG.fundingAmount)} ETH`); + } + + // Deploy GelatoKeeperCompatible if not already deployed + console.log('Checking GelatoKeeperCompatible contract...'); + // For now, assume it needs to be deployed via Foundry script + // In production, deploy it first and set GELATO_KEEPER_COMPATIBLE_ADDRESS + + const gelatoKeeperAddress = process.env.GELATO_KEEPER_COMPATIBLE_ADDRESS; + if (!gelatoKeeperAddress) { + console.log('⚠ GELATO_KEEPER_COMPATIBLE_ADDRESS not set'); + console.log('Please deploy GelatoKeeperCompatible contract first using:'); + console.log('forge script script/reserve/DeployGelatoKeeper.s.sol:DeployGelatoKeeper --rpc-url chain138 --broadcast'); + process.exit(1); + } + + console.log('GelatoKeeperCompatible:', gelatoKeeperAddress); + + // Create task + console.log('\nCreating Gelato task...'); + const gelatoOps = new ethers.Contract(CONFIG.gelatoOps, GELATO_OPS_ABI, wallet); + + const execAddress = gelatoKeeperAddress; + const execSelector = '0x3c4b2e02'; // executeTask() selector + const resolverAddress = gelatoKeeperAddress; + const resolverData = ethers.AbiCoder.defaultAbiCoder().encode(['bytes4'], ['0x3c4b2e02']); // canExec() selector + + const createTaskTx = await gelatoOps.createTask( + execAddress, + execSelector, + resolverAddress, + resolverData, + { value: CONFIG.fundingAmount } + ); + + console.log('Transaction sent:', createTaskTx.hash); + const receipt = await createTaskTx.wait(); + + // Parse TaskCreated event + const event = receipt.logs.find(log => { + try { + const parsed = gelatoOps.interface.parseLog(log); + return parsed.name === 'TaskCreated'; + } catch { + return false; + } + }); + + if (event) { + const parsed = gelatoOps.interface.parseLog(event); + const taskId = parsed.args.taskId; + console.log('✓ Task created!'); + console.log('Task ID:', taskId); + console.log(''); + console.log('=== Setup Complete ==='); + console.log('Task ID:', taskId); + console.log('Monitor at: https://app.gelato.network/task/' + taskId); + } else { + console.log('⚠ Could not parse TaskCreated event'); + console.log('Check transaction receipt for task ID'); + } +} + +main().catch(error => { + console.error('Error:', error.message); + process.exit(1); +}); + diff --git a/scripts/reserve/monitor-keeper.js b/scripts/reserve/monitor-keeper.js new file mode 100755 index 0000000..4e0782f --- /dev/null +++ b/scripts/reserve/monitor-keeper.js @@ -0,0 +1,249 @@ +#!/usr/bin/env node +/** + * Keeper Monitoring Service + * Monitors keeper performance and sends alerts on failures + * + * Usage: + * node scripts/reserve/monitor-keeper.js + * + * Environment Variables: + * RPC_URL_138 - ChainID 138 RPC endpoint + * PRICE_FEED_KEEPER_ADDRESS - PriceFeedKeeper contract address + * ALERT_WEBHOOK - Webhook URL for alerts (optional) + * CHECK_INTERVAL - Check interval in seconds (default: 60) + * ALERT_THRESHOLD - Number of consecutive failures before alert (default: 3) + */ + +const { ethers } = require('ethers'); +const http = require('http'); +require('dotenv').config(); + +const CONFIG = { + rpcUrl: process.env.RPC_URL_138 || 'http://localhost:8545', + keeperAddress: process.env.PRICE_FEED_KEEPER_ADDRESS, + alertWebhook: process.env.ALERT_WEBHOOK, + checkInterval: parseInt(process.env.CHECK_INTERVAL || '60') * 1000, + alertThreshold: parseInt(process.env.ALERT_THRESHOLD || '3'), +}; + +const KEEPER_ABI = [ + "function checkUpkeep() external view returns (bool needsUpdate, address[] memory assets)", + "function getTrackedAssets() external view returns (address[] memory)", + "function updateInterval() external view returns (uint256)", + "function lastUpdateTime(address asset) external view returns (uint256)", + "event PriceFeedsUpdated(address[] assets, uint256 timestamp)", +]; + +class KeeperMonitor { + constructor() { + if (!CONFIG.keeperAddress) { + throw new Error('PRICE_FEED_KEEPER_ADDRESS is required'); + } + + this.provider = new ethers.JsonRpcProvider(CONFIG.rpcUrl); + this.keeper = new ethers.Contract(CONFIG.keeperAddress, KEEPER_ABI, this.provider); + this.failureCount = 0; + this.lastCheck = null; + this.stats = { + checks: 0, + failures: 0, + alerts: 0, + lastUpdate: null, + }; + } + + async start() { + console.log('=== Keeper Monitor Service ==='); + console.log(`RPC URL: ${CONFIG.rpcUrl}`); + console.log(`Keeper Address: ${CONFIG.keeperAddress}`); + console.log(`Check Interval: ${CONFIG.checkInterval / 1000} seconds`); + console.log(`Alert Threshold: ${CONFIG.alertThreshold} failures`); + console.log(''); + + // Start monitoring loop + this.monitorLoop(); + + // Start HTTP health endpoint + this.startHealthServer(); + } + + async monitorLoop() { + while (true) { + try { + await this.checkKeeper(); + } catch (error) { + console.error(`Monitor error: ${error.message}`); + this.failureCount++; + } + + await this.sleep(CONFIG.checkInterval); + } + } + + async checkKeeper() { + this.stats.checks++; + const checkTime = new Date(); + + try { + // Check if upkeep is needed + const [needsUpdate, assets] = await this.keeper.checkUpkeep(); + + // Get tracked assets + const trackedAssets = await this.keeper.getTrackedAssets(); + const updateInterval = await this.keeper.updateInterval(); + + // Check last update times + const staleAssets = []; + for (const asset of trackedAssets) { + const lastUpdate = await this.keeper.lastUpdateTime(asset); + const timeSinceUpdate = checkTime.getTime() / 1000 - Number(lastUpdate); + + if (lastUpdate > 0 && timeSinceUpdate > Number(updateInterval) * 2) { + staleAssets.push({ asset, lastUpdate: Number(lastUpdate), stale: timeSinceUpdate }); + } + } + + // Log status + const status = { + timestamp: checkTime.toISOString(), + needsUpdate, + assetsNeedingUpdate: assets.length, + trackedAssets: trackedAssets.length, + staleAssets: staleAssets.length, + updateInterval: Number(updateInterval), + }; + + console.log(`[${status.timestamp}] Status:`, { + needsUpdate: status.needsUpdate, + assetsNeedingUpdate: status.assetsNeedingUpdate, + trackedAssets: status.trackedAssets, + staleAssets: status.staleAssets, + }); + + // Check for issues + if (needsUpdate && assets.length > 0) { + const timeSinceLastCheck = this.lastCheck + ? (checkTime.getTime() - this.lastCheck.getTime()) / 1000 + : 0; + + if (timeSinceLastCheck > Number(updateInterval) * 2 && this.lastCheck !== null) { + // Keeper hasn't updated in time + this.failureCount++; + console.warn(`⚠ Keeper appears stalled. ${assets.length} assets need update.`); + + if (this.failureCount >= CONFIG.alertThreshold) { + await this.sendAlert({ + type: 'keeper_stalled', + message: `Keeper has not updated for ${timeSinceLastCheck} seconds`, + assetsNeedingUpdate: assets.length, + staleAssets, + }); + } + } else { + this.failureCount = 0; // Reset on success + } + } + + // Check for stale assets + if (staleAssets.length > 0) { + console.warn(`⚠ Found ${staleAssets.length} stale assets:`); + staleAssets.forEach(({ asset, stale }) => { + console.warn(` - ${asset}: ${(stale / 60).toFixed(1)} minutes stale`); + }); + + await this.sendAlert({ + type: 'stale_assets', + message: `Found ${staleAssets.length} stale assets`, + staleAssets, + }); + } + + this.lastCheck = checkTime; + this.stats.lastUpdate = checkTime; + + } catch (error) { + this.stats.failures++; + this.failureCount++; + console.error(`✗ Check failed: ${error.message}`); + + if (this.failureCount >= CONFIG.alertThreshold) { + await this.sendAlert({ + type: 'monitor_error', + message: `Monitor check failed: ${error.message}`, + error: error.message, + }); + } + } + } + + async sendAlert(alert) { + this.stats.alerts++; + const alertData = { + ...alert, + timestamp: new Date().toISOString(), + keeperAddress: CONFIG.keeperAddress, + stats: this.stats, + }; + + console.error('🚨 ALERT:', alertData); + + if (CONFIG.alertWebhook) { + try { + await fetch(CONFIG.alertWebhook, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(alertData), + }); + console.log('Alert sent to webhook'); + } catch (error) { + console.error('Failed to send alert:', error.message); + } + } + } + + startHealthServer() { + const server = http.createServer((req, res) => { + if (req.url === '/health') { + res.writeHead(200, { 'Content-Type': 'application/json' }); + res.end(JSON.stringify({ + status: 'healthy', + stats: this.stats, + lastCheck: this.lastCheck?.toISOString(), + })); + } else if (req.url === '/stats') { + res.writeHead(200, { 'Content-Type': 'application/json' }); + res.end(JSON.stringify(this.stats)); + } else { + res.writeHead(404); + res.end('Not found'); + } + }); + + server.listen(3000, () => { + console.log('Health server listening on port 3000'); + }); + } + + sleep(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); + } +} + +// Main execution +if (require.main === module) { + const monitor = new KeeperMonitor(); + + process.on('SIGINT', () => { + console.log('\nStopping monitor...'); + console.log('Final stats:', monitor.stats); + process.exit(0); + }); + + monitor.start().catch(error => { + console.error('Fatal error:', error); + process.exit(1); + }); +} + +module.exports = KeeperMonitor; + diff --git a/systemd/price-feed-keeper.service b/systemd/price-feed-keeper.service new file mode 100644 index 0000000..a41f432 --- /dev/null +++ b/systemd/price-feed-keeper.service @@ -0,0 +1,35 @@ +[Unit] +Description=Price Feed Keeper Service +Documentation=https://github.com/d-bis/smom-dbis-138 +After=network.target + +[Service] +Type=simple +User=keeper +Group=keeper +WorkingDirectory=/opt/smom-dbis-138 +Environment="NODE_ENV=production" +Environment="RPC_URL_138=https://rpc.d-bis.org" +EnvironmentFile=-/etc/smom-dbis-138/keeper.env +ExecStart=/usr/bin/node scripts/reserve/keeper-service.js +Restart=always +RestartSec=10 +StandardOutput=journal +StandardError=journal +SyslogIdentifier=price-feed-keeper + +# Security settings +NoNewPrivileges=true +PrivateTmp=true +ProtectSystem=strict +ProtectHome=true +ReadWritePaths=/opt/smom-dbis-138/logs + +# Resource limits +LimitNOFILE=65536 +MemoryLimit=512M +CPUQuota=50% + +[Install] +WantedBy=multi-user.target +