ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

fuels-rs 合约调用参数详解:用 CallParameters 向 Fuel 合约转发资产与 Gas

fuels-rs 合约调用参数详解:用 CallParameters 向 Fuel 合约转发资产与 Gas fuels-rs 合约调用参数详解用 CallParameters 向 Fuel 合约转发资产与 Gas【免费下载链接】fuels-rsFuel Network Rust SDK项目地址: https://gitcode.com/GitHub_Trending/fu/fuels-rs本文基于 fuels-rs 官方文档 Call parameters 展开系统讲解 Fuel Network Rust SDK 中合约调用参数Call Parameters的三个核心字段——金额、资产 ID、转发 Gas——的含义、默认值与底层实现读完你可以掌握如何通过CallParameters在发起合约调用时向合约转发任意资产、精确控制单次调用的 Gas 上限并理解 SDK 对非#[payable]方法的防护机制。合约调用参数是什么在 fuels-rs 中每次向合约发起调用时都可以附带一组「调用参数」用于向合约转发 coins。文档将其归纳为三个字段Amount金额本次调用随交易转发给合约的资产数量Asset ID资产 ID转发的资产种类Gas forwarded转发 Gas转发给合约实际执行的 Gas 额度。这三个字段在 SDK 中被封装为CallParameters结构体定义在 contract_call.rs 中#[derive(Debug, Clone)] pub struct CallParameters { amount: u64, asset_id: OptionAssetId, gas_forwarded: Optionu64, }从源码结构看asset_id与gas_forwarded都是Option类型意味着两者均可缺省而amount是裸的u64。当asset_id缺省时SDK 会自动回退到链上的 base asset——这一行为发生在ContractCall::data()中即 contract_call.rs 的如下映射逻辑Ok(ContractCallData { amount: self.call_parameters.amount(), asset_id: self.call_parameters.asset_id().unwrap_or(base_asset_id), // 未指定则回退 base asset contract_id: self.contract_id, fn_selector_encoded: self.encoded_selector.clone(), encoded_args, gas_forwarded: self.call_parameters.gas_forwarded, })构造与配置new 与链式 builderCallParameters提供两种构造方式均定义在 contract_call.rsCallParameters::new(amount, asset_id, gas_forwarded)一次性显式指定全部三个字段CallParameters::default()配合链式 builder 方法with_amount/with_asset_id/with_gas_forwarded按需覆盖单个字段其余保持默认。默认值由 constants.rs 中的常量决定// ANCHOR: default_call_parameters pub const DEFAULT_CALL_PARAMS_AMOUNT: u64 0; // ANCHOR_END: default_call_parameters结合 contract_call.rs 的Default实现可以确认CallParameters::default()的语义为金额 0、资产 ID 为 base assetNone回退、Gas 转发量不限制None。向合约转发资产完整示例先看一个典型的 Sway 合约示例。仓库中的 contract_test 合约 使用 Sway 标准库的msg_amount()把交易带入的金额原样返回这正是文档选用的演示合约// ANCHOR: msg_amount #[payable] fn get_msg_amount() - u64 { msg_amount() } // ANCHOR_END: msg_amount注意方法上的#[payable]标注——它是接收资产转发的前提详见后文 payable 校验一节。部署该合约后在 Rust 侧通过call_params链式方法配置转发金额完整示例见 examples/contracts/src/lib.rs// ANCHOR: call_parameters let contract_methods MyContract::new(contract_id, wallet.clone()).methods(); let tx_policies TxPolicies::default(); // Forward 1_000_000 coin amount of base asset_id // this is a big number for checking that amount can be a u64 let call_params CallParameters::default().with_amount(1_000_000); let response contract_methods .get_msg_amount() // Our contract method. .with_tx_policies(tx_policies) // Chain the tx policies. .call_params(call_params)? // Chain the call parameters. .call() // Perform the contract call. .await?; // This is an async call, .await it. // ANCHOR_END: call_parameters示例中转发1_000_000单位的 base asset因为未调用with_asset_id按上文逻辑回退为链上 base asset。合约方法get_msg_amount返回的response.value即该金额读者可据此验证转发是否生效。从调用链看call_params是CallHandler上的 builder 方法实现位于 call_handler.rs。它把参数写入内部ContractCall.call_parameters字段后续在构建交易时经由ContractCall::data()落到ContractCallData最终编码进合约调用的 context 中。为什么 call_params 返回 Resultpayable 校验call_params与链上其他 builder 方法不同它的签名是pub fn call_params(mut self, params: CallParameters) - ResultSelf返回Result是为了防止把资产转发给非 payable 方法。源码中的校验逻辑只有一行但语义明确call_handler.rspub fn call_params(mut self, params: CallParameters) - ResultSelf { if !self.is_payable() params.amount() 0 { return Err(error!(Other, assets forwarded to non-payable method)); } self.call.call_parameters params; Ok(self) }其中is_payable标志由abigen!宏从合约 ABI 中解析#[payable]注解读取。以仓库的 payable_annotation 测试合约 为例它同时定义了带标注与不带标注的两个方法abi TestContract { #[payable] fn payable() - u64; fn non_payable() - u64; }对应的 e2e 测试 contracts.rs 验证了校验行为向non_payable转发 100 单位资产会直接返回编译期之外的运行时错误// ANCHOR: non_payable_params let err contract_methods .non_payable() .call_params(CallParameters::default().with_amount(100)) .expect_err(should return error); assert!(matches!(err, Error::Other(s) if s.contains(assets forwarded to non-payable method))); // ANCHOR_END: non_payable_params注意原文档强调向合约调用转发 Gas 始终是被允许的即使目标方法没有#[payable]标注。上面测试的后半段contracts.rs也验证了这一点non_payable().call_params(CallParameters::default().with_gas_forwarded(20_000))可以正常执行并成功返回。默认行为不设置参数会转发什么如果既不调用call_params也不显式传入CallParameters::default()SDK 的默认行为是转发整笔交易的 gas limit而不是转发给单次合约调用。换言之gas_forwarded缺省None等价于「把交易层 Gas 上限全部作为本次调用的可用 Gas」。若你只想显式走一遍默认路径可以像 examples/contracts/src/lib.rs 这样写// ANCHOR: call_parameters_default let response contract_methods .initialize_counter(42) .call_params(CallParameters::default())? .call() .await?; // ANCHOR_END: call_parameters_default注意即使在这里call_params也返回Result链式调用中必须用?处理。gas_forwarded为单次调用设定 Gas 上限gas_forwarded参数定义的是本次合约调用本身的 Gas 上限区别于TxPolicies中配置的整笔交易的script_gas_limit。文档给出的约束关系是调用级 Gas 上限受交易级 Gas 上限约束如果把gas_forwarded设置得比交易实际可用的 Gas 还大则实际转发的就是全部可用 Gas而不是报错或取你设置的值。官方示例完整展示了两个层面的配合见 examples/contracts/src/lib.rs// ANCHOR: call_params_gas // Set the transaction gas_limit to 1_000_000 and gas_forwarded to 4300 to specify that // the contract call transaction may consume up to 1_000_000 gas, while the actual call may // only use 4300 gas let tx_policies TxPolicies::default().with_script_gas_limit(1_000_000); let call_params CallParameters::default().with_gas_forwarded(4300); let response contract_methods .get_msg_amount() // Our contract method. .with_tx_policies(tx_policies) // Chain the tx policies. .call_params(call_params)? // Chain the call parameters. .call() // Perform the contract call. .await?; // ANCHOR_END: call_params_gas这里交易层允许消耗最多 1_000_000 Gas而真正转发给合约执行的只有 4300 Gas。这种分层控制在多调用multi-call场景中尤为有用你可以让单笔交易里的某个调用只拿到有限的 Gas从而隔离资源消耗。速查表与小结字段类型默认值设置方法语义amountu640见 constants.rswith_amount转发资产的单位数量asset_idOptionAssetIdNone回退 base assetwith_asset_id转发的资产种类gas_forwardedOptionu64None转发交易 gas limitwith_gas_forwarded本次合约调用的 Gas 上限受交易 gas limit 约束小结在 fuels-rs 中CallParameters是「交易级策略」TxPolicies之外、针对单次合约调用的资源控制手段。核心要点有四通过CallParameters::default().with_amount(...)等 builder 方法配置并以.call_params(params)?链入调用asset_id缺省时自动使用链上 base asset见 ContractCall::data 的回退逻辑call_params返回Result向非#[payable]方法转发非零金额会被 SDK 在本地拦截并报assets forwarded to non-payable method见 call_handler.rs转发 Gas 不受 payable 限制而gas_forwarded与交易script_gas_limit是「调用级 vs 交易级」两层独立的 Gas 预算。更多合约调用相关内容可参考同目录文档合约调用总览、自定义资产转移、交易策略。【免费下载链接】fuels-rsFuel Network Rust SDK项目地址: https://gitcode.com/GitHub_Trending/fu/fuels-rs创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表