# CCIP v1.6.0 SVM Messages API Reference
Source: https://docs.chain.link/ccip/api-reference/svm/v1.6.0/messages


## Messages

### SVMTokenAmount

The `SVMTokenAmount` struct captures essential information about a specific token and the transfer amount.

```rust
pub struct SVMTokenAmount {
    pub token: Pubkey,
    pub amount: u64,
}
```

**Parameters**

| Field    | Type     | Description                                                                                     |
| -------- | -------- | ----------------------------------------------------------------------------------------------- |
| `token`  | `Pubkey` | The **mint address** of the token on Solana. For example, the Mint `Pubkey` for an SPL token.   |
| `amount` | `u64`    | The number of tokens to transfer is in the token's smallest unit (often nine decimals for SPL). |

**Where it's used**:

- CCIP Sender: As part of `SVM2AnyMessage.token_amounts`
- CCIP Receiver: As part of `Any2SVMMessage.token_amounts`

## Extra Args

Below is a developer-focused API reference for the extra arguments used when sending SVM → EVM or SVM → SVM messages. These extra arguments get serialized into the `extra_args` field inside the `SVM2AnyMessage` struct. We will show:

1. The **constants** (tags), identifying each extra-args type.
2. The **struct layouts** (`EVMExtraArgsV2` and `SVMExtraArgsV1`).
3. How to **serialize** (and deserialize) these extra-args so they can be appended to the extra\_args in a CCIP message.

### Tags

You **prepend** a 4-byte "tag" inside your message, identifying which extra args to use. These tags are just constants, computed as 32-bit from a known hash:

| Constant                | Value (Hex)  | Purpose                                         |
| ----------------------- | ------------ | ----------------------------------------------- |
| `EVM_EXTRA_ARGS_V2_TAG` | `0x181dcf10` | Denotes `EVMExtraArgsV2` (SVM → EVM extra args) |
| `SVM_EXTRA_ARGS_V1_TAG` | `0x1f3b3aba` | Denotes `SVMExtraArgsV1` (SVM → SVM extra args) |

### `EVMExtraArgsV2`

When sending a message **from SVM-based blockchains (e.g., Solana) to EVM-based blockchains (e.g., Ethereum)**, you can supply extra parameters such as a per-message `gas_limit`. This is particularly relevant for an EVM-based destination that requires enough gas to call the receiver contract.

```rust
/// `bytes4(keccak256("CCIP EVMExtraArgsV2"))` = `0x181dcf10`
pub const EVM_EXTRA_ARGS_V2_TAG: u32 = 0x181dcf10;

#[derive(Clone, AnchorSerialize, AnchorDeserialize, Default)]
pub struct EVMExtraArgsV2 {
    pub gas_limit: u128,                    // message gas limit for EVM execution
    pub allow_out_of_order_execution: bool, // user-configurable OOO execution
}
```

**Parameters**

| Field                          | Type   | Description                                                                                                                                                      |
| ------------------------------ | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `gas_limit`                    | `u128` | The exact **gas limit** to call the `ccipReceive` function of the Receiver contract. If your Receiver contract needs 50,000 gas to run, set `gas_limit = 50000`. |
| `allow_out_of_order_execution` | `bool` | If `true`, you let CCIP process the message in a potentially **out-of-order** manner.                                                                            |

Below is a Rust function showing how to serialize an `EVMExtraArgsV2`:

```rust
fn create_evm_extra_args(gas_limit: u128, ooo: bool) -> Vec<u8> {
    use anchor_lang::AnchorSerialize;
    let data = EVMExtraArgsV2 {
        gas_limit,
        allow_out_of_order_execution: ooo,
    };
    // 1) Start with the 4-byte tag, big-endian
    let mut buffer = EVM_EXTRA_ARGS_V2_TAG.to_be_bytes().to_vec();
    // 2) Serialize the struct via Borsh
    let mut serialized = data.try_to_vec().unwrap();
    // 3) Append the serialized payload
    buffer.append(&mut serialized);
    buffer
}
```

### `SVMExtraArgsV1`

If your destination is another SVM-based blockchain, the extra args can define `compute_units`, an accounts list, and whether you allow out-of-order execution, among other fields.

