Skip to content

Commit

Permalink
Merge 831e9be into 57ee7cf
Browse files Browse the repository at this point in the history
  • Loading branch information
lrubasze authored Jan 6, 2025
2 parents 57ee7cf + 831e9be commit f9ac912
Show file tree
Hide file tree
Showing 3 changed files with 218 additions and 70 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
use scrypto::prelude::*;

#[derive(ScryptoSbor, NonFungibleData)]
pub struct DummyData {}

#[blueprint]
mod execution_trace_test {
struct ExecutionTraceBp {
vault: Vault,
}

impl ExecutionTraceBp {
pub fn transfer_resource_between_two_components(
pub fn transfer_fungible_resource_between_two_components(
amount: u8,
use_take_advanced: bool,
) -> (
Expand Down Expand Up @@ -45,6 +48,41 @@ mod execution_trace_test {
(resource_address, source_component, target_component)
}

pub fn transfer_non_fungible_resource_between_two_components(
amount: u8,
) -> (
ResourceAddress,
Global<ExecutionTraceBp>,
Global<ExecutionTraceBp>,
) {
let mut entries = vec![];
for i in 1..amount as u64 + 1 {
entries.push((i.into(), DummyData {}));
}
let bucket = ResourceBuilder::new_integer_non_fungible::<DummyData>(OwnerRole::None)
.mint_initial_supply(entries);
let resource_address = bucket.resource_address();

let source_component = ExecutionTraceBp {
vault: Vault::with_bucket(bucket.into()),
}
.instantiate()
.prepare_to_globalize(OwnerRole::None)
.globalize();

let target_component = ExecutionTraceBp {
vault: Vault::new(resource_address),
}
.instantiate()
.prepare_to_globalize(OwnerRole::None)
.globalize();

let transfer_bucket: Bucket = source_component.take_non_fungibles(amount);
target_component.put(transfer_bucket);

(resource_address, source_component, target_component)
}

pub fn take(&mut self, amount: u8) -> Bucket {
self.vault.take(amount)
}
Expand All @@ -53,6 +91,16 @@ mod execution_trace_test {
self.vault.take_advanced(amount, WithdrawStrategy::Exact)
}

pub fn take_non_fungibles(&mut self, amount: u8) -> Bucket {
let amount = amount as u64;
let mut ids = indexset![];
for i in 1..amount + 1 {
ids.insert(NonFungibleLocalId::integer(i));
}

self.vault.as_non_fungible().take_non_fungibles(&ids).into()
}

pub fn put(&mut self, b: Bucket) {
self.vault.put(b)
}
Expand Down
202 changes: 142 additions & 60 deletions radix-engine-tests/tests/application/execution_trace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ use radix_transactions::{model::PreviewFlags, validation::TransactionValidator};
use scrypto_test::prelude::*;

#[test]
fn test_trace_resource_transfers_using_take() {
fn test_trace_fungible_resource_transfers_within_blueprint_using_take() {
run_resource_transfers_trace_test(false);
}

#[test]
fn test_trace_resource_transfers_using_take_advanced() {
fn test_trace_fungible_resource_transfers_within_blueprint_using_take_advanced() {
run_resource_transfers_trace_test(true);
}

Expand All @@ -29,7 +29,7 @@ fn run_resource_transfers_trace_test(use_take_advanced: bool) {
.call_function(
package_address,
"ExecutionTraceBp",
"transfer_resource_between_two_components",
"transfer_fungible_resource_between_two_components",
manifest_args!(transfer_amount, use_take_advanced),
)
.build();
Expand All @@ -47,87 +47,112 @@ fn run_resource_transfers_trace_test(use_take_advanced: bool) {
ComponentAddress,
) = receipt.expect_commit(true).output(1);

let resource_changes = &receipt
.expect_commit_success()
.execution_trace
.as_ref()
.unwrap()
.resource_changes;

/* There should be three resource changes: withdrawal from the source vault,
deposit to the target vault and withdrawal for the fee */
println!(
"{:?}",
receipt
.expect_commit_success()
.execution_trace
.as_ref()
.unwrap()
.resource_changes
);
assert_eq!(
2,
receipt
.expect_commit_success()
.execution_trace
.as_ref()
.unwrap()
.resource_changes
.len()
); // Two instructions
assert_eq!(
1,
receipt
.expect_commit_success()
.execution_trace
.as_ref()
.unwrap()
.resource_changes
.get(&0)
.unwrap()
.len()
); // One resource change in the first instruction (lock fee)
assert_eq!(
2,
receipt
.expect_commit_success()
.execution_trace
.as_ref()
.unwrap()
.resource_changes
.get(&1)
.unwrap()
.len()
); // One resource change in the first instruction (lock fee)
println!("{:?}", resource_changes);
assert_eq!(2, resource_changes.len()); // Two instructions
assert_eq!(1, resource_changes.get(&0).unwrap().len()); // One resource change in the first instruction (lock fee)
assert_eq!(2, resource_changes.get(&1).unwrap().len()); // Two resource changes in the second instruction (transfer_fungible_resource_between_two_components)

let fee_summary = receipt.fee_summary.clone();
let total_fee_paid = fee_summary.total_cost();

// Source vault withdrawal
assert!(receipt
.expect_commit_success()
.execution_trace
.as_ref()
.unwrap()
.resource_changes
assert!(resource_changes
.iter()
.flat_map(|(_, rc)| rc)
.any(|r| r.node_id == source_component.into()
&& r.amount == Decimal::from(transfer_amount).checked_neg().unwrap()));

// Target vault deposit
assert!(receipt
.expect_commit_success()
.execution_trace
.as_ref()
.unwrap()
.resource_changes
assert!(resource_changes
.iter()
.flat_map(|(_, rc)| rc)
.any(
|r| r.node_id == target_component.into() && r.amount == Decimal::from(transfer_amount)
));

// Fee withdrawal
assert!(receipt
assert!(resource_changes
.iter()
.flat_map(|(_, rc)| rc)
.any(|r| r.node_id == account.into()
&& r.amount == Decimal::from(total_fee_paid).checked_neg().unwrap()));
}

#[test]
fn test_trace_non_fungible_resource_transfers_within_blueprint() {
// Arrange
let mut ledger = LedgerSimulatorBuilder::new().build();
let (public_key, _, account) = ledger.new_allocated_account();
let package_address = ledger.publish_package_simple(PackageLoader::get("execution_trace"));
let transfer_amount = 10u8;

// Act
let manifest = ManifestBuilder::new()
.lock_fee(account, 500)
.call_function(
package_address,
"ExecutionTraceBp",
"transfer_non_fungible_resource_between_two_components",
manifest_args!(transfer_amount),
)
.build();
let receipt = ledger.preview_manifest(
manifest,
vec![public_key.clone().into()],
0,
PreviewFlags::default(),
);

// Assert
let (_resource_address, source_component, target_component): (
ResourceAddress,
ComponentAddress,
ComponentAddress,
) = receipt.expect_commit(true).output(1);

let resource_changes = &receipt
.expect_commit_success()
.execution_trace
.as_ref()
.unwrap()
.resource_changes
.resource_changes;

/* There should be three resource changes: withdrawal from the source vault,
deposit to the target vault and withdrawal for the fee */
println!("{:?}", resource_changes);
assert_eq!(2, resource_changes.len()); // Two instructions
assert_eq!(1, resource_changes.get(&0).unwrap().len()); // One resource change in the first instruction (lock fee)
assert_eq!(2, resource_changes.get(&1).unwrap().len()); // Two resource changes in the second instruction (transfer_non_fungible_resource_between_two_components)

let fee_summary = receipt.fee_summary.clone();
let total_fee_paid = fee_summary.total_cost();

// Source vault withdrawal
assert!(resource_changes
.iter()
.flat_map(|(_, rc)| rc)
.any(|r| r.node_id == source_component.into()
&& r.amount == Decimal::from(transfer_amount).checked_neg().unwrap()));

// Target vault deposit
assert!(resource_changes
.iter()
.flat_map(|(_, rc)| rc)
.any(
|r| r.node_id == target_component.into() && r.amount == Decimal::from(transfer_amount)
));

// Fee withdrawal
assert!(resource_changes
.iter()
.flat_map(|(_, rc)| rc)
.any(|r| r.node_id == account.into()
Expand Down Expand Up @@ -1047,3 +1072,60 @@ fn test_execution_trace_for_transaction_v2() {
)"#;
assert_eq!(format!("{:#?}", trace), expected_trace);
}

#[test]
fn test_trace_non_fungible_resource_transfers_using_manifest() {
// Arrange
let mut ledger = LedgerSimulatorBuilder::new().build();

let (from_public_key, _from_private_key, from_address) = ledger.new_allocated_account();
let (_to_public_key, _to_private_key, to_address) = ledger.new_allocated_account();

let nf_resource_address = ledger.create_non_fungible_resource_advanced(
NonFungibleResourceRoles::default(),
from_address,
4,
);
let nf_global_id =
NonFungibleGlobalId::new(nf_resource_address, NonFungibleLocalId::integer(1));

let manifest = ManifestBuilder::new()
.lock_fee(from_address, 100)
.withdraw_non_fungible_from_account(from_address, nf_global_id)
.take_all_from_worktop(nf_resource_address, "nf_bucket")
.try_deposit_or_abort(to_address, None, "nf_bucket")
.build();

let receipt = ledger.preview_manifest(
manifest,
vec![from_public_key.clone().into()],
0,
PreviewFlags::default(),
);
let fee_summary = receipt.fee_summary.clone();
let total_fee_paid = fee_summary.total_cost();

// Act & Assert: Execute the preview, followed by a normal execution.
let resource_changes = &receipt
.expect_commit_success()
.execution_trace
.as_ref()
.unwrap()
.resource_changes;

println!("{:?}", resource_changes);
assert!(resource_changes
.iter()
.flat_map(|(_, rc)| rc)
.any(|r| r.node_id == from_address.into() && r.amount == -total_fee_paid));

assert!(resource_changes
.iter()
.flat_map(|(_, rc)| rc)
.any(|r| r.node_id == from_address.into() && r.amount == dec!(-1)));

assert!(resource_changes
.iter()
.flat_map(|(_, rc)| rc)
.any(|r| r.node_id == to_address.into() && r.amount == dec!(1)));
}
Loading

0 comments on commit f9ac912

Please sign in to comment.