当前位置: 首页 > news >正文

轻松上手 Chainlink CCIP:Sepolia → BSC Testnet 跨链消息全流程 - 若

CCIP 简介(超简)

  • CCIP(Cross-Chain Interoperability Protocol):Chainlink 推出的跨链消息与资产传输协议。
  • 本示例:在 Ethereum Sepolia 上发送一条文本消息,经 CCIP 路由传到 BSC Testnet 并被目标链合约接收与解码。

架构与流程

  • 源链:Sepolia;合约:Sender
  • 目标链:BSC Testnet;合约:Receiver
  • 流程:Sender.sendMessage(...) → CCIP 路由跨链 → Receiver._ccipReceive(...) 解码与记录

快速上手步骤(概览)

  • 在 BSC Testnet 部署 Receiver(构造写死 Router 地址)
  • 在 Sepolia 部署 Sender(构造写死 Router 与 LINK 地址)
  • Sender 合约转入足量 LINK → 调 sendMessage(chainSelector, receiver, "hello")
  • 在 BSC Testnet 监听 MessageReceived 或读 getLastReceivedMessageDetails()

源码:Receiver(BSC Testnet 接收)

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;import {Client} from "@chainlink/contracts-ccip@1.6.0/contracts/libraries/Client.sol";
import {CCIPReceiver} from "@chainlink/contracts-ccip@1.6.0/contracts/applications/CCIPReceiver.sol";/*** THIS IS AN EXAMPLE CONTRACT THAT USES HARDCODED VALUES FOR CLARITY.* THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE.* DO NOT USE THIS CODE IN PRODUCTION.*/
/**
bsc测试网接收消息
1. 部署合约
**//// @title - A simple contract for receiving string data across chains.
contract Receiver is CCIPReceiver {// Event emitted when a message is received from another chain.event MessageReceived(bytes32 indexed messageId, // The unique ID of the message.uint64 indexed sourceChainSelector, // The chain selector of the source chain.address sender, // The address of the sender from the source chain.string text // The text that was received.);bytes32 private s_lastReceivedMessageId; // Store the last received messageId.string private s_lastReceivedText; // Store the last received text./// @notice Constructor initializes the contract with the router address./// 写死bsc testnet的router:0xE1053aE1857476f36A3C62580FF9b016E8EE8F6fconstructor() CCIPReceiver(0xE1053aE1857476f36A3C62580FF9b016E8EE8F6f) {}/// handle a received messagefunction _ccipReceive(Client.Any2EVMMessage memory any2EvmMessage) internal override {s_lastReceivedMessageId = any2EvmMessage.messageId; // fetch the messageIds_lastReceivedText = abi.decode(any2EvmMessage.data, (string)); // abi-decoding of the sent textemit MessageReceived(any2EvmMessage.messageId,any2EvmMessage.sourceChainSelector, // fetch the source chain identifier (aka selector)abi.decode(any2EvmMessage.sender, (address)), // abi-decoding of the sender address,abi.decode(any2EvmMessage.data, (string)));}/// @notice Fetches the details of the last received message./// @return messageId The ID of the last received message./// @return text The last received text.function getLastReceivedMessageDetails()externalviewreturns (bytes32 messageId, string memory text){return (s_lastReceivedMessageId, s_lastReceivedText);}
}

