# CCIP Message Format

## Overview

This document describes the message format used for CCIP cross-chain oracle updates.

## Message Structure

CCIP messages contain encoded oracle data in the following format:

```solidity
struct OracleMessage {
    uint256 answer;      // Oracle price/answer (scaled by 10^8)
    uint256 roundId;     // Round ID for this update
    uint256 timestamp;   // Unix timestamp of the update
}
```

## Encoding

Messages are encoded using ABI encoding:

```solidity
bytes memory messageData = abi.encode(answer, roundId, timestamp);
```

## Decoding

On the receiving chain, messages are decoded:

```solidity
(uint256 answer, uint256 roundId, uint256 timestamp) = abi.decode(message.data, (uint256, uint256, uint256));
```

## Example

### Sending Message

```solidity
uint256 price = 25000000000; // $250.00 (scaled by 10^8)
uint256 roundId = 12345;
uint256 timestamp = block.timestamp;

bytes memory messageData = abi.encode(price, roundId, timestamp);

CCIPSender sender = CCIPSender(senderAddress);
uint256 fee = sender.calculateFee(targetChainSelector, messageData);
sender.sendOracleUpdate{value: fee}(targetChainSelector, receiverAddress, messageData);
```

### Receiving Message

```solidity
function ccipReceive(
    IRouterClient.Any2EVMMessage calldata message
) external onlyRouter {
    (uint256 answer, uint256 roundId, uint256 timestamp) = abi.decode(
        message.data,
        (uint256, uint256, uint256)
    );
    
    // Update oracle
    updateOracle(answer, roundId, timestamp);
}
```

## Data Types

### Answer (uint256)

- Oracle price/value
- Scaled by 10^8 (8 decimal places)
- Example: $250.00 = 25000000000

### Round ID (uint256)

- Sequential round identifier
- Increments with each update
- Used for ordering and deduplication

### Timestamp (uint256)

- Unix timestamp (seconds since epoch)
- When the price was observed
- Used for staleness checks

## Message Size

Typical message size: ~96 bytes (3 * 32 bytes)

Maximum recommended size: 256 bytes

## Validation

Before processing, validate:

1. **Message ID**: Check for replay attacks
2. **Source Chain**: Verify source chain selector
3. **Sender**: Verify sender address is authorized
4. **Timestamp**: Check timestamp is recent
5. **Round ID**: Ensure round ID is sequential

## Error Handling

### Invalid Format

If message cannot be decoded:

```solidity
try abi.decode(message.data, (uint256, uint256, uint256)) returns (uint256, uint256, uint256) {
    // Process message
} catch {
    // Log error and reject message
    emit InvalidMessageFormat(message.messageId);
    return;
}
```

### Stale Data

Check timestamp is recent:

```solidity
require(block.timestamp - timestamp < MAX_STALENESS, "Data too stale");
```

### Invalid Round ID

Ensure round ID is sequential:

```solidity
require(roundId > lastRoundId, "Invalid round ID");
```

## Security Considerations

1. **Replay Protection**: Track processed message IDs
2. **Source Validation**: Verify source chain and sender
3. **Data Validation**: Validate all fields before processing
4. **Access Control**: Only authorized contracts can receive messages

## References

- [CCIP Integration Guide](CCIP_INTEGRATION.md)
- [CCIP Router Setup](CCIP_ROUTER_SETUP.md)
- [Chainlink CCIP Documentation](https://docs.chain.link/ccip)
