Note
This repository represents an example of using a Chainlink product or service. It is provided to help you understand how to interact with Chainlink's systems so that you can integrate them into your own. This template is provided "AS IS" without warranties of any kind, has not been audited, and may be missing key checks or error handling to make the usage of the product more clear. Take everything in this repository as an example and not something to be copy pasted into a production ready service.
Disclaimer: Please note, this repo contains community examples only — these are not Chainlink products or services and are not supported or maintained by Chainlink. This code represents an example of using a Chainlink product or service, and is intended for demonstration and educational purposes only. It is provided “AS IS” and “AS AVAILABLE” without warranties of any kind, may not have been audited, and may omit checks or error handling. Each party intending to use this example code does so entirely at their own risk and must perform its own audits, security and code review, key management, and testing before any production deployment and ensure the operation and performance of such code matches expectations. Neither Chainlink Labs nor the Chainlink Foundation deploys, operates, monitors, maintains or endorses any deployment of this code. Note that this is not a Chainlink product, feature or service, and there are no commitments made with respect to the code, including compatibility with future Chainlink releases. You should not rely on this code without first conducting your own technical, engineering, and security review. This code is also outside the scope of any Chainlink bug bounty programs. Neither Chainlink Labs, the Chainlink Foundation, nor Chainlink node operators are responsible for outcomes due to errors in this example or how it is deployed or operated, or liable for any resulting claims or damages. Use of the Chainlink Network is subject to the Chainlink Foundation Terms of Service, which provides important information and disclosures. By using this code, you acknowledge and agree to these terms.
Reference starter kit for learning and testing CCIP v2 with Hardhat 3: tasks, Ignition deployments, Solidity contracts, and SDK examples.
Examples 01–10 use Ethereum Sepolia → Polygon Amoy as their primary CCIP 2.0 lane. Example 01, Example 03, and Example 04 use faucet-issued CCIP-BnM. Examples 06–10 teach custom token and pool deployment. The legacy chapters retain their older-lane demonstrations.
The primary documentation lives in the book. Run it locally:
mdbook serve book --opentasks/— Hardhat tasks for CCIP examples (e.g.example01,example02,faucet) and helpers (e.g.erc20-balance-of,get-allow-list). Task definitions are intasks/hardhat.tasks.ts.ignition/— Hardhat Ignition modules and parameter files for deploying receivers, senders, and token pools. Fill inignition/paramsEthSepolia.jsonandignition/paramsAmoy.jsonwith chain addresses before deploying.contracts/— Solidity contracts used by the examples.test/— Node.js tests that run the example tasks against the Chainlink Local V3 simulator.test-fork/— Fork tests for the CCT examples (Examples 06–10) on Ethereum Sepolia → Polygon Amoy.book/src/— Step-by-step tutorial chapters (mdbook source).sdk-examples/— Minimal CCIP SDK demos (ccip-send,ccip-track).
-
Keystore — Set private keys and RPC URLs for the networks you use:
npx hardhat keystore set SEPOLIA_PRIVATE_KEY npx hardhat keystore set AMOY_PRIVATE_KEY npx hardhat keystore set SEPOLIA_RPC_URL npx hardhat keystore set AMOY_RPC_URL
-
Ignition parameters — Edit
ignition/paramsEthSepolia.jsonandignition/paramsAmoy.json: replace the placeholder values (<ROUTER_ADDRESS>, etc.) with the correct addresses for each chain (e.g. from the CCIP Directory). -
Run examples — Start with the faucet and Example 01. Use Example 06 when you want to deploy your own CCT. The
faucettask also serves the legacy token examples.
List all tasks:
npx hardhat --helpThe tests in test/ run the real example tasks (tasks/Example01.ts ... Example05.ts) and the example contracts against the Chainlink Local V3 no-fork simulator, so no RPC URLs or keys are needed:
npx hardhat test nodejsChainlink Local is single-chain and has no token pools, CCV verifiers, executors or manual execution. It does enforce the CCIP 2.0 finality rules, one token per message, and receiver CCV config validation.
Chainlink Local's no-fork mode has no token pools or TokenAdminRegistry, so the CCT examples (Examples 06–10) are tested in test-fork/ instead. They run the real Ignition modules and tasks against forks of Ethereum Sepolia and Polygon Amoy, then route each message to the destination OffRamp with the Chainlink Local fork helper. They are not part of npx hardhat test nodejs.
Requirements:
-
Archive-capable RPC URLs for both chains (a free-tier Alchemy or Infura endpoint works; public non-archive endpoints fail with "historical state is not available"). Provide them as environment variables or in the Hardhat keystore:
npx hardhat keystore set ETHEREUM_SEPOLIA_RPC_URL npx hardhat keystore set POLYGON_AMOY_RPC_URL
-
The
productionbuild profile: the token pools exceed the 24 KB contract size limit without the optimizer. Thetest:forkscript sets it.
npm run test:forkBoth forks are pinned to a block (forking.blockNumber in hardhat.config.ts) so a fresh clone runs the same chain state. Override the pins for a run with ETHEREUM_SEPOLIA_FORK_BLOCK and POLYGON_AMOY_FORK_BLOCK, for example to check whether the live lane has drifted. Pinned state never sees testnet upgrades, so green tests only prove the examples against that snapshot.