源码:Sender(Sepolia 发送)

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;import {IRouterClient} from "@chainlink/contracts-ccip@1.6.0/contracts/interfaces/IRouterClient.sol";
import {OwnerIsCreator} from "@chainlink/contracts@1.4.0/src/v0.8/shared/access/OwnerIsCreator.sol";
import {Client} from "@chainlink/contracts-ccip@1.6.0/contracts/libraries/Client.sol";
import {LinkTokenInterface} from "@chainlink/contracts@1.4.0/src/v0.8/shared/interfaces/LinkTokenInterface.sol";/*** THIS IS AN EXAMPLE CONTRACT THAT USES HARDCODED VALUES FOR CLARITY.* THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE.* DO NOT USE THIS CODE IN PRODUCTION.*//**
从sepolia发送消息给bsc测试网
1. 部署合约
2. 给合约转账70link
**//// @title - A simple contract for sending string data across chains.
contract Sender is OwnerIsCreator {// Custom errors to provide more descriptive revert messages.error NotEnoughBalance(uint256 currentBalance, uint256 calculatedFees); // Used to make sure contract has enough balance.// Event emitted when a message is sent to another chain.event MessageSent(bytes32 indexed messageId, // The unique ID of the CCIP message.uint64 indexed destinationChainSelector, // The chain selector of the destination chain.address receiver, // The address of the receiver on the destination chain.string text, // The text being sent.address feeToken, // the token address used to pay CCIP fees.uint256 fees // The fees paid for sending the CCIP message.);IRouterClient private s_router;LinkTokenInterface private s_linkToken;/// @notice Constructor initializes the contract with the router address.constructor() {// 写死sepolia的router和link地址address _router =0x0BF3dE8c5D3e8A2B34D2BEeB17ABfCeBaf363A59;address _link =  0x779877A7B0D9E8603169DdbD7836e478b4624789;s_router = IRouterClient(_router);s_linkToken = LinkTokenInterface(_link);}/// @notice Sends data to receiver on the destination chain./// @dev Assumes your contract has sufficient LINK./// @param destinationChainSelector The identifier (aka selector) for the destination blockchain./// @param receiver The address of the recipient on the destination blockchain./// @param text The string text to be sent./// @return messageId The ID of the message that was sent.function sendMessage(uint64 destinationChainSelector,address receiver,string calldata text) external onlyOwner returns (bytes32 messageId) {// Create an EVM2AnyMessage struct in memory with necessary information for sending a cross-chain messageClient.EVM2AnyMessage memory evm2AnyMessage = Client.EVM2AnyMessage({receiver: abi.encode(receiver), // ABI-encoded receiver addressdata: abi.encode(text), // ABI-encoded stringtokenAmounts: new Client.EVMTokenAmount[](0), // Empty array indicating no tokens are being sentextraArgs: Client._argsToBytes(// Additional arguments, setting gas limit and allowing out-of-order execution.// Best Practice: For simplicity, the values are hardcoded. It is advisable to use a more dynamic approach// where you set the extra arguments off-chain. This allows adaptation depending on the lanes, messages,// and ensures compatibility with future CCIP upgrades. Read more about it here: https://docs.chain.link/ccip/concepts/best-practices/evm#using-extraargsClient.GenericExtraArgsV2({gasLimit: 200_000, // Gas limit for the callback on the destination chainallowOutOfOrderExecution: true // Allows the message to be executed out of order relative to other messages from the same sender})),// Set the feeToken  address, indicating LINK will be used for feesfeeToken: address(s_linkToken)});// Get the fee required to send the messageuint256 fees = s_router.getFee(destinationChainSelector,evm2AnyMessage);if (fees > s_linkToken.balanceOf(address(this)))revert NotEnoughBalance(s_linkToken.balanceOf(address(this)), fees);// approve the Router to transfer LINK tokens on contract's behalf. It will spend the fees in LINKs_linkToken.approve(address(s_router), fees);// Send the message through the router and store the returned message IDmessageId = s_router.ccipSend(destinationChainSelector, evm2AnyMessage);// Emit an event with message detailsemit MessageSent(messageId,destinationChainSelector,receiver,text,address(s_linkToken),fees);// Return the message IDreturn messageId;}
}

实战提示(简版)

  • 确认两链的 CCIP Router 地址与 Chain Selector 为官方最新值。
  • feeToken 使用 LINK 时,需要先将 LINK 转入 Sender 合约,并 approve 费用。
  • gasLimit 需与接收逻辑复杂度匹配;开启 allowOutOfOrderExecution 时注意幂等与去重(用 messageId)。

如果需要,我可以补充一份一键部署与调用的脚本(Hardhat/Foundry),并附上常用测试网的 chain selector 与 Router 地址清单,帮助你从部署到演示全流程跑通。

http://www.sczhlp.com/news/71866/

相关文章:

  • 2025年SE Labs大奖:Sophos端点安全技术荣获四项殊荣
  • 小波域稀疏表示与正交匹配追踪算法压缩感知重建
  • VK1640B点阵LED驱动控制专用芯片数显驱动控制器原厂
  • LINUX--a free unix-386 kernel
  • 电子商务网站建设的核心硬件江苏省城乡和建设厅网站首页
  • 船山网站建设手机平台软件开发
  • 做海岛旅游类网站的背景及意义网站头部导航
  • 简单学校网站模板wordpress 登录 缓存
  • 网站开发流程管理河南开封网站建设
  • 北京哪有建网站公司或个人的网站建设协议书是否贴花
  • 建设一个网站需要注意的事项网站开发公司规章制度
  • 长沙市做网站性价比最高网站建设
  • 哪里提供邢台做网站vps云服务器免费
  • 仿土豆网站源码网站开发任务分解
  • 做响应式网站设计师如何布局呢用html制作个人网页
  • 一个域名访问不同的网站kali 搭建wordpress
  • 专业建设验收网站南昌企业建设网站开发
  • 通用网站模板网站备案 信息
  • 青岛市城市建设投标网站wordpress首页广告
  • 河北省住房建设厅网站首页做销售在哪些网站发贴
  • 天眼查公司注册信息seo推广培训中心
  • 网站设计主要包含3个方面个人怎么注册域名
  • 白山市城乡建设局网站seo服务销售招聘
  • 泰安口碑好的网站建设银川网站建设哪家优质
  • Collections
  • 读书笔记:白话解读Oracle嵌套表:像套娃一样存储数据
  • 用 Chainlink Data Feeds 打造“即插即用”的上链数据读取:从价格,到收益率,再到智能数据 - 若
  • 故障分析:常见坏块分类,dbv报错代码:6106
  • 网站免费建站k哈尔滨建站优化定制
  • 如何申请建设个人网站台州永建建设有限公司网站