Search code examples
scrypto

Scrypto: how to write test passing bucket as a function argument


In my blueprint, I have a function for the admin to deposit tokens back into the blueprint token vault.

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))
}

I know how to generate a new account in my test file, and how to make a method call with badge protected access... And I have learned from Scrypto-example/nft/magic-card: https://github.com/radixdlt/scrypto-examples

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();

Then I got this error:

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) })

But how can I make the bucket variable from my account_component as a function argument?


Solution

  • I solved it... my blueprint function should not include the amount, which has been represented in bucket argument...

    pub fn deposit_to_vault(&mut self, bucket: Bucket) {
      self.token_vault.put(bucket)
    }
    

    then use take_from_worktop_by_amount to get the bucket_id:

      .withdraw_from_account_by_amount(user.compo_addr, amount, token_addr)
      .take_from_worktop_by_amount(amount, token_addr, |builder, bucket_id| {
          builder.call_method(component, func_name, args!(Bucket(bucket_id)))
      })
      .call_method(
          user.compo_addr,
          "deposit_batch",
          args!(Expression::entire_worktop()),
      )
      .build();