CCIP icon
CCIP

Cross-chain by Chainlink

The era of secure blockchain interoperability has arrived.

A secure interoperability protocol for

enabling token transfers across blockchains
sending cross-chain messages
building cross-chain applications
enabling cross-chain real-world assets
scaling cross-chain ecosystems
connecting private and public blockchains
enabling token transfers across blockchains

Defense-in-depth security

Powered by Chainlink’s industry-standard oracle networks. Cross-Chain Interoperability Protocol (CCIP) also features additional layers of protection via the Risk Management Network and transfer rate limits.

Simplified token transfers

Seamlessly scale your userbase and benefit from enhanced token composability by securely transferring tokens across chains in a fraction of the time it would take to build a custom solution.

Programmable token transfers

Send tokens and instructions for their use to a receiving smart contract on a different blockchain—specify to swap or stake assets once they arrive at the destination chain, for example.

Reliable transaction execution

A transaction price is quoted on the source chain via a gas-locked fee payment mechanism that confirms execution regardless of destination chain gas spikes and network congestion.

Seamless integration

A single, easy-to-integrate interface for a unified cross-chain developer experience. Simply integrate CCIP onchain and start building secure cross-chain applications.

Extendable and future-proof

CCIP will continue to be updated over time to support new blockchains, enhanced functionalities, and additional defense-in-depth approaches.

Start building with Chainlink CCIP

Securely send messages, transfer tokens, and initiate actions across blockchains.

Copy icon

// The message to send cross-chain with CCIP 
struct EVM2AnyMessage {
  bytes receiver;                  // Receiver at destination
  bytes data;                      // Arbitrary data payload
  EVMTokenAmount[] tokenAmounts;   // ERC20 tokens and amounts
  address feeToken;                // Token to pay fees with
  bytes extraArgs;                 // Optional parameters
}

// Sending a message to any destination chain with CCIP
function ccipSend(
  uint64 destinationChainSelector, 
  EVM2AnyMessage calldata message) 
external
payable 
returns (bytes32 messageId);
Copy icon

// Set the tokens and amounts to transfer
Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1);
Client.EVMTokenAmount memory tokenAmount = Client.EVMTokenAmount({
  token: _addressToken,
  amount: _amount
});
tokenAmounts[0] = tokenAmount;

// Create an EVM2AnyMessage struct in memory to send via CCIP
Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({
  receiver: abi.encode(_receiver),  // Receiver (EOA) at destination
  data:  "",                        // No data to send
  tokenAmounts: tokenAmounts,       // ERC20 tokens and amounts
  extraArgs: Client._argsToBytes(   // Optional parameters
    Client.EVMExtraArgsV1({
      gasLimit: 0,                  // gasLimit = 0 because EOA
      strict: false})               // No strict sequencing
  ),
  feeToken:  address(_addressLink)  // Setting feeToken to LINK
});

// approve the Router to spend tokens on sender contract's behalf.
IERC20(addressToken).approve(address(router), _amount);

// Send the message through the router and store the returned message ID
bytes32 messageId = router.ccipSend(
  destinationChainSelector,
  message
);
 
Copy icon

// Create an EVM2AnyMessage struct in memory to send via CCIP
Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({
  receiver: abi.encode(_receiver),               // Receiver contract at destination
  data: abi.encode("Hello world!"),              // Send "Hello world!"
  tokenAmounts: new Client.EVMTokenAmount[](0),  // No tokens to be sent
  extraArgs: "",                                 // Use default values
  feeToken: address(_addressLink)                // Setting feeToken to LINK
});

// Send the message through the router and store the returned message ID
bytes32 messageId = router.ccipSend(
  destinationChainSelector,
  message
);
 

CCIP is the only interoperability protocol with level-5 security

Purpose-built for token transfers

Effortless integration 

With CCIP token transfers, your protocol can start transferring tokens across chains in a fraction of the time it would take for you to build a solution on your own. CCIP provides audited token pool contracts that handle the complexity of burning/minting or locking/minting of your token across chains. Importantly, token sponsors maintain full control over their token pool contract while using CCIP.

Secure token transfers

In addition to providing fully audited token pool smart contracts, CCIP token transfers have additional security features, such as rate limits that allow you to cap the value transferred over a given time interval. CCIP rate limits are configurable per-token-pool and per-lane and are set up in alignment with the token issuer. This feature is part of the heavily-audited CCIP code base and is only available for CCIP token transfers and not arbitrary messaging.

Enhanced composability

CCIP token transfers increase the utility of your token, helping you seamlessly scale your userbase across many chains. Tokens transferred through CCIP are highly composable, allowing your ecosystem partners to transfer and build new capabilities with your token via a single CCIP interface.

