Files
smom-dbis-138/docs/ccip/archive-import/developer-guides/CCIP_INTEGRATION_GUIDE.md
2026-06-02 05:59:06 -07:00

6.9 KiB

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

// 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

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

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

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

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

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

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

// 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

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

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


Last Updated: 2025-01-27