资讯动态

fuels-ts 合约调用时如何通过 callParams 向合约转发资产

发布时间:2026/9/10 6:07:06 来源:尧图企业网站定制
fuels-ts 合约调用时如何通过 callParams 向合约转发资产【免费下载链接】fuels-tsFuel Network Typescript SDK项目地址: https://gitcode.com/GitHub_Trending/fu/fuels-ts当你调用 Fuel 合约的某个函数时有时需要随调用一并给合约转交一定数量的资产例如向合约充值、或为合约即将执行的转账提供资金来源。在 fuels-ts 中这件事通过合约调用链上的callParams方法完成它在构造合约调用时接受forward和gasLimit两个参数其中forward就是向合约转发资产的入口。完成本场景的前提是你已有一个本地或测试网节点、一个Provider实例和一个可转发的私钥钱包并且合约端函数声明了#[payable]否则合约无法接收随调用转发的资产。callParams提供的参数callParams方法可用于为合约调用配置两类参数forward在调用函数时向合约发送指定数量的资产。当合约函数执行需要动用资金时例如把资金转给另一个账户或合约就需要用到它。同时forward也帮助你控制分配给合约调用的资源起到保护作用避免合约动用超出你预期的资金。gasLimit限制该合约调用本身可消耗的最大 gas与交易其余部分分开计算。除了这两个调用参数合约函数调用还可以设置交易参数txParams相关说明见 Transaction Parameters。准备一个#[payable]合约以下示例使用的 return-context 合约 会返回本次调用转发给它的金额contract; use std::context::msg_amount; abi ReturnContext { #[payable] fn return_context_amount() - u64; } impl ReturnContext for Contract { #[payable] fn return_context_amount() - u64 { msg_amount() } }注意#[payable]属性函数需要显式声明为 payable 才能接收转发进来的资产。文档中的示例代码从fuels包引入Provider与Wallet并通过 typegen 生成的ReturnContextFactory部署合约LOCAL_NETWORK_URL与WALLET_PVT_KEY来自文档配套的 env.ts实际使用时替换为你自己的节点地址与钱包私钥。用forward向合约转发资产下面的示例转发 10 个基础资产并等待交易完成import { Provider, Wallet } from fuels; import { LOCAL_NETWORK_URL, WALLET_PVT_KEY } from ../../../../env; import { ReturnContextFactory } from ../../../../typegend; const provider new Provider(LOCAL_NETWORK_URL); const wallet Wallet.fromPrivateKey(WALLET_PVT_KEY, provider); const deploy await ReturnContextFactory.deploy(wallet); const { contract } await deploy.waitForResult(); const amountToForward 10; const baseAssetId await provider.getBaseAssetId(); const { waitForResult } await contract.functions .return_context_amount() .callParams({ forward: [amountToForward, baseAssetId], }) .call(); const { value } await waitForResult(); console.log(forwarded amount:, value.toNumber()); // forwarded amount: 10代码中的forward: [amountToForward, baseAssetId]是本次转发的两个要素金额与资产 ID。资产 ID 通过provider.getBaseAssetId()获取如果要转发的不是基础资产替换为对应资产的AssetId即可。末尾的// forwarded amount: 10是文档示例输出函数返回值即本次msg_amount()也就是转发给合约的金额用它来确认转发确实到账。完整示例见 forward.ts主题文档为 Call Parameters。转发超额资产后用getBalance核对合约余额实际场景中常见的情况是向合约转发的金额大于合约本次实际要花的金额。例如 transfer-to-address 合约 的transfer函数把指定数量的资产转给指定地址。可以先转发一个更大的数量执行调用后用Contract.getBalance核对合约剩余余额import type { AssetId } from fuels; import { Provider, Wallet } from fuels; import { LOCAL_NETWORK_URL, WALLET_PVT_KEY } from ../../../env; import { TransferToAddressFactory } from ../../../typegend; const provider new Provider(LOCAL_NETWORK_URL); const wallet Wallet.fromPrivateKey(WALLET_PVT_KEY, provider); const { waitForResult: waitForDeploy } await TransferToAddressFactory.deploy(wallet); const { contract } await waitForDeploy(); const amountToForward 40; const amountToTransfer 10; const baseAssetId await provider.getBaseAssetId(); const recipient Wallet.generate({ provider, }); const asset: AssetId { bits: baseAssetId, }; const { waitForResult } await contract.functions .transfer(amountToTransfer, asset, recipient.address.toB256()) .callParams({ forward: [amountToForward, baseAssetId], }) .call(); await waitForResult(); const contractBalance await contract.getBalance(baseAssetId); console.log( contract balance reduced by amountToTransfer, contractBalance.toNumber() amountToForward - amountToTransfer );验证逻辑先转发 40 个基础资产大于本次转账需要的 10 个调用完成后用contract.getBalance(baseAssetId)查询合约该资产的可用余额判断余额是否恰好等于转发总额减去已转出金额。getBalance返回的是合约该资产的总可用余额与资产被转入或花费的次数无关。该核对方式出自 Contract Balance 与 contract-balance.ts。与gasLimit一起设置callParams的gasLimit约束的是合约调用本身的 gas 上限。文档展示了设置过低的后果try { await contract.functions .return_context_amount() .callParams({ forward: [10, await provider.getBaseAssetId()], gasLimit: 1, }) .call(); } catch (e) { console.log(error, e); // error _FuelError: The transaction reverted with reason: OutOfGas }这是文档示例输出gasLimit设为 1 时交易因OutOfGas回滚。也就是说如果调用执行所需 gas 超出你为调用设置的gasLimit交易会 revert 并报出上述原因。注意区分两层gasLimit调用参数gasLimit限制实际合约调用可使用的最大 gas交易参数gasLimit通过txParams设置限制整笔交易可使用的最大 gas并反过来约束调用参数gasLimit。如果调用参数gasLimit设得大于交易可用 gas则会以全部可用交易 gas 分配给合约调用执行如果不设置调用参数gasLimit则直接应用交易gasLimit。两者可以在同一次调用中同时设置const contractCallGasLimit 4_000; const transactionGasLimit 100_000; const call await contract.functions .return_context_amount() .callParams({ forward: [10, await provider.getBaseAssetId()], gasLimit: contractCallGasLimit, }) .txParams({ gasLimit: transactionGasLimit, }) .call(); const { transactionResult: { isStatusSuccess }, } await call.waitForResult(); console.log(tx successful, isStatusSuccess);对应片段见 setting-both-parameters.ts 与 gas-fee.ts。延伸向需要转入资产的#[payable]函数充值如果你的合约像 Deposit And Withdraw 中的流动性池一样deposit(recipient: Address)函数在合约内断言0 msg_amount()即必须先收到转发资产才能执行。调用方式为const { waitForResult } await contract.functions .deposit({ bits: liquidityOwner.address.toB256() }) .callParams({ forward: [depositAmount, await provider.getBaseAssetId()] }) .txParams({ variableOutputs: 1 }) .call();该合约deposit会按msg_amount()铸造两倍的流动性资产给收款方此处txParams({ variableOutputs: 1 })用于支持调用产生的可变输出。调用完成后可通过liquidityOwner.getBalance(assetId)查询收款方收到的流动性资产数量示例见 deposit.ts。【免费下载链接】fuels-tsFuel Network Typescript SDK项目地址: https://gitcode.com/GitHub_Trending/fu/fuels-ts创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价