You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Scrypto测试:如何将账户Bucket作为函数参数传递?

Scrypto中正确传递Bucket参数到合约方法的问题

问题背景

我在Scrypto蓝图中编写了一个供管理员将代币存入合约Token Vault的deposit函数:

pub fn deposit(&mut self, amount: Decimal, mut bucket: Bucket) {
  assert!(amount <= bucket.amount(), "not enough amount in your bucket");
  self.token_vault.put(bucket.take(amount))
}

测试时,我已掌握生成新账户、调用带徽章保护方法的操作,参考Scrypto示例项目编写的测试代码如下:

let (public_key, private_key, account_component) = test_runner.new_allocated_account();
...
let manifest = ManifestBuilder::new(&NetworkDefinition::simulator())
    .create_proof_from_account_by_amount(account_component, badge_amount, badge_addr)
    .withdraw_from_account_by_amount(account_component, amount, token_addr)
    .take_from_worktop(token_addr, |builder, bucket_id| {
        builder.call_method(component, func_name, args!(amount, Bucket(bucket_id)))
        })
    .call_method(
        account_component,
        "deposit_batch",
        args!(Expression::entire_worktop()),
    )
    .build();
let receipt = test_runner.execute_manifest_ignoring_fee(
    manifest,
    vec![NonFungibleAddress::from_public_key(&public_key)],
);
println!("{} receipt: {:?}\n", func_name, receipt);
receipt.expect_commit_success();

执行时出现如下错误:

COMMITTED FAILURE: KernelError(InvalidDropNodeVisibility { mode: Application, actor: 
Method(Scrypto { package_address: NormalPackage[011784f2e3c4b3dc9d14c850484fc4962f59ea68271e917d2f075c],
blueprint_name: "StableCoin", ident: "deposit" }, ResolvedReceiver { derefed_from: 

Some((Global(Component(NormalComponent[02fd2e738e08b33e7d19001684043cd24fe35fda1ddc9429f7051e])), 36)), 
receiver: Component([252, 13, 40, 104, 140, 209, 211, 110, 141, 213, 197, 200, 172, 195, 190, 178, 219, 47, 174, 17, 52, 209, 75, 207, 106, 97, 105, 21, 213, 159, 52, 25, 15, 4, 0, 0]) }), 
node_id: Bucket(1027) })

请问如何正确将账户中的Bucket作为函数参数传递?


解决方法

这个错误的核心原因是传递给deposit方法的Bucket在执行后未被完全处理,Scrypto要求所有从工作区取出的Bucket必须被明确消费(存入Vault、销毁或返回给调用者),不能遗留未处理的Bucket节点。

修正步骤

  1. 调整蓝图的deposit函数
    原函数仅将指定数量代币存入Vault,但剩余的Bucket未返回给调用者,导致Bucket节点悬空。修改为返回剩余Bucket:

    pub fn deposit(&mut self, amount: Decimal, mut bucket: Bucket) -> Bucket {
      assert!(amount <= bucket.amount(), "not enough amount in your bucket");
      self.token_vault.put(bucket.take(amount));
      bucket // 返回剩余的Bucket
    }
    
  2. 修正测试中的Manifest逻辑
    调用deposit方法后,需要将返回的Bucket放回工作区,再存入账户,完成资源流转闭环:

    let manifest = ManifestBuilder::new(&NetworkDefinition::simulator())
        .create_proof_from_account_by_amount(account_component, badge_amount, badge_addr)
        .withdraw_from_account_by_amount(account_component, amount, token_addr)
        .take_from_worktop(token_addr, |builder, bucket_id| {
            // 调用deposit方法并接收返回的剩余Bucket
            builder.call_method(component, func_name, args!(amount, Bucket(bucket_id)))
                .then(|builder, returned_bucket_id| {
                    // 将返回的Bucket放回工作区
                    builder.return_to_worktop(Bucket(returned_bucket_id))
                })
        })
        .call_method(
            account_component,
            "deposit_batch",
            args!(Expression::entire_worktop()),
        )
        .build();
    

关键说明

  • Scrypto的Manifest执行过程中,所有被取出的Bucket必须有明确的归宿:要么存入合约Vault,要么返回工作区最终回到账户,要么被销毁。
  • 原代码中deposit方法未返回剩余Bucket,导致Bucket节点处于未处理状态,触发InvalidDropNodeVisibility错误。
  • 修正后,剩余Bucket被返回并放回工作区,最终通过deposit_batch存入账户,完成了完整的资源流转流程。

内容的提问来源于stack exchange,提问作者Russo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 17:10:19