链路本地链接
链路本地化是一个可安装的依赖. 它提供了一个工具(Chainlink Local Simulator),开发者会将它导入到他们的创建或Hardhat或Remix项目. 此工具运行 链路 CCIP 本地意味着开发者可以在本地环境中快速地探索,原型并网罗出CCIP dApps出链,只有当他们准备在活的环境下进行测试时才能移动到测试网.
该套件暴露出一套智能合同和脚本,您在本地的Remix,Hardhat或Anvil(Foundry)开发节点上,用这些合同和脚本构建,部署和执行CCIP令牌传输和任意消息. 链路本地端也支持要塞.
与链路本地公司进行测试的用户合同可以在不作任何修改的情况下部署到测试网络(假设网络特定合同地址,如路由器合同和LINK标志地址通过构建器传递).
欲了解更详细的文件和更多实例,请访问 链路链接本地文档。 。 。 .
安装
0.3.x (V3)支持Foundry,Hardhat 3和Remix IDE. Hardhat 2 用户应该保持 0.2.x
(单位:千美元)npm install @chainlink/[email protected]) (中文(简体) ).
创建( git)
forge install smartcontractkit/[email protected]
然后设置重映射到: @chainlink/local/=lib/chainlink-local/ 任意 remappings.txt 或者说 foundry.toml 文件
创始人( Soldeer)
forge soldeer install chainlink-local~v0.3.0 https://github.com/smartcontractkit/chainlink-local.git
哈德哈特语 3 (npm)
npm install @chainlink/[email protected]
Hardhat 3 (Node.js 22) 固态性测试不需要再映射:包件自发出行 remappings.txt,以及
打开齐柏林飞艇和 forge-std 依赖性与它相接。 需要叉子测试 evmVersion: "cancun" 或较后:
// hardhat.config.ts
import { defineConfig } from "hardhat/config";
export default defineConfig({
solidity: { version: "0.8.24", settings: { evmVersion: "cancun" } },
});
npx hardhat test solidity
用于JavaScript/TypeScript叉帮助器(@chainlink/local/scripts/CCIPLocalSimulatorFork.js),并安装和
注册 edes 插件,并添加要塞网络:
npm install --save-dev @nomicfoundation/hardhat-ethers ethers
import { configVariable, defineConfig } from "hardhat/config";
import hardhatEthers from "@nomicfoundation/hardhat-ethers";
export default defineConfig({
plugins: [hardhatEthers],
solidity: { version: "0.8.24", settings: { evmVersion: "cancun" } },
networks: {
sepoliaFork: {
type: "edr-simulated",
chainType: "generic",
chainId: 11155111,
forking: { url: configVariable("ETHEREUM_SEPOLIA_RPC_URL") },
},
},
});
铸币局(npm)
从 npm 安装到创建工程中; 在您中列出软件包的依赖性 remappings.txt
(Foundry不将软件包的再绘图装入 node_modules:
@chainlink/local/=node_modules/@chainlink/local/
@chainlink/contracts-ccip/=node_modules/@chainlink/contracts-ccip/
@chainlink/contracts/=node_modules/@chainlink/contracts/
@openzeppelin/[email protected]/=node_modules/@openzeppelin/contracts-4.8.3/
@openzeppelin/[email protected]/=node_modules/@openzeppelin/contracts-5.3.0/
forge-std/=node_modules/forge-std/src/
Remix IDE( 本地模式)
import "https://github.com/smartcontractkit/chainlink-local/blob/v0.3.0/src/ccip/CCIPLocalSimulator.sol";
调和解析 @chainlink/contracts 财务报告和审定财务报表 @chainlink/contracts-ccip 导入其最新 npm 版本.
一旦您安装了 CCIP Local, 您现在可以开始使用您的项目 .
使用量
导入 CCIPLocalSimulator.sol 例如,在测试或脚本中(这是
测试/ smoke/cip/ReadmeUsage 实例. t. sol:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import {Test} from "forge-std/Test.sol";
import {
CCIPLocalSimulator,
IRouterClient,
WETH9,
LinkToken,
BurnMintERC677Helper
} from "@chainlink/local/src/ccip/CCIPLocalSimulator.sol";
import {Client} from "@chainlink/contracts-ccip/contracts/libraries/Client.sol";
import {ExtraArgsCodec} from "@chainlink/contracts-ccip/contracts/libraries/ExtraArgsCodec.sol";
import {FinalityCodec} from "@chainlink/contracts-ccip/contracts/libraries/FinalityCodec.sol";
contract ReadmeUsageExampleTest is Test {
CCIPLocalSimulator public ccipLocalSimulator;
uint64 public chainSelector;
IRouterClient public sourceRouter;
LinkToken public linkToken;
BurnMintERC677Helper public ccipBnM;
function setUp() public {
ccipLocalSimulator = new CCIPLocalSimulator();
WETH9 wrappedNative;
IRouterClient destinationRouter;
BurnMintERC677Helper ccipLnM;
(chainSelector, sourceRouter, destinationRouter, wrappedNative, linkToken, ccipBnM, ccipLnM) =
ccipLocalSimulator.configuration();
}
function test_sendTokens() public {
address alice = makeAddr("alice");
address bob = makeAddr("bob");
ccipLocalSimulator.requestLinkFromFaucet(alice, 5 ether);
ccipBnM.drip(alice);
Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1);
tokenAmounts[0] = Client.EVMTokenAmount({token: address(ccipBnM), amount: 1 ether});
// Fast Transfers example with 5 block confirmations
uint32 gasLimit = 0;
uint16 blockConfirmations = 5;
bytes4 finalityConfig = FinalityCodec._encodeBlockDepth(blockConfirmations);
bytes memory extraArgsBytes = ExtraArgsCodec._getBasicEncodedExtraArgsV3(gasLimit, finalityConfig);
Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({
receiver: abi.encode(bob),
data: "",
tokenAmounts: tokenAmounts,
extraArgs: extraArgsBytes,
feeToken: address(linkToken)
});
vm.startPrank(alice);
uint256 fee = sourceRouter.getFee(chainSelector, message);
linkToken.approve(address(sourceRouter), fee);
ccipBnM.approve(address(sourceRouter), 1 ether);
sourceRouter.ccipSend(chainSelector, message);
vm.stopPrank();
assertEq(ccipBnM.balanceOf(bob), 1 ether);
}
}
分叉模式和 CCIP 2.0
CCIPLocalSimulatorFork 每个CCIP时代的叉线网络上的路由信息:1.6前(EVM2EVMOnRamp页:1
CCIP 2.0 (基于CCV的车道,即今天运行的活测试网车道). 叉口测试要求:
- 编译叉测试
evm_version = "cancun"或后来(部署的CCIP 2.0合同使用坎昆操作码;paris失败EvmError: NotActivated) (中文(简体) ). 使用仅分叉配置文件, 这样您部署的字节代码不会受到影响 :[profile.fork]与evm_version = "cancun"内foundry.toml,则FOUNDRY_PROFILE=fork forge test。 。 。 . - 创始人QQ 1.5.1分叉测试(Hardhat 3需要Node.js 22).
CCIPLocalSimulatorFork ccipLocalSimulatorFork = new CCIPLocalSimulatorFork();
vm.makePersistent(address(ccipLocalSimulatorFork));
// Send through the router returned by getNetworkDetails(block.chainid).routerAddress, or through the dedicated
// CCIP 2.0 router where one exists: ccipLocalSimulatorFork.getCCIPV2RouterAddress(block.chainid).
// ...ccipSend(...)
ccipLocalSimulatorFork.switchChainAndRouteMessage(destinationForkId);
运行在默认情况下是严格的: switchChainAndRouteMessage 返回为
CCIPLocalSimulatorFork__MessageNotRouted(messageId, reason) 当一个抓取的信件无法被引导到任何给定的
叉子,还有 CCIPLocalSimulatorFork__MessageExecutionFailed(messageId, reason) (解码回放数据)当它发生时
未成功执行 。 打电话 setStrictRouting(false) 来记录失败,然后用
getMessageStatus(messageId)。有好几个目的地,或者一次通过每个目的地的叉子
uint256[] forkIds 超载或呼叫 switchChainAndRouteMessage 每分叉一次: 1.6或 2.0 个消息
不在呼叫中的链条 QUEUED 并且通过包括目的地分叉在内的呼唤.
Hardhat 3 JavaScript/ TypeScript 测试可以用同样的方式进行 scripts/CCIPLocalSimulatorFork.js (所需经费)
@nomicfoundation/hardhat-ethers; TypeScript申报船旁边:
import { network } from "hardhat";
import { getCCIPMessages, routeMessage } from "@chainlink/local/scripts/CCIPLocalSimulatorFork.js";
const source = await network.connect({ network: "sepoliaFork" });
const destination = await network.connect({ network: "arbitrumSepoliaFork" });
const receipt = await (await sourceRouter.ccipSend(destChainSelector, message, { value: fee })).wait();
const [sent] = getCCIPMessages(source, receipt);
await routeMessage(destination, destinationRouterAddress, sent);
| 环境 | 0.3.x (单位:千美元) | 0.2.x (中文(简体) ) |
|---|---|---|
| Hardhat 3 (团结测试,本地+分叉) | ✅ | 仅创建 |
| Hardhat 3 JavaScript/ TypeScript 帮助器 | ✅ | - 说吧 |
| 哈达特2 | - (不支持:Hardhat 2不能解决 @openzeppelin/[email protected]/ 样式导入) | 只使用前1.6分叉路由 |
| Remix IDE( 本地模式) | ✅ | ✅ |
在CCIP 2.0道上,目的地OffRamp选择CCV并执行消息(V2VerificationMode.OFFRAMP_DERIVED, (中文(简体) ),
; 模拟CCV证明。 带有数据的快传送消息只发送给接收者
选择通过 getCCVsAndFinalityConfig,如同生产。 见 变动情况 0.3.0的断裂
变化、移徙指南和已知的局限性.
本地模式限制
CCIPLocalSimulator 在内部同步发送消息 ccipSend 并应用 CCIP 2.0 OnRamp 和 OnRamp 消息
规则(终局,每封信一个令牌,没有零金额,没有V3) tokenReceiver 在EVM道上, V2 接收器 CCV 配置
审定)。 它不模拟:
- 指使池(集合终局政策、费率限制和集合要求的CCV不执行;指使直接到 接收器;
- CCV或区块确认(接收的CCV清单经过验证而未核实);
- 所支持的
getSupportedTokens属于信息; - 手动执行( e)
NO_EXECUTION_ADDRESS立即执行信件; - 车道
maxPerMsgGasLimit(仅限V1/V2外燃气限值以上)uint32还原MessageGasLimitTooHigh) (中文(简体) ).
使用分叉模式对照真实的合同测试这些.
学多点
欲查看详细文件和更多实例,请访问 链路链接本地文档。 。 。 .
免责声明
请注意,这种repo只包含社区实例——这些不是链路链接的产品或服务,也不由链路链接支持或维护. 这一代码代表了使用链链路产品或服务的例子,仅用于示范和教育目的。 提供“AS IS”和“AS AVAILALAL”时没有任何形式的保证,可能没有经过审计,也可能省略检查或错误处理。 打算使用这个实例代码的各方完全冒着风险这样做,必须在任何生产部署之前进行自己的审计、安全和代码审查、关键管理和测试,并确保这种代码的运作和性能符合预期。 链路实验室和链路基金会都没有部署、操作、监测、维护或认可该代码的任何部署. 请注意,这不是链路链接产品、特性或服务,也没有对代码作出承诺,包括与未来的链路链接发布兼容。 你不应该依赖这个代码 不首先进行你自己的技术、工程和安全审查。 这个代码也超出了任何链路链接bug赏金程序的范围. 链路链路实验室、链路链路链基金会和链路链节点操作员都不负责因本示例中的错误或如何部署或操作而产生的结果,也不负责任何由此产生的索赔或损害。 链路网络的使用受链路基础管理 服务条件,提供了重要信息和披露。 通过使用这个代码,你承认并同意这些术语.