```rust
/// `bytes4(keccak256("CCIP SVMExtraArgsV1"))` = `0x1f3b3aba`
pub const SVM_EXTRA_ARGS_V1_TAG: u32 = 0x1f3b3aba;

#[derive(Clone, AnchorSerialize, AnchorDeserialize, Default)]
pub struct SVMExtraArgsV1 {
    pub compute_units: u32,                 // Offchain usage for compute budget
    pub account_is_writable_bitmap: u64,    // Bitmask describing which accounts are writable
    pub allow_out_of_order_execution: bool, // Must match the receiving chain config if OOO
    pub token_receiver: [u8; 32],           // If tokens are sent, cannot be the 0-address
    pub accounts: Vec<[u8; 32]>,            // Additional accounts for SVM cross-program calls
}
```

**Parameters**

| Field                          | Type            | Description                                                                                                                                                                                                                                        |
| ------------------------------ | --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `compute_units`                | `u32`           | An optional override determines how many compute units the destination OffRamp should set.                                                                                                                                                         |
| `account_is_writable_bitmap`   | `u64`           | A bitmask marking which `accounts` entries are writable (bit = 1) vs. read-only (bit = 0). For example, if the 2nd bit is set, the underlying on-chain program treats `accounts[1]` as writable.                                                   |
| `allow_out_of_order_execution` | `bool`          | Whether this cross-chain message may be executed out of order (OOO). If `true`, the normal strict sequence requirement can be bypassed, allowing the chain to process it earlier/later.                                                            |
| `token_receiver`               | `[u8; 32]`      | A Solana Pubkey (32 bytes) that receives tokens if the cross-chain message includes token transfers. If so, this field must be nonzero. Typically, the Associated Token Account (ATA) of the receiver. Set this to \[0; 32] if no tokens are sent. |
| `accounts`                     | `Vec<[u8; 32]>` | A list of additional accounts (each a 32-byte Solana `Pubkey`) that the transaction needs to reference on the destination chain. These might be program IDs to invoke, PDAs storing state, or other required accounts.                             |

Below is a Rust function showing how to serialize an `SVMExtraArgsV1`:

```rust
fn create_svm_extra_args(
    compute_units: u32,
    account_is_writable_bitmap: u64,
    allow_ooo: bool,
    token_receiver: [u8; 32],
    accounts: Vec<[u8; 32]>,
) -> Vec<u8> {
    use anchor_lang::AnchorSerialize;

    let data = SVMExtraArgsV1 {
        compute_units,
        account_is_writable_bitmap,
        allow_out_of_order_execution: allow_ooo,
        token_receiver,
        accounts,
    };

    // 1) Start with the 4-byte tag, big-endian
    let mut buffer = SVM_EXTRA_ARGS_V1_TAG.to_be_bytes().to_vec();

    // 2) Serialize the struct via Borsh (AnchorSerialize)
    let mut serialized = data.try_to_vec().unwrap();

    // 3) Append the serialized payload
    buffer.append(&mut serialized);
    buffer
}
```

## Message Structures

### SVM2AnyMessage

When you send a cross-chain message from SVM-based blockchains to another blockchain, the `SVM2AnyMessage` struct packages all necessary data: destination address, payload, tokens, fees, and any extra arguments.

```rust
pub struct SVM2AnyMessage {
    pub receiver: Vec<u8>,
    pub data: Vec<u8>,
    pub token_amounts: Vec<SVMTokenAmount>,
    pub fee_token: Pubkey,
    pub extra_args: Vec<u8>,
}
```

**Parameters**

| Field           | Type                  | Description                                                                                              |
| --------------- | --------------------- | -------------------------------------------------------------------------------------------------------- |
| `receiver`      | `Vec<u8>`             | The destination address in raw byte format (since different blockchains have different address lengths). |
| `data`          | `Vec<u8>`             | Arbitrary payload to be parsed by the receiver on the destination blockchain.                            |
| `token_amounts` | `Vec<SVMTokenAmount>` | List of tokens to transfer.                                                                              |
| `fee_token`     | `Pubkey`              | Mint of the fee token used to pay cross-chain fees. Use `Pubkey::default()` if paying with native SOL.   |
| `extra_args`    | `Vec<u8>`             | Additional arguments or metadata (Read Extra Args for more details).                                     |