Unlock a wide variety of cross-chain use cases

Use Cases

Transfer tokens

CCIP enables users to programmatically transfer tokens from one blockchain to another via lock-and-mint or burn-and-mint mechanisms, along with attaching arbitrary data commands.

View example in docs
const tokenAmounts = [
  {
    token: tokenAddress,
    amount: amount,
  },
];

// Encoding the data

const functionSelector = ethers.utils.id("CCIP EVMExtraArgsV1").slice(0, 10);
// "extraArgs" is a structure that can be represented as [ 'uint256', 'bool' ]
// extraArgs are { gasLimit: 0, strict: false }
// we set gasLimit specifically to 0 because we are not sending any data so we are not expecting a receiving contract to handle data


const extraArgs = ethers.utils.defaultAbiCoder.encode(    
  ["uint256", "bool"],
  [0, false]
);

const
encodedExtraArgs = functionSelector + extraArgs.slice(2);

const
message = {
  receiver: ethers.utils.defaultAbiCoder.encode(
    ["address"],
    [destinationAccount]
  ),
  data: "0x", // no data
  tokenAmounts: tokenAmounts,
  feeToken: feeTokenAddress ? feeTokenAddress : ethers.constants.AddressZero, // If fee token address is provided then fees must be paid in fee token.
  extraArgs: encodedExtraArgs,
};
 

Gaming

CCIP allows interoperability between Web3 games across multiple different blockchains, which enables players on one chain to play a game against players on another chain.

View example in docs
bytes32 uniqueId = keccak256(abi.encodePacked(block.timestamp, msg.sender));
  sessionIds.push(uniqueId);
  gameSessions[uniqueId]= GameSession(
    uniqueId,
    msg.sender,
    address(0),
    address(0),

    msg.sender,
    initialCombination,
    initialCombination
    );

  sendMessage(destinationChainSelector, receiver, gameSessions[uniqueId]);

Web3 usernames

CCIP brings complete interoperability to Web3 naming protocols by enabling users to register onchain names on one chain and propagate these names across other blockchains.

View example in docs
interface ICrossChainNameServiceLookup {
  function register(string memory _name, address _address)   external;
}

function ccipReceive(
  Client.Any2EVMMessage calldata message
) external override onlyRouter onlyFromSourceChain(message.sourceChainSelector) {
  (string memory _name, address _address) = abi.decode(
    message.data,
    (string, address)
  );

  i_lookup.register(_name, _address);
}

DeFi

CCIP enables DeFi applications to use tokens on one chain as collateral for DeFi applications on another chain, unlocking native cross-chain lending markets.

View example in docs
bytes32 messageId = any2EvmMessage.messageId; // fetch the messageId
uint64 sourceChainSelector = any2EvmMessage.sourceChainSelector; // fetch the source chain identifier (aka selector)
address sender = abi.decode(any2EvmMessage.sender, (address)); // abi-decoding of the sender address

// Collect tokens transferred. This increases this contract's balance for that Token.
Client.EVMTokenAmount[] memory tokenAmounts = any2EvmMessage
  .destTokenAmounts;
address token = tokenAmounts[0].token;
uint256 amount = tokenAmounts[0].amount;

address depositor = abi.decode(any2EvmMessage.data, (address)); // abi-decoding of the depositor's address

receivedMessages.push(messageId);
MessageIn memory detail = MessageIn(
  sourceChainSelector,
  sender,
  depositor,
  token,
  amount
);
messageDetail[messageId] = detail;

// Store depositor data.
deposits[depositor][token] = amount;
 

DeFi liquidation protection

CCIP can help protect positions held in DeFi protocols across multiple chains by automatically sending assets from one chain to DeFi protocols on another chain to prevent liquidations.

View example in docs
bytes32 messageId = receivedMessage.messageId;
  uint64 sourceChainSelector = receivedMessage.sourceChainSelector;    
  address sender = abi.decode(receivedMessage.sender, (address));    
  (address tokenAddress, uint256 amount) = abi.decode(
    receivedMessage.data,
    (address, uint256)
  );

  Client.EVMTokenAmount[] memory tokenAmounts;
  tokenAmounts[1] = (Client.EVMTokenAmount(tokenAddress, amount));

  Client.EVM2AnyMessage memory messageReply = Client.EVM2AnyMessage({
    receiver: abi.encode(sender),
    data: abi.encode(messageId),
    tokenAmounts: tokenAmounts,
    extraArgs: s_chains[sourceChainSelector],
    feeToken: tokenAddress
  });

  IRouterClient(i_router).ccipSend(sourceChainSelector, messageReply);
 

Get the latest Chainlink content straight to your inbox.