ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

fuels-ts 实战指南:在部署 Sway 合约时设置 Configurable Constants(可配置常量)

2026/9/6 19:21:09 拓冰建站 浏览量
fuels-ts 实战指南:在部署 Sway 合约时设置 Configurable Constants(可配置常量) fuels-ts 实战指南在部署 Sway 合约时设置 Configurable Constants可配置常量【免费下载链接】fuels-tsFuel Network Typescript SDK项目地址: https://gitcode.com/GitHub_Trending/fu/fuels-ts本篇基于 fuels-ts 文档《Configurable Constants》展开讲解 Fuel SDK 中 Sway 合约可配置常量configurable constants的完整用法如何在合约中用configurable块声明带默认值的常量如何在部署时通过configurableConstants选项按需覆盖其中任意常量以及配置不完整例如 Struct 缺字段时的报错行为。读完本文你将掌握可配置常量的声明、覆盖与验证全流程并理解 SDK 在底层改写字节码的实现原理。一、什么是 Configurable ConstantsSway 提供了强大的可配置常量特性在创建合约时可以定义一批常量并为每个常量指定默认值在合约部署之前你可以重新定义这些常量的值——可以只改其中一部分也可以全部覆盖。这一特性为动态的合约环境提供了灵活性同一份合约代码可以在不同环境下以不同的常量配置部署实现高定制化从而编写出更高效、更易适应不同场景的智能合约。二、在 Sway 合约中声明可配置常量下面是一个声明了四个可配置常量的示例合约来自仓库文档配套 Sway 工程 echo-configurablescontract; enum MyEnum { Checked: (), Pending: (), } struct MyStruct { x: u8, y: u8, state: MyEnum, } configurable { age: u8 25, tag: str[4] __to_str_array(fuel), grades: [u8; 4] [3, 4, 3, 2], my_struct: MyStruct MyStruct { x: 1, y: 2, state: MyEnum::Pending, }, } abi EchoConfigurables { fn echo_configurables() - (u8, str[4], [u8; 4], MyStruct); } impl EchoConfigurables for Contract { fn echo_configurables() - (u8, str[4], [u8; 4], MyStruct) { (age, tag, grades, my_struct) } }该合约中echo_configurables函数会返回四个可配置常量的当前值供我们用它来演示通过 SDK 设置常量配置。示例覆盖了多种典型类型无符号整数u8、定长字符串str[4]、固定长度数组[u8; 4]以及嵌套了枚举的Struct。三、部署时为新值覆盖常量在合约部署阶段可以为任意一个或全部可配置常量指定新值。下面的示例对应 文档代码片段只覆盖了age一个常量其余常量保持 Sway 中定义的默认值import { Provider, Wallet } from fuels; import { LOCAL_NETWORK_URL, WALLET_PVT_KEY } from ../../../env; import { EchoConfigurablesFactory } from ../../../typegend; const provider new Provider(LOCAL_NETWORK_URL); const wallet Wallet.fromPrivateKey(WALLET_PVT_KEY, provider); const configurableConstants { age: 10, }; const deploy await EchoConfigurablesFactory.deploy(wallet, { configurableConstants, }); const { contract } await deploy.waitForResult(); const { value: [age, tag, grades, myStruct], } await contract.functions.echo_configurables().get(); // age got updated console.log(age, age); // 10 // while the rest are default values console.log(tag, tag); // fuel console.log(grades, grades); // [3, 4, 3, 2] console.log(myStruct, myStruct); // { x: 1, y: 2, state: Pending }要点说明EchoConfigurablesFactory由 fuels-ts 的类型生成typegen流程基于合约 ABI 生成deploy方法接收的第二个参数即 DeployContractOptionsconfigurableConstants是一个以常量名为键的对象类型签名为{ [name: string]: unknown }只需给出你想覆盖的常量未提及的常量自动沿用 Sway 源码中的默认值调用deploy(wallet, { configurableConstants })后等待交易结果拿到contract实例再通过contract.functions.echo_configurables().get()验证age变为 10而tag、grades、myStruct仍为fuel、[3, 4, 3, 2]、{ x: 1, y: 2, state: Pending }。四、Struct 常量必须完整配置否则部署报错文档特别强调为Struct类型常量赋新值时必须定义该 Struct 的全部属性否则会抛出错误。仓库文档片段中给出了反例const invalidConfigurables { my_struct: { x: 10, }, }; try { await EchoConfigurablesFactory.deploy(wallet, { configurableConstants: invalidConfigurables, }); } catch (e) { console.log(error, e); // error: Error setting configurable constants on contract: // Invalid struct MyStruct. Field y not present. }只写了x: 10而遗漏了y和state字段deploy会同步抛出Error setting configurable constants on contract: Invalid struct MyStruct. Field y not present.。该错误信息恰好对应 ContractFactory.setConfigurableConstants 中统一的错误包装逻辑见下文原理分析。五、源码级原理常量值是如何写进合约的从源码结构看可配置常量的本质是在部署交易发出之前把编码后的常量值直接覆写到合约字节码的固定偏移位置即对字节码做打补丁。关键调用链如下入口ContractFactory.deploy→deployAsCreateTx→prepareDeploy。在 prepareDeploy 中只要deployOptions.configurableConstants存在就会先调用this.setConfigurableConstants(configurableConstants)之后才创建交易请求。由于合约 IDcontractId是在字节码改写之后基于bytecode salt stateRoot计算的见 createTransactionRequest 中getContractId(bytecode, options.salt, stateRoot)调用可以推断不同configurableConstants配置会产生不同的字节码与不同的合约 ID。核心逻辑setConfigurableConstants 逐条处理用户传入的键值对先校验合约 ABI 中确实声明了configurables否则抛出Contract does not have configurables to be set再校验每个键都在this.interface.configurables中存在否则抛出Contract does not have a configurable named: ${key}随后通过 Interface.encodeConfigurable 按 ABI 中的configurableType将 JS 值编码为字节序列并从this.interface.configurables[key].offset取出该常量在字节码中的偏移地址执行bytes.set(encoded, offset)完成覆写最后把改写后的字节序列回写到this.bytecode所有异常都会被捕获并统一包装为INVALID_CONFIGURABLE_CONSTANTS错误消息前缀即文档示例中看到的Error setting configurable constants on contract: ...Struct 缺字段时内部抛出Invalid struct MyStruct. Field y not present.后同样走这条包装路径。ABI 侧支撑Interface 构造函数 在初始化时就把 JSON ABI 中的configurables数组转成以名称为键的映射每条记录包含常量名、类型与offset这正是部署时能定位到字节码哪一段的依据。Blob 分片部署同样支持当合约超过链上contractMaxSize限制时deploy会自动走 deployAsBlobTx 分片路径该方法在分块之前同样会调用setConfigurableConstants因此无论走 Create 交易还是 Blob 分片部署configurableConstants都能生效。六、测试验证SDK 支持的可配置常量类型仓库集成测试 configurable-contract.test.ts 用ConfigurableContractFactory系统性地验证了各类型常量的默认值断言与覆盖能力可作为哪些类型可以安全配置的权威参考。测试中定义的默认值与覆盖用例涵盖类型默认值覆盖值示例U8/U16/U32/U6410 / 301 / 799 / 10000099 / 499 / 854 / 999999BOOLtruefalseB2560x1d6ebd57...随机 256 位值ENUMredblue以字符串传枚举变体名ARRAY二维数组[[253,254],[255,256]][[666,667],[656,657]]STR_4定长字符串fuelleufTUPLE[12, false, hi][99, true, by]STRUCT_1{ tag:000, age:21, scores:[1,3,4] }{ tag:007, age:30, scores:[10,10,10] }测试的部署方式值得注意它并没有手动deploy而是使用fuels/test-utils提供的launchTestNode通过contractsConfigs参数把工厂与选项一并交给测试节点function setupContract(configurableConstants?: { [name: string]: unknown }) { return launchTestNode({ contractsConfigs: [ { factory: ConfigurableContractFactory, options: { configurableConstants }, }, ], }); }这说明configurableConstants作为DeployContractOptions的一部分同样适用于测试节点批量部署场景。该测试文件同时标注了group node与group browser即同一套用法在 Node 与浏览器环境下均已验证。此外仓库中还存在 predicate-configurables.test.ts 等用例表明该机制不只服务于合约部署。七、一个真实应用场景SDK CLI 部署代理合约fuels-ts 的 CLI 部署命令内部就依赖了configurableConstants。在 deployContracts.ts 中部署 SR-C14 兼容的代理合约Proxy Contract时SDK 会把目标合约 ID 与部署者地址写入代理合约的两个可配置常量const proxyDeployConfig: DeployContractOptions { ...commonDeployConfig, storageSlots: mergedStorageSlots, configurableConstants: { INITIAL_TARGET: { bits: targetContract.id.toB256() }, INITIAL_OWNER: { Initialized: { Address: { bits: wallet.address.toB256() } } }, }, };示例体现了两个实践细节b256类常量需以{ bits: ... }的包装结构传入枚举型常量则使用{ 变体名: { ... } }的 tagged union 结构——这与AbiCoder的编码规则保持一致。八、小结与注意事项只能覆盖、不能新增configurableConstants的键必须存在于 ABI 声明的configurables中且合约必须至少声明一个可配置常量否则 SDK 直接抛错Struct 必须完整覆盖 Struct 常量时缺一不可字段否则报错Invalid struct Xxx. Field yyy not present.时机是部署时从源码实现看常量覆盖发生在deploy创建交易请求之前属于部署时一次性写入字节码的语义并非部署后可通过链上调用的存储写入影响合约 ID常量值被覆写进字节码后才计算 contractId因此同一份合约代码配不同的configurableConstants得到的合约 ID 不同全类型支持u8/u16/u32/u64、bool、b256、enum、数组、定长字符串、元组、struct 等类型均有集成测试覆盖可放心使用。【免费下载链接】fuels-tsFuel Network Typescript SDK项目地址: https://gitcode.com/GitHub_Trending/fu/fuels-ts创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考