### Any2SVMMessage

When the OffRamp executes a cross-chain message into an SVM-based blockchain (e.g., Solana), it provides an `Any2SVMMessage` to the receiving program. This struct lets you verify the source, handle tokens, and parse the payload.

```rust
pub struct Any2SVMMessage {
    pub message_id: [u8; 32],
    pub source_chain_selector: u64,
    pub sender: Vec<u8>,
    pub data: Vec<u8>,
    pub token_amounts: Vec<SVMTokenAmount>,
}
```

**Parameters**

| Field                   | Type                  | Description                                                                   |
| ----------------------- | --------------------- | ----------------------------------------------------------------------------- |
| `message_id`            | `[u8; 32]`            | Unique 32-byte ID for this cross-chain message.                               |
| `source_chain_selector` | `u64`                 | Indicates which blockchain the message originated from.                       |
| `sender`                | `Vec<u8>`             | The sender's address on the source blockchain, in raw byte format.            |
| `data`                  | `Vec<u8>`             | Arbitrary payload to be parsed by the receiver on the destination blockchain. |
| `token_amounts`         | `Vec<SVMTokenAmount>` | If tokens are bridged, they appear here, along with how many.                 |

### SVM2AnyRampMessage

When sending a cross-chain message from a Solana-compatible (SVM) blockchain to a destination chain (EVM, SVM, etc.), the `SVM2AnyRampMessage` struct describes all necessary data and token information. It’s typically constructed inside the ccip\_send call.

```rust
#[derive(Clone, AnchorSerialize, AnchorDeserialize)]
pub struct SVM2AnyRampMessage {
    pub header: RampMessageHeader,
    pub sender: Pubkey,
    pub data: Vec<u8>,
    pub receiver: Vec<u8>,
    pub extra_args: Vec<u8>,
    pub fee_token: Pubkey,
    pub token_amounts: Vec<SVM2AnyTokenTransfer>,
    pub fee_token_amount: CrossChainAmount,
    pub fee_value_juels: CrossChainAmount,
}
```

**Parameters**

| Field              | Type                        | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| ------------------ | --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `header`           | `RampMessageHeader`         | Metadata about the message: `message_id`, `source_chain_selector`, `dest_chain_selector`, `sequence_number`, `nonce`.                                                                                                                                                                                                                                                                                                                                                                                     |
| `sender`           | `Pubkey`                    | The sender's Solana Pubkey (32 bytes) on the source chain, representing the wallet or program that invoked `ccip_send`.                                                                                                                                                                                                                                                                                                                                                                                   |
| `data`             | `Vec<u8>`                   | Arbitrary payload data.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `receiver`         | `Vec<u8>`                   | The destination address in raw bytes. For example, if it's an EVM chain, this might be 20 bytes (the EVM contract address). If it's an SVM chain, it might be 32 bytes (a Solana Pubkey).                                                                                                                                                                                                                                                                                                                 |
| `extra_args`       | `Vec<u8>`                   | Serialized "extra arguments" relevant to the destination.                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `fee_token`        | `Pubkey`                    | Mint of the token used to pay the cross-chain fees.                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| `token_amounts`    | `Vec<SVM2AnyTokenTransfer>` | List of tokens locked or burned as part of this cross-chain message. Each `SVM2AnyTokenTransfer` in the array has: `source_pool_address` (the source pool address that locked/burned these tokens), `dest_token_address` (the byte address for the destination token contract), `extra_data` (optional data attached to this token transfer), `amount` (how many tokens are locked on Solana, denominated in the source token's decimals), and `dest_exec_data` (destination-chain execution parameters). |
| `fee_token_amount` | `CrossChainAmount`          | The billing token amount (in local chain decimals) was ultimately charged as a fee.                                                                                                                                                                                                                                                                                                                                                                                                                       |
| `fee_value_juels`  | `CrossChainAmount`          | The fees are converted to Juels.                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |