From b2da4f65a91e11e1f63ecfe5658c8fad4806c62e Mon Sep 17 00:00:00 2001 From: Ovidiu Stinga Date: Tue, 22 Aug 2023 15:28:44 +0300 Subject: [PATCH 01/21] staking module test basic setup --- .../tests/staking_module_whitebox_test.rs | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 contracts/feature-tests/use-module/tests/staking_module_whitebox_test.rs diff --git a/contracts/feature-tests/use-module/tests/staking_module_whitebox_test.rs b/contracts/feature-tests/use-module/tests/staking_module_whitebox_test.rs new file mode 100644 index 0000000000..7f24f008f5 --- /dev/null +++ b/contracts/feature-tests/use-module/tests/staking_module_whitebox_test.rs @@ -0,0 +1,100 @@ +use multiversx_sc::types::{Address, EgldOrEsdtTokenIdentifier, ManagedVec}; +use multiversx_sc_modules::staking::StakingModule; +use multiversx_sc_scenario::{ + managed_address, managed_biguint, managed_token_id, rust_biguint, + scenario_model::{Account, AddressValue, ScDeployStep, SetStateStep}, + ScenarioWorld, WhiteboxContract, +}; + +const STAKING_TOKEN_ID_EXPR: &str = "str:STAKE-123456"; +const STAKING_TOKEN_ID: &[u8] = b"STAKE-123456"; +const INITIAL_BALANCE: u64 = 2_000_000; +const REQUIRED_STAKE_AMOUNT: u64 = 1_000_000; +const SLASH_AMOUNT: u64 = 600_000; +const QUORUM: usize = 2; + +const OWNER_ADDRESS_EXPR: &str = "address:owner"; +const ALICE_ADDRESS_EXPR: &str = "address:alice"; +const BOB_ADDRESS_EXPR: &str = "address:bob"; +const CAROL_ADDRESS_EXPR: &str = "address:carol"; +const EVE_ADDRESS_EXPR: &str = "address:eve"; + +const USE_MODULE_ADDRESS_EXPR: &str = "sc:use-module"; +const USE_MODULE_PATH_EXPR: &str = "file:output/use-module.wasm"; + +fn world() -> ScenarioWorld { + let mut blockchain = ScenarioWorld::new(); + blockchain.set_current_dir_from_workspace("contracts/features-tests/use-module"); + + blockchain.register_contract(USE_MODULE_PATH_EXPR, use_module::ContractBuilder); + blockchain +} + +#[test] +fn test_staking_module() { + let mut world = world(); + + world.set_state_step( + SetStateStep::new() + .put_account(OWNER_ADDRESS_EXPR, Account::new().nonce(1)) + .new_address(OWNER_ADDRESS_EXPR, 1, USE_MODULE_ADDRESS_EXPR) + .put_account( + ALICE_ADDRESS_EXPR, + Account::new() + .nonce(1) + .esdt_balance(STAKING_TOKEN_ID_EXPR, rust_biguint!(INITIAL_BALANCE)), + ) + .put_account( + BOB_ADDRESS_EXPR, + Account::new() + .nonce(1) + .esdt_balance(STAKING_TOKEN_ID_EXPR, rust_biguint!(INITIAL_BALANCE)), + ) + .put_account( + CAROL_ADDRESS_EXPR, + Account::new() + .nonce(1) + .esdt_balance(STAKING_TOKEN_ID_EXPR, rust_biguint!(INITIAL_BALANCE)), + ) + .put_account( + EVE_ADDRESS_EXPR, + Account::new() + .nonce(1) + .esdt_balance(STAKING_TOKEN_ID_EXPR, rust_biguint!(INITIAL_BALANCE)), + ), + ); + + // init + let use_module_whitebox = + WhiteboxContract::new(USE_MODULE_ADDRESS_EXPR, use_module::contract_obj); + let use_module_code = world.code_expression(USE_MODULE_PATH_EXPR); + + world.whitebox_deploy( + &use_module_whitebox, + ScDeployStep::new() + .from(OWNER_ADDRESS_EXPR) + .code(use_module_code), + |sc| { + let mut whitelist = ManagedVec::new(); + whitelist.push(managed_address!(&address_expr_to_address( + ALICE_ADDRESS_EXPR + ))); + whitelist.push(managed_address!(&address_expr_to_address(BOB_ADDRESS_EXPR))); + whitelist.push(managed_address!(&address_expr_to_address( + CAROL_ADDRESS_EXPR + ))); + + sc.init_staking_module( + &EgldOrEsdtTokenIdentifier::esdt(managed_token_id!(STAKING_TOKEN_ID)), + &managed_biguint!(REQUIRED_STAKE_AMOUNT), + &managed_biguint!(SLASH_AMOUNT), + QUORUM, + &whitelist, + ); + }, + ); +} + +fn address_expr_to_address(address_expr: &str) -> Address { + AddressValue::from(address_expr).to_address() +} From 18b42297e77b718b7503be05d4bf096cefe4e2bd Mon Sep 17 00:00:00 2001 From: Ovidiu Stinga Date: Tue, 22 Aug 2023 15:48:07 +0300 Subject: [PATCH 02/21] add some tests --- .../tests/staking_module_whitebox_test.rs | 117 +++++++++++++++++- 1 file changed, 116 insertions(+), 1 deletion(-) diff --git a/contracts/feature-tests/use-module/tests/staking_module_whitebox_test.rs b/contracts/feature-tests/use-module/tests/staking_module_whitebox_test.rs index 7f24f008f5..d95f6d94b7 100644 --- a/contracts/feature-tests/use-module/tests/staking_module_whitebox_test.rs +++ b/contracts/feature-tests/use-module/tests/staking_module_whitebox_test.rs @@ -2,7 +2,9 @@ use multiversx_sc::types::{Address, EgldOrEsdtTokenIdentifier, ManagedVec}; use multiversx_sc_modules::staking::StakingModule; use multiversx_sc_scenario::{ managed_address, managed_biguint, managed_token_id, rust_biguint, - scenario_model::{Account, AddressValue, ScDeployStep, SetStateStep}, + scenario_model::{ + Account, AddressValue, CheckAccount, CheckStateStep, ScCallStep, ScDeployStep, SetStateStep, + }, ScenarioWorld, WhiteboxContract, }; @@ -93,6 +95,119 @@ fn test_staking_module() { ); }, ); + + // try stake - not a board member + world.whitebox_call_check( + &use_module_whitebox, + ScCallStep::new() + .from(EVE_ADDRESS_EXPR) + .esdt_transfer(STAKING_TOKEN_ID, 0, rust_biguint!(REQUIRED_STAKE_AMOUNT)) + .no_expect(), + |sc| sc.stake(), + |r| { + r.assert_user_error("Only whitelisted members can stake"); + }, + ); + + // stake half and try unstake + world.whitebox_call( + &use_module_whitebox, + ScCallStep::new().from(ALICE_ADDRESS_EXPR).esdt_transfer( + STAKING_TOKEN_ID, + 0, + rust_biguint!(REQUIRED_STAKE_AMOUNT / 2), + ), + |sc| sc.stake(), + ); + + world.whitebox_call_check( + &use_module_whitebox, + ScCallStep::new().from(ALICE_ADDRESS_EXPR).no_expect(), + |sc| sc.unstake(managed_biguint!(REQUIRED_STAKE_AMOUNT / 4)), + |r| { + r.assert_user_error("Not enough stake"); + }, + ); + + // bob and carol stake + world.whitebox_call( + &use_module_whitebox, + ScCallStep::new().from(BOB_ADDRESS_EXPR).esdt_transfer( + STAKING_TOKEN_ID, + 0, + rust_biguint!(REQUIRED_STAKE_AMOUNT), + ), + |sc| sc.stake(), + ); + + world.whitebox_call( + &use_module_whitebox, + ScCallStep::new().from(CAROL_ADDRESS_EXPR).esdt_transfer( + STAKING_TOKEN_ID, + 0, + rust_biguint!(REQUIRED_STAKE_AMOUNT), + ), + |sc| sc.stake(), + ); + + // try vote slash, not enough stake + world.whitebox_call_check( + &use_module_whitebox, + ScCallStep::new().from(ALICE_ADDRESS_EXPR).no_expect(), + |sc| sc.vote_slash_member(managed_address!(&address_expr_to_address(BOB_ADDRESS_EXPR))), + |r| { + r.assert_user_error("Not enough stake"); + }, + ); + + // try vote slash, slashed address not a board member + world.whitebox_call_check( + &use_module_whitebox, + ScCallStep::new().from(ALICE_ADDRESS_EXPR).no_expect(), + |sc| sc.vote_slash_member(managed_address!(&address_expr_to_address(EVE_ADDRESS_EXPR))), + |r| { + r.assert_user_error("Voted user is not a staked board member"); + }, + ); + + // alice stake over max amount and withdraw surplus + world.whitebox_call( + &use_module_whitebox, + ScCallStep::new().from(ALICE_ADDRESS_EXPR).esdt_transfer( + STAKING_TOKEN_ID, + 0, + rust_biguint!(REQUIRED_STAKE_AMOUNT), + ), + |sc| { + sc.stake(); + let alice_staked_amount = sc + .staked_amount(&managed_address!(&address_expr_to_address( + ALICE_ADDRESS_EXPR + ))) + .get(); + assert_eq!(alice_staked_amount, managed_biguint!(1_500_000)); + }, + ); + + world.whitebox_call( + &use_module_whitebox, + ScCallStep::new().from(ALICE_ADDRESS_EXPR), + |sc| { + sc.unstake(managed_biguint!(500_000)); + + let alice_staked_amount = sc + .staked_amount(&managed_address!(&address_expr_to_address( + ALICE_ADDRESS_EXPR + ))) + .get(); + assert_eq!(alice_staked_amount, managed_biguint!(1_000_000)); + }, + ); + + world.check_state_step(CheckStateStep::new().put_account( + ALICE_ADDRESS_EXPR, + CheckAccount::new().esdt_balance(STAKING_TOKEN_ID_EXPR, rust_biguint!(1_000_000)), + )); } fn address_expr_to_address(address_expr: &str) -> Address { From a850924523b430f8fb0a628fb4cf19fcf5108bcd Mon Sep 17 00:00:00 2001 From: Ovidiu Stinga Date: Tue, 22 Aug 2023 15:55:44 +0300 Subject: [PATCH 03/21] add more tests for staking module --- .../tests/staking_module_whitebox_test.rs | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/contracts/feature-tests/use-module/tests/staking_module_whitebox_test.rs b/contracts/feature-tests/use-module/tests/staking_module_whitebox_test.rs index d95f6d94b7..36bfc0d949 100644 --- a/contracts/feature-tests/use-module/tests/staking_module_whitebox_test.rs +++ b/contracts/feature-tests/use-module/tests/staking_module_whitebox_test.rs @@ -208,6 +208,88 @@ fn test_staking_module() { ALICE_ADDRESS_EXPR, CheckAccount::new().esdt_balance(STAKING_TOKEN_ID_EXPR, rust_biguint!(1_000_000)), )); + + // alice vote to slash bob + world.whitebox_call( + &use_module_whitebox, + ScCallStep::new().from(ALICE_ADDRESS_EXPR), + |sc| { + sc.vote_slash_member(managed_address!(&address_expr_to_address(BOB_ADDRESS_EXPR))); + + assert_eq!( + sc.slashing_proposal_voters(&managed_address!(&address_expr_to_address( + BOB_ADDRESS_EXPR + ))) + .len(), + 1 + ); + assert!(sc + .slashing_proposal_voters(&managed_address!(&address_expr_to_address( + BOB_ADDRESS_EXPR + ))) + .contains(&managed_address!(&address_expr_to_address( + ALICE_ADDRESS_EXPR + )))); + }, + ); + + // bob vote to slash alice + world.whitebox_call( + &use_module_whitebox, + ScCallStep::new().from(BOB_ADDRESS_EXPR), + |sc| { + sc.vote_slash_member(managed_address!(&address_expr_to_address( + ALICE_ADDRESS_EXPR + ))); + }, + ); + + // try slash before quorum reached + world.whitebox_call_check( + &use_module_whitebox, + ScCallStep::new().from(BOB_ADDRESS_EXPR).no_expect(), + |sc| { + sc.slash_member(managed_address!(&address_expr_to_address( + ALICE_ADDRESS_EXPR + ))); + }, + |r| { + r.assert_user_error("Quorum not reached"); + }, + ); + + // carol vote + world.whitebox_call( + &use_module_whitebox, + ScCallStep::new().from(CAROL_ADDRESS_EXPR), + |sc| { + sc.vote_slash_member(managed_address!(&address_expr_to_address( + ALICE_ADDRESS_EXPR + ))); + + assert_eq!( + sc.slashing_proposal_voters(&managed_address!(&address_expr_to_address( + ALICE_ADDRESS_EXPR + ))) + .len(), + 2 + ); + assert!(sc + .slashing_proposal_voters(&managed_address!(&address_expr_to_address( + ALICE_ADDRESS_EXPR + ))) + .contains(&managed_address!(&address_expr_to_address( + BOB_ADDRESS_EXPR + )))); + assert!(sc + .slashing_proposal_voters(&managed_address!(&address_expr_to_address( + ALICE_ADDRESS_EXPR + ))) + .contains(&managed_address!(&address_expr_to_address( + CAROL_ADDRESS_EXPR + )))); + }, + ); } fn address_expr_to_address(address_expr: &str) -> Address { From 1177238e980da3786a88e4c4ab17f948c5aea956 Mon Sep 17 00:00:00 2001 From: Ovidiu Stinga Date: Tue, 22 Aug 2023 16:05:00 +0300 Subject: [PATCH 04/21] fully migrate staking module tests --- .../tests/staking_module_whitebox_test.rs | 103 ++++++++++++++++++ 1 file changed, 103 insertions(+) diff --git a/contracts/feature-tests/use-module/tests/staking_module_whitebox_test.rs b/contracts/feature-tests/use-module/tests/staking_module_whitebox_test.rs index 36bfc0d949..7fe9e993d5 100644 --- a/contracts/feature-tests/use-module/tests/staking_module_whitebox_test.rs +++ b/contracts/feature-tests/use-module/tests/staking_module_whitebox_test.rs @@ -290,6 +290,109 @@ fn test_staking_module() { )))); }, ); + + // slash alice + world.whitebox_call( + &use_module_whitebox, + ScCallStep::new().from(BOB_ADDRESS_EXPR), + |sc| { + sc.slash_member(managed_address!(&address_expr_to_address( + ALICE_ADDRESS_EXPR + ))); + + assert_eq!( + sc.staked_amount(&managed_address!(&address_expr_to_address( + ALICE_ADDRESS_EXPR + ))) + .get(), + managed_biguint!(REQUIRED_STAKE_AMOUNT - SLASH_AMOUNT) + ); + assert_eq!( + sc.total_slashed_amount().get(), + managed_biguint!(SLASH_AMOUNT) + ); + assert!(sc + .slashing_proposal_voters(&managed_address!(&address_expr_to_address( + ALICE_ADDRESS_EXPR + ))) + .is_empty()); + }, + ); + + // alice try vote after slash + world.whitebox_call_check( + &use_module_whitebox, + ScCallStep::new().from(ALICE_ADDRESS_EXPR).no_expect(), + |sc| { + sc.vote_slash_member(managed_address!(&address_expr_to_address(BOB_ADDRESS_EXPR))); + }, + |r| { + r.assert_user_error("Not enough stake"); + }, + ); + + // alice try unstake the remaining tokens + world.whitebox_call_check( + &use_module_whitebox, + ScCallStep::new().from(ALICE_ADDRESS_EXPR).no_expect(), + |sc| { + sc.unstake(managed_biguint!(400_000)); + }, + |r| { + r.assert_user_error("Not enough stake"); + }, + ); + + // alice remove from board members + world.whitebox_call( + &use_module_whitebox, + ScCallStep::new().from(OWNER_ADDRESS_EXPR), + |sc| { + // check alice's votes before slash + assert!(sc + .slashing_proposal_voters(&managed_address!(&address_expr_to_address( + BOB_ADDRESS_EXPR + ))) + .contains(&managed_address!(&address_expr_to_address( + ALICE_ADDRESS_EXPR + )))); + + sc.remove_board_member(&managed_address!(&address_expr_to_address( + ALICE_ADDRESS_EXPR + ))); + + assert_eq!(sc.user_whitelist().len(), 2); + assert!(!sc + .user_whitelist() + .contains(&managed_address!(&address_expr_to_address( + ALICE_ADDRESS_EXPR + )))); + + // alice's vote gets removed + assert!(sc + .slashing_proposal_voters(&managed_address!(&address_expr_to_address( + BOB_ADDRESS_EXPR + ))) + .is_empty()); + }, + ); + + // alice unstake ok + world.whitebox_call( + &use_module_whitebox, + ScCallStep::new().from(ALICE_ADDRESS_EXPR), + |sc| { + sc.unstake(managed_biguint!(400_000)); + }, + ); + + world.check_state_step(CheckStateStep::new().put_account( + ALICE_ADDRESS_EXPR, + CheckAccount::new().esdt_balance( + STAKING_TOKEN_ID_EXPR, + rust_biguint!(INITIAL_BALANCE - SLASH_AMOUNT), + ), + )); } fn address_expr_to_address(address_expr: &str) -> Address { From 0174ed50a8e8d4e74b8e0b826932d91a0822e1db Mon Sep 17 00:00:00 2001 From: Ovidiu Stinga Date: Tue, 22 Aug 2023 16:32:57 +0300 Subject: [PATCH 05/21] gov module tests migration basic setup --- .../tests/gov_module_whitebox_test.rs | 56 ++++ .../tests/staking_module_legacy_test.rs | 266 ------------------ 2 files changed, 56 insertions(+), 266 deletions(-) create mode 100644 contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs delete mode 100644 contracts/feature-tests/use-module/tests/staking_module_legacy_test.rs diff --git a/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs b/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs new file mode 100644 index 0000000000..672468644d --- /dev/null +++ b/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs @@ -0,0 +1,56 @@ +use multiversx_sc::types::Address; +use multiversx_sc_scenario::{scenario_model::AddressValue, ScenarioWorld}; + +const _GOV_TOKEN_ID_EXPR: &str = "str:GOV-123456"; +const _GOV_TOKEN_ID: &[u8] = b"GOV-123456"; +const _QUORUM: u64 = 1_500; +const _MIN_BALANCE_PROPOSAL: u64 = 500; +const _VOTING_DELAY_BLOCKS: u64 = 10; +const _VOTING_PERIOD_BLOCKS: u64 = 20; +const _LOCKING_PERIOD_BLOCKS: u64 = 30; + +const _INITIAL_GOV_TOKEN_BALANCE: u64 = 1_000; +const _GAS_LIMIT: u64 = 1_000_000; + +const _USE_MODULE_ADDRESS_EXPR: &str = "sc:use-module"; +const USE_MODULE_PATH_EXPR: &str = "file:output/use-module.wasm"; + +pub struct Payment { + pub token: Vec, + pub nonce: u64, + pub amount: u64, +} + +fn world() -> ScenarioWorld { + let mut blockchain = ScenarioWorld::new(); + blockchain.set_current_dir_from_workspace("contracts/features-tests/use-module"); + + blockchain.register_contract(USE_MODULE_PATH_EXPR, use_module::ContractBuilder); + blockchain +} + +fn setup() -> ScenarioWorld { + // setup + world() +} + +#[test] +fn test_init() { + setup(); +} + +#[test] +fn test_change_gov_config() {} + +#[test] +fn test_down_veto_gov_config() {} + +#[test] +fn test_abstain_vote_gov_config() {} + +#[test] +fn test_gov_cancel_defeated_proposal() {} + +fn _address_expr_to_address(address_expr: &str) -> Address { + AddressValue::from(address_expr).to_address() +} diff --git a/contracts/feature-tests/use-module/tests/staking_module_legacy_test.rs b/contracts/feature-tests/use-module/tests/staking_module_legacy_test.rs deleted file mode 100644 index 3d35ae4984..0000000000 --- a/contracts/feature-tests/use-module/tests/staking_module_legacy_test.rs +++ /dev/null @@ -1,266 +0,0 @@ -#![allow(deprecated)] // TODO: migrate tests - -use multiversx_sc::types::{EgldOrEsdtTokenIdentifier, ManagedVec}; -use multiversx_sc_modules::staking::StakingModule; -use multiversx_sc_scenario::{ - managed_address, managed_biguint, managed_token_id, rust_biguint, - testing_framework::BlockchainStateWrapper, -}; - -static STAKING_TOKEN_ID: &[u8] = b"STAKE-123456"; -const INITIAL_BALANCE: u64 = 2_000_000; -const REQUIRED_STAKE_AMOUNT: u64 = 1_000_000; -const SLASH_AMOUNT: u64 = 600_000; -const QUORUM: usize = 2; - -#[test] -fn staking_module_test() { - // setup accounts - let rust_zero = rust_biguint!(0); - let mut b_mock = BlockchainStateWrapper::new(); - let owner = b_mock.create_user_account(&rust_zero); - let alice = b_mock.create_user_account(&rust_zero); - let bob = b_mock.create_user_account(&rust_zero); - let carol = b_mock.create_user_account(&rust_zero); - let eve = b_mock.create_user_account(&rust_zero); - let staking_sc = b_mock.create_sc_account( - &rust_zero, - Some(&owner), - use_module::contract_obj, - "wasm path", - ); - - b_mock.set_esdt_balance(&alice, STAKING_TOKEN_ID, &rust_biguint!(INITIAL_BALANCE)); - b_mock.set_esdt_balance(&bob, STAKING_TOKEN_ID, &rust_biguint!(INITIAL_BALANCE)); - b_mock.set_esdt_balance(&carol, STAKING_TOKEN_ID, &rust_biguint!(INITIAL_BALANCE)); - b_mock.set_esdt_balance(&eve, STAKING_TOKEN_ID, &rust_biguint!(INITIAL_BALANCE)); - - // init module - b_mock - .execute_tx(&owner, &staking_sc, &rust_zero, |sc| { - let mut whitelist = ManagedVec::new(); - whitelist.push(managed_address!(&alice)); - whitelist.push(managed_address!(&bob)); - whitelist.push(managed_address!(&carol)); - - sc.init_staking_module( - &EgldOrEsdtTokenIdentifier::esdt(managed_token_id!(STAKING_TOKEN_ID)), - &managed_biguint!(REQUIRED_STAKE_AMOUNT), - &managed_biguint!(SLASH_AMOUNT), - QUORUM, - &whitelist, - ); - }) - .assert_ok(); - - // try stake - not a board member - b_mock - .execute_esdt_transfer( - &eve, - &staking_sc, - STAKING_TOKEN_ID, - 0, - &rust_biguint!(REQUIRED_STAKE_AMOUNT), - |sc| { - sc.stake(); - }, - ) - .assert_user_error("Only whitelisted members can stake"); - - // stake half and try unstake - b_mock - .execute_esdt_transfer( - &alice, - &staking_sc, - STAKING_TOKEN_ID, - 0, - &rust_biguint!(REQUIRED_STAKE_AMOUNT / 2), - |sc| { - sc.stake(); - }, - ) - .assert_ok(); - b_mock - .execute_tx(&alice, &staking_sc, &rust_zero, |sc| { - sc.unstake(managed_biguint!(REQUIRED_STAKE_AMOUNT / 4)); - }) - .assert_user_error("Not enough stake"); - - // bob and carol stake - b_mock - .execute_esdt_transfer( - &bob, - &staking_sc, - STAKING_TOKEN_ID, - 0, - &rust_biguint!(REQUIRED_STAKE_AMOUNT), - |sc| { - sc.stake(); - }, - ) - .assert_ok(); - b_mock - .execute_esdt_transfer( - &carol, - &staking_sc, - STAKING_TOKEN_ID, - 0, - &rust_biguint!(REQUIRED_STAKE_AMOUNT), - |sc| { - sc.stake(); - }, - ) - .assert_ok(); - - // try vote slash, not enough stake - b_mock - .execute_tx(&alice, &staking_sc, &rust_zero, |sc| { - sc.vote_slash_member(managed_address!(&bob)); - }) - .assert_user_error("Not enough stake"); - - // try vote slash, slashed address not a board member - b_mock - .execute_tx(&bob, &staking_sc, &rust_zero, |sc| { - sc.vote_slash_member(managed_address!(&eve)); - }) - .assert_user_error("Voted user is not a staked board member"); - - // alice stake over max amount and withdraw surplus - b_mock - .execute_esdt_transfer( - &alice, - &staking_sc, - STAKING_TOKEN_ID, - 0, - &rust_biguint!(REQUIRED_STAKE_AMOUNT), - |sc| { - sc.stake(); - - let alice_staked_amount = sc.staked_amount(&managed_address!(&alice)).get(); - assert_eq!(alice_staked_amount, managed_biguint!(1_500_000)); - }, - ) - .assert_ok(); - b_mock - .execute_tx(&alice, &staking_sc, &rust_zero, |sc| { - sc.unstake(managed_biguint!(500_000)); - - let alice_staked_amount = sc.staked_amount(&managed_address!(&alice)).get(); - assert_eq!(alice_staked_amount, managed_biguint!(1_000_000)); - }) - .assert_ok(); - b_mock.check_esdt_balance(&alice, STAKING_TOKEN_ID, &rust_biguint!(1_000_000)); - - // alice vote to slash bob - b_mock - .execute_tx(&alice, &staking_sc, &rust_zero, |sc| { - sc.vote_slash_member(managed_address!(&bob)); - - assert_eq!( - sc.slashing_proposal_voters(&managed_address!(&bob)).len(), - 1 - ); - assert!(sc - .slashing_proposal_voters(&managed_address!(&bob)) - .contains(&managed_address!(&alice))); - }) - .assert_ok(); - - // bob vote to slash alice - b_mock - .execute_tx(&bob, &staking_sc, &rust_zero, |sc| { - sc.vote_slash_member(managed_address!(&alice)); - }) - .assert_ok(); - - // try slash before quorum reached - b_mock - .execute_tx(&bob, &staking_sc, &rust_zero, |sc| { - sc.slash_member(managed_address!(&alice)); - }) - .assert_user_error("Quorum not reached"); - - // carol vote - b_mock - .execute_tx(&carol, &staking_sc, &rust_zero, |sc| { - sc.vote_slash_member(managed_address!(&alice)); - - assert_eq!( - sc.slashing_proposal_voters(&managed_address!(&alice)).len(), - 2 - ); - assert!(sc - .slashing_proposal_voters(&managed_address!(&alice)) - .contains(&managed_address!(&bob))); - assert!(sc - .slashing_proposal_voters(&managed_address!(&alice)) - .contains(&managed_address!(&carol))); - }) - .assert_ok(); - - // slash alice - b_mock - .execute_tx(&bob, &staking_sc, &rust_zero, |sc| { - sc.slash_member(managed_address!(&alice)); - - assert_eq!( - sc.staked_amount(&managed_address!(&alice)).get(), - managed_biguint!(REQUIRED_STAKE_AMOUNT - SLASH_AMOUNT) - ); - assert_eq!( - sc.total_slashed_amount().get(), - managed_biguint!(SLASH_AMOUNT) - ); - assert!(sc - .slashing_proposal_voters(&managed_address!(&alice)) - .is_empty()); - }) - .assert_ok(); - - // alice try vote after slash - b_mock - .execute_tx(&alice, &staking_sc, &rust_zero, |sc| { - sc.vote_slash_member(managed_address!(&bob)); - }) - .assert_user_error("Not enough stake"); - - // alice try unstake the remaining tokens - b_mock - .execute_tx(&alice, &staking_sc, &rust_zero, |sc| { - sc.unstake(managed_biguint!(400_000)); - }) - .assert_user_error("Not enough stake"); - - // alice remove from board members - b_mock - .execute_tx(&owner, &staking_sc, &rust_zero, |sc| { - // check alice's votes before slash - assert!(sc - .slashing_proposal_voters(&managed_address!(&bob)) - .contains(&managed_address!(&alice))); - - sc.remove_board_member(&managed_address!(&alice)); - - assert_eq!(sc.user_whitelist().len(), 2); - assert!(!sc.user_whitelist().contains(&managed_address!(&alice))); - - // alice's vote gets removed - assert!(sc - .slashing_proposal_voters(&managed_address!(&bob)) - .is_empty()); - }) - .assert_ok(); - - // alice unstake ok - b_mock - .execute_tx(&alice, &staking_sc, &rust_zero, |sc| { - sc.unstake(managed_biguint!(400_000)); - }) - .assert_ok(); - b_mock.check_esdt_balance( - &alice, - STAKING_TOKEN_ID, - &rust_biguint!(INITIAL_BALANCE - SLASH_AMOUNT), - ); -} From ddaa1a9e8dac105d5bb81a3d289ddc48967cf221 Mon Sep 17 00:00:00 2001 From: Ovidiu Stinga Date: Tue, 22 Aug 2023 16:45:42 +0300 Subject: [PATCH 06/21] fully migrated init test --- .../tests/gov_module_whitebox_test.rs | 88 ++++++++++++++++--- 1 file changed, 76 insertions(+), 12 deletions(-) diff --git a/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs b/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs index 672468644d..23f206544b 100644 --- a/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs +++ b/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs @@ -1,20 +1,30 @@ use multiversx_sc::types::Address; -use multiversx_sc_scenario::{scenario_model::AddressValue, ScenarioWorld}; +use multiversx_sc_modules::governance::governance_configurable::GovernanceConfigurablePropertiesModule; +use multiversx_sc_scenario::{ + managed_biguint, managed_token_id, rust_biguint, + scenario_model::{Account, AddressValue, ScDeployStep, SetStateStep}, + ScenarioWorld, WhiteboxContract, +}; -const _GOV_TOKEN_ID_EXPR: &str = "str:GOV-123456"; -const _GOV_TOKEN_ID: &[u8] = b"GOV-123456"; -const _QUORUM: u64 = 1_500; -const _MIN_BALANCE_PROPOSAL: u64 = 500; -const _VOTING_DELAY_BLOCKS: u64 = 10; -const _VOTING_PERIOD_BLOCKS: u64 = 20; -const _LOCKING_PERIOD_BLOCKS: u64 = 30; +const GOV_TOKEN_ID_EXPR: &str = "str:GOV-123456"; +const GOV_TOKEN_ID: &[u8] = b"GOV-123456"; +const QUORUM: u64 = 1_500; +const MIN_BALANCE_PROPOSAL: u64 = 500; +const VOTING_DELAY_BLOCKS: u64 = 10; +const VOTING_PERIOD_BLOCKS: u64 = 20; +const LOCKING_PERIOD_BLOCKS: u64 = 30; -const _INITIAL_GOV_TOKEN_BALANCE: u64 = 1_000; +const INITIAL_GOV_TOKEN_BALANCE: u64 = 1_000; const _GAS_LIMIT: u64 = 1_000_000; -const _USE_MODULE_ADDRESS_EXPR: &str = "sc:use-module"; +const USE_MODULE_ADDRESS_EXPR: &str = "sc:use-module"; const USE_MODULE_PATH_EXPR: &str = "file:output/use-module.wasm"; +const OWNER_ADDRESS_EXPR: &str = "address:owner"; +const FIRST_USER_ADDRESS_EXPR: &str = "address:first-user"; +const SECOND_USER_ADDRESS_EXPR: &str = "address:second-user"; +const THIRD_USER_ADDRESS_EXPR: &str = "address:third-user"; + pub struct Payment { pub token: Vec, pub nonce: u64, @@ -30,8 +40,62 @@ fn world() -> ScenarioWorld { } fn setup() -> ScenarioWorld { - // setup - world() + let mut world = world(); + + world.set_state_step( + SetStateStep::new() + .put_account( + OWNER_ADDRESS_EXPR, + Account::new() + .nonce(1) + .esdt_balance(GOV_TOKEN_ID_EXPR, rust_biguint!(INITIAL_GOV_TOKEN_BALANCE)), + ) + .new_address(OWNER_ADDRESS_EXPR, 1, USE_MODULE_ADDRESS_EXPR) + .put_account( + FIRST_USER_ADDRESS_EXPR, + Account::new() + .nonce(1) + .esdt_balance(GOV_TOKEN_ID_EXPR, rust_biguint!(INITIAL_GOV_TOKEN_BALANCE)), + ) + .put_account( + SECOND_USER_ADDRESS_EXPR, + Account::new() + .nonce(1) + .esdt_balance(GOV_TOKEN_ID_EXPR, rust_biguint!(INITIAL_GOV_TOKEN_BALANCE)), + ) + .put_account( + THIRD_USER_ADDRESS_EXPR, + Account::new() + .nonce(1) + .esdt_balance(GOV_TOKEN_ID_EXPR, rust_biguint!(INITIAL_GOV_TOKEN_BALANCE)), + ), + ); + + // init + let use_module_whitebox = + WhiteboxContract::new(USE_MODULE_ADDRESS_EXPR, use_module::contract_obj); + let use_module_code = world.code_expression(USE_MODULE_PATH_EXPR); + + world.whitebox_deploy( + &use_module_whitebox, + ScDeployStep::new() + .from(OWNER_ADDRESS_EXPR) + .code(use_module_code), + |sc| { + sc.init_governance_module( + managed_token_id!(GOV_TOKEN_ID), + managed_biguint!(QUORUM), + managed_biguint!(MIN_BALANCE_PROPOSAL), + VOTING_DELAY_BLOCKS, + VOTING_PERIOD_BLOCKS, + LOCKING_PERIOD_BLOCKS, + ); + }, + ); + + world.set_state_step(SetStateStep::new().block_nonce(10)); + + world } #[test] From a2df3262b8b2c106a2c9957719e9c030eeb96948 Mon Sep 17 00:00:00 2001 From: Ovidiu Stinga Date: Tue, 22 Aug 2023 16:53:17 +0300 Subject: [PATCH 07/21] add propose helper function --- .../tests/gov_module_whitebox_test.rs | 56 +++++++++++++++++-- 1 file changed, 51 insertions(+), 5 deletions(-) diff --git a/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs b/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs index 23f206544b..4270e3a095 100644 --- a/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs +++ b/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs @@ -1,8 +1,10 @@ -use multiversx_sc::types::Address; -use multiversx_sc_modules::governance::governance_configurable::GovernanceConfigurablePropertiesModule; +use multiversx_sc::types::{Address, ManagedVec, MultiValueEncoded}; +use multiversx_sc_modules::governance::{ + governance_configurable::GovernanceConfigurablePropertiesModule, GovernanceModule, +}; use multiversx_sc_scenario::{ - managed_biguint, managed_token_id, rust_biguint, - scenario_model::{Account, AddressValue, ScDeployStep, SetStateStep}, + managed_address, managed_biguint, managed_buffer, managed_token_id, rust_biguint, + scenario_model::{Account, AddressValue, ScCallStep, ScDeployStep, SetStateStep}, ScenarioWorld, WhiteboxContract, }; @@ -15,7 +17,7 @@ const VOTING_PERIOD_BLOCKS: u64 = 20; const LOCKING_PERIOD_BLOCKS: u64 = 30; const INITIAL_GOV_TOKEN_BALANCE: u64 = 1_000; -const _GAS_LIMIT: u64 = 1_000_000; +const GAS_LIMIT: u64 = 1_000_000; const USE_MODULE_ADDRESS_EXPR: &str = "sc:use-module"; const USE_MODULE_PATH_EXPR: &str = "file:output/use-module.wasm"; @@ -98,6 +100,50 @@ fn setup() -> ScenarioWorld { world } +pub fn propose( + world: &mut ScenarioWorld, + proposer: &Address, + gov_token_amount: u64, + dest_address: &Address, + endpoint_name: &[u8], + args: Vec>, +) -> usize { + let use_module_whitebox = + WhiteboxContract::new(USE_MODULE_ADDRESS_EXPR, use_module::contract_obj); + + let mut proposal_id = 0; + + world.whitebox_call( + &use_module_whitebox, + ScCallStep::new().from(proposer).esdt_transfer( + GOV_TOKEN_ID, + 0, + &rust_biguint!(gov_token_amount), + ), + |sc| { + let mut args_managed = ManagedVec::new(); + for arg in args { + args_managed.push(managed_buffer!(&arg)); + } + + let mut actions = MultiValueEncoded::new(); + actions.push( + ( + GAS_LIMIT, + managed_address!(dest_address), + managed_buffer!(endpoint_name), + args_managed, + ) + .into(), + ); + + proposal_id = sc.propose(managed_buffer!(b"change quorum"), actions); + }, + ); + + proposal_id +} + #[test] fn test_init() { setup(); From 1358bfbbbe7929274a1de868e58ea6753d63d0b6 Mon Sep 17 00:00:00 2001 From: Ovidiu Stinga Date: Tue, 22 Aug 2023 17:02:05 +0300 Subject: [PATCH 08/21] first propose check --- .../tests/gov_module_whitebox_test.rs | 35 +++++++++++++++++-- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs b/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs index 4270e3a095..32a110d1d1 100644 --- a/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs +++ b/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs @@ -1,6 +1,6 @@ use multiversx_sc::types::{Address, ManagedVec, MultiValueEncoded}; use multiversx_sc_modules::governance::{ - governance_configurable::GovernanceConfigurablePropertiesModule, GovernanceModule, + governance_configurable::GovernanceConfigurablePropertiesModule, GovernanceModule, governance_proposal::VoteType, }; use multiversx_sc_scenario::{ managed_address, managed_biguint, managed_buffer, managed_token_id, rust_biguint, @@ -150,7 +150,36 @@ fn test_init() { } #[test] -fn test_change_gov_config() {} +fn test_change_gov_config() { + let mut world = setup(); + let use_module_whitebox = + WhiteboxContract::new(USE_MODULE_ADDRESS_EXPR, use_module::contract_obj); + + let proposal_id = propose( + &mut world, + &address_expr_to_address(FIRST_USER_ADDRESS_EXPR), + 500, + &address_expr_to_address(USE_MODULE_ADDRESS_EXPR), + b"changeQuorum", + vec![1_000u64.to_be_bytes().to_vec()], + ); + + assert_eq!(proposal_id, 1); + + world.whitebox_call_check( + &use_module_whitebox, + ScCallStep::new() + .from(SECOND_USER_ADDRESS_EXPR) + .esdt_transfer(GOV_TOKEN_ID, 0, rust_biguint!(999)) + .no_expect(), + |sc| { + sc.vote(proposal_id, VoteType::UpVote); + }, + |r| { + r.assert_user_error("Proposal is not active"); + }, + ); +} #[test] fn test_down_veto_gov_config() {} @@ -161,6 +190,6 @@ fn test_abstain_vote_gov_config() {} #[test] fn test_gov_cancel_defeated_proposal() {} -fn _address_expr_to_address(address_expr: &str) -> Address { +fn address_expr_to_address(address_expr: &str) -> Address { AddressValue::from(address_expr).to_address() } From 8fc43dbbf9f41b489cb0e4be36e4b10c6b646223 Mon Sep 17 00:00:00 2001 From: Ovidiu Stinga Date: Tue, 22 Aug 2023 17:41:18 +0300 Subject: [PATCH 09/21] gov module fully working test --- .../tests/gov_module_whitebox_test.rs | 184 +++++++++++++++++- 1 file changed, 182 insertions(+), 2 deletions(-) diff --git a/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs b/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs index 32a110d1d1..9dd4fe0b6d 100644 --- a/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs +++ b/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs @@ -1,10 +1,13 @@ use multiversx_sc::types::{Address, ManagedVec, MultiValueEncoded}; use multiversx_sc_modules::governance::{ - governance_configurable::GovernanceConfigurablePropertiesModule, GovernanceModule, governance_proposal::VoteType, + governance_configurable::GovernanceConfigurablePropertiesModule, governance_proposal::VoteType, + GovernanceModule, }; use multiversx_sc_scenario::{ managed_address, managed_biguint, managed_buffer, managed_token_id, rust_biguint, - scenario_model::{Account, AddressValue, ScCallStep, ScDeployStep, SetStateStep}, + scenario_model::{ + Account, AddressValue, CheckAccount, CheckStateStep, ScCallStep, ScDeployStep, SetStateStep, + }, ScenarioWorld, WhiteboxContract, }; @@ -155,6 +158,8 @@ fn test_change_gov_config() { let use_module_whitebox = WhiteboxContract::new(USE_MODULE_ADDRESS_EXPR, use_module::contract_obj); + let mut current_block_nonce = 10; + let proposal_id = propose( &mut world, &address_expr_to_address(FIRST_USER_ADDRESS_EXPR), @@ -166,6 +171,7 @@ fn test_change_gov_config() { assert_eq!(proposal_id, 1); + // vote too early world.whitebox_call_check( &use_module_whitebox, ScCallStep::new() @@ -179,6 +185,180 @@ fn test_change_gov_config() { r.assert_user_error("Proposal is not active"); }, ); + + current_block_nonce += VOTING_DELAY_BLOCKS; + world.set_state_step(SetStateStep::new().block_nonce(current_block_nonce)); + + world.whitebox_call( + &use_module_whitebox, + ScCallStep::new() + .from(SECOND_USER_ADDRESS_EXPR) + .esdt_transfer(GOV_TOKEN_ID, 0, rust_biguint!(999)), + |sc| { + sc.vote(proposal_id, VoteType::UpVote); + }, + ); + + // try execute before queue + world.whitebox_call_check( + &use_module_whitebox, + ScCallStep::new().from(FIRST_USER_ADDRESS_EXPR).no_expect(), + |sc| { + sc.execute(proposal_id); + }, + |r| { + r.assert_user_error("Can only execute queued proposals"); + }, + ); + + // try queue before voting ends + world.whitebox_call_check( + &use_module_whitebox, + ScCallStep::new().from(FIRST_USER_ADDRESS_EXPR).no_expect(), + |sc| { + sc.queue(proposal_id); + }, + |r| { + r.assert_user_error("Can only queue succeeded proposals"); + }, + ); + + current_block_nonce += VOTING_PERIOD_BLOCKS; + world.set_state_step(SetStateStep::new().block_nonce(current_block_nonce)); + + // try queue not enough votes + world.whitebox_call_check( + &use_module_whitebox, + ScCallStep::new().from(FIRST_USER_ADDRESS_EXPR).no_expect(), + |sc| { + sc.queue(proposal_id); + }, + |r| { + r.assert_user_error("Can only queue succeeded proposals"); + }, + ); + + // user 1 vote again + world.set_state_step(SetStateStep::new().block_nonce(20)); + world.whitebox_call( + &use_module_whitebox, + ScCallStep::new() + .from(FIRST_USER_ADDRESS_EXPR) + .esdt_transfer(GOV_TOKEN_ID, 0, rust_biguint!(200)), + |sc| { + sc.vote(proposal_id, VoteType::UpVote); + }, + ); + + // owner downvote + world.whitebox_call( + &use_module_whitebox, + ScCallStep::new().from(OWNER_ADDRESS_EXPR).esdt_transfer( + GOV_TOKEN_ID, + 0, + rust_biguint!(200), + ), + |sc| { + sc.vote(proposal_id, VoteType::DownVote); + }, + ); + + // try queue too many downvotes + world.set_state_step(SetStateStep::new().block_nonce(45)); + world.whitebox_call_check( + &use_module_whitebox, + ScCallStep::new().from(FIRST_USER_ADDRESS_EXPR).no_expect(), + |sc| { + sc.queue(proposal_id); + }, + |r| { + r.assert_user_error("Can only queue succeeded proposals"); + }, + ); + + // user 1 vote again + world.set_state_step(SetStateStep::new().block_nonce(20)); + world.whitebox_call_check( + &use_module_whitebox, + ScCallStep::new() + .from(FIRST_USER_ADDRESS_EXPR) + .esdt_transfer(GOV_TOKEN_ID, 0, rust_biguint!(200)) + .no_expect(), + |sc| { + sc.vote(proposal_id, VoteType::UpVote); + }, + |r| { + r.assert_user_error("Already voted for this proposal"); + }, + ); + + // user 3 vote again + world.whitebox_call( + &use_module_whitebox, + ScCallStep::new() + .from(THIRD_USER_ADDRESS_EXPR) + .esdt_transfer(GOV_TOKEN_ID, 0, rust_biguint!(200)), + |sc| { + sc.vote(proposal_id, VoteType::UpVote); + }, + ); + + // queue ok + current_block_nonce = 45; + world.set_state_step(SetStateStep::new().block_nonce(current_block_nonce)); + world.whitebox_call( + &use_module_whitebox, + ScCallStep::new().from(FIRST_USER_ADDRESS_EXPR).no_expect(), + |sc| { + sc.queue(proposal_id); + }, + ); + + // try execute too early + world.whitebox_call_check( + &use_module_whitebox, + ScCallStep::new().from(FIRST_USER_ADDRESS_EXPR).no_expect(), + |sc| { + sc.execute(proposal_id); + }, + |r| { + r.assert_user_error("Proposal is in timelock status. Try again later"); + }, + ); + + // execute ok + current_block_nonce += LOCKING_PERIOD_BLOCKS; + world.set_state_step(SetStateStep::new().block_nonce(current_block_nonce)); + world.whitebox_call( + &use_module_whitebox, + ScCallStep::new().from(FIRST_USER_ADDRESS_EXPR).no_expect(), + |sc| { + sc.execute(proposal_id); + }, + ); + + // after execution, quorum changed from 1_500 to the proposed 1_000 + world.whitebox_query(&use_module_whitebox, |sc| { + assert_eq!(sc.quorum().get(), managed_biguint!(1_000)); + assert!(sc.proposals().item_is_empty(1)); + }); + + world.check_state_step(CheckStateStep::new().put_account( + FIRST_USER_ADDRESS_EXPR, + CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, rust_biguint!(300)), + )); + world.check_state_step(CheckStateStep::new().put_account( + SECOND_USER_ADDRESS_EXPR, + CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, rust_biguint!(1)), + )); + world.check_state_step(CheckStateStep::new().put_account( + THIRD_USER_ADDRESS_EXPR, + CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, rust_biguint!(800)), + )); + world.check_state_step(CheckStateStep::new().put_account( + OWNER_ADDRESS_EXPR, + CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, rust_biguint!(800)), + )); } #[test] From a16cde84f11db6950028f1d2ce28bb142fb6ea87 Mon Sep 17 00:00:00 2001 From: Ovidiu Stinga Date: Tue, 22 Aug 2023 17:54:05 +0300 Subject: [PATCH 10/21] second test for gov module --- .../tests/gov_module_whitebox_test.rs | 90 ++++++++++++++++++- 1 file changed, 86 insertions(+), 4 deletions(-) diff --git a/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs b/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs index 9dd4fe0b6d..8577840280 100644 --- a/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs +++ b/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs @@ -239,7 +239,8 @@ fn test_change_gov_config() { ); // user 1 vote again - world.set_state_step(SetStateStep::new().block_nonce(20)); + current_block_nonce = 20; + world.set_state_step(SetStateStep::new().block_nonce(current_block_nonce)); world.whitebox_call( &use_module_whitebox, ScCallStep::new() @@ -264,7 +265,8 @@ fn test_change_gov_config() { ); // try queue too many downvotes - world.set_state_step(SetStateStep::new().block_nonce(45)); + current_block_nonce = 45; + world.set_state_step(SetStateStep::new().block_nonce(current_block_nonce)); world.whitebox_call_check( &use_module_whitebox, ScCallStep::new().from(FIRST_USER_ADDRESS_EXPR).no_expect(), @@ -277,7 +279,8 @@ fn test_change_gov_config() { ); // user 1 vote again - world.set_state_step(SetStateStep::new().block_nonce(20)); + current_block_nonce = 20; + world.set_state_step(SetStateStep::new().block_nonce(current_block_nonce)); world.whitebox_call_check( &use_module_whitebox, ScCallStep::new() @@ -362,7 +365,86 @@ fn test_change_gov_config() { } #[test] -fn test_down_veto_gov_config() {} +fn test_down_veto_gov_config() { + let mut world = setup(); + let use_module_whitebox = + WhiteboxContract::new(USE_MODULE_ADDRESS_EXPR, use_module::contract_obj); + + let mut current_block_nonce = 10; + + let proposal_id = propose( + &mut world, + &address_expr_to_address(FIRST_USER_ADDRESS_EXPR), + 500, + &address_expr_to_address(USE_MODULE_ADDRESS_EXPR), + b"changeQuorum", + vec![1_000u64.to_be_bytes().to_vec()], + ); + + assert_eq!(proposal_id, 1); + + current_block_nonce += VOTING_DELAY_BLOCKS; + world.set_state_step(SetStateStep::new().block_nonce(current_block_nonce)); + + world.whitebox_call( + &use_module_whitebox, + ScCallStep::new() + .from(FIRST_USER_ADDRESS_EXPR) + .esdt_transfer(GOV_TOKEN_ID, 0, rust_biguint!(300)), + |sc| { + sc.vote(proposal_id, VoteType::UpVote); + }, + ); + + current_block_nonce = 20; + world.set_state_step(SetStateStep::new().block_nonce(current_block_nonce)); + world.whitebox_call( + &use_module_whitebox, + ScCallStep::new() + .from(SECOND_USER_ADDRESS_EXPR) + .esdt_transfer(GOV_TOKEN_ID, 0, rust_biguint!(200)), + |sc| { + sc.vote(proposal_id, VoteType::UpVote); + }, + ); + + world.whitebox_call( + &use_module_whitebox, + ScCallStep::new() + .from(THIRD_USER_ADDRESS_EXPR) + .esdt_transfer(GOV_TOKEN_ID, 0, rust_biguint!(200)), + |sc| { + sc.vote(proposal_id, VoteType::DownVetoVote); + }, + ); + + // Vote didn't succeed; + current_block_nonce = 45; + world.set_state_step(SetStateStep::new().block_nonce(current_block_nonce)); + world.whitebox_call_check( + &use_module_whitebox, + ScCallStep::new().from(FIRST_USER_ADDRESS_EXPR).no_expect(), + |sc| { + sc.queue(proposal_id); + }, + |r| { + r.assert_user_error("Can only queue succeeded proposals"); + }, + ); + + world.check_state_step(CheckStateStep::new().put_account( + FIRST_USER_ADDRESS_EXPR, + CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, rust_biguint!(200)), + )); + world.check_state_step(CheckStateStep::new().put_account( + SECOND_USER_ADDRESS_EXPR, + CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, rust_biguint!(800)), + )); + world.check_state_step(CheckStateStep::new().put_account( + THIRD_USER_ADDRESS_EXPR, + CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, rust_biguint!(800)), + )); +} #[test] fn test_abstain_vote_gov_config() {} From 31af881455076dc77f72682de6d3ce11895902e6 Mon Sep 17 00:00:00 2001 From: Ovidiu Stinga Date: Tue, 22 Aug 2023 17:59:58 +0300 Subject: [PATCH 11/21] and another working test --- .../tests/gov_module_whitebox_test.rs | 95 ++++++++++++++++++- 1 file changed, 94 insertions(+), 1 deletion(-) diff --git a/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs b/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs index 8577840280..1e633b5db7 100644 --- a/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs +++ b/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs @@ -447,7 +447,100 @@ fn test_down_veto_gov_config() { } #[test] -fn test_abstain_vote_gov_config() {} +fn test_abstain_vote_gov_config() { + let mut world = setup(); + let use_module_whitebox = + WhiteboxContract::new(USE_MODULE_ADDRESS_EXPR, use_module::contract_obj); + + let mut current_block_nonce = 10; + + let proposal_id = propose( + &mut world, + &address_expr_to_address(FIRST_USER_ADDRESS_EXPR), + 500, + &address_expr_to_address(USE_MODULE_ADDRESS_EXPR), + b"changeQuorum", + vec![1_000u64.to_be_bytes().to_vec()], + ); + + assert_eq!(proposal_id, 1); + + current_block_nonce += VOTING_DELAY_BLOCKS; + world.set_state_step(SetStateStep::new().block_nonce(current_block_nonce)); + + world.whitebox_call( + &use_module_whitebox, + ScCallStep::new() + .from(FIRST_USER_ADDRESS_EXPR) + .esdt_transfer(GOV_TOKEN_ID, 0, rust_biguint!(500)), + |sc| { + sc.vote(proposal_id, VoteType::UpVote); + }, + ); + + current_block_nonce = 20; + world.set_state_step(SetStateStep::new().block_nonce(current_block_nonce)); + world.whitebox_call( + &use_module_whitebox, + ScCallStep::new() + .from(SECOND_USER_ADDRESS_EXPR) + .esdt_transfer(GOV_TOKEN_ID, 0, rust_biguint!(400)), + |sc| { + sc.vote(proposal_id, VoteType::DownVote); + }, + ); + + world.whitebox_call( + &use_module_whitebox, + ScCallStep::new() + .from(THIRD_USER_ADDRESS_EXPR) + .esdt_transfer(GOV_TOKEN_ID, 0, rust_biguint!(600)), + |sc| { + sc.vote(proposal_id, VoteType::AbstainVote); + }, + ); + + // Vote didn't succeed; + current_block_nonce = 45; + world.set_state_step(SetStateStep::new().block_nonce(current_block_nonce)); + world.whitebox_call( + &use_module_whitebox, + ScCallStep::new().from(FIRST_USER_ADDRESS_EXPR).no_expect(), + |sc| { + sc.queue(proposal_id); + }, + ); + + // execute ok + current_block_nonce += LOCKING_PERIOD_BLOCKS; + world.set_state_step(SetStateStep::new().block_nonce(current_block_nonce)); + world.whitebox_call( + &use_module_whitebox, + ScCallStep::new().from(FIRST_USER_ADDRESS_EXPR).no_expect(), + |sc| { + sc.execute(proposal_id); + }, + ); + + // after execution, quorum changed from 1_500 to the proposed 1_000 + world.whitebox_query(&use_module_whitebox, |sc| { + assert_eq!(sc.quorum().get(), managed_biguint!(1_000)); + assert!(sc.proposals().item_is_empty(1)); + }); + + world.check_state_step(CheckStateStep::new().put_account( + FIRST_USER_ADDRESS_EXPR, + CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, rust_biguint!(0)), + )); + world.check_state_step(CheckStateStep::new().put_account( + SECOND_USER_ADDRESS_EXPR, + CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, rust_biguint!(600)), + )); + world.check_state_step(CheckStateStep::new().put_account( + THIRD_USER_ADDRESS_EXPR, + CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, rust_biguint!(400)), + )); +} #[test] fn test_gov_cancel_defeated_proposal() {} From d54f91241fec94887740189dad6adf3c13e5aa9e Mon Sep 17 00:00:00 2001 From: Ovidiu Stinga Date: Tue, 22 Aug 2023 18:04:11 +0300 Subject: [PATCH 12/21] fully migrate gov module with new syntax --- .../tests/gov_module_legacy_test.rs | 507 ------------------ .../tests/gov_module_whitebox_test.rs | 55 +- 2 files changed, 54 insertions(+), 508 deletions(-) delete mode 100644 contracts/feature-tests/use-module/tests/gov_module_legacy_test.rs diff --git a/contracts/feature-tests/use-module/tests/gov_module_legacy_test.rs b/contracts/feature-tests/use-module/tests/gov_module_legacy_test.rs deleted file mode 100644 index 1a51124bb5..0000000000 --- a/contracts/feature-tests/use-module/tests/gov_module_legacy_test.rs +++ /dev/null @@ -1,507 +0,0 @@ -#![allow(deprecated)] // TODO: migrate tests - -use multiversx_sc::types::{Address, ManagedVec, MultiValueEncoded}; -use multiversx_sc_modules::governance::{ - governance_configurable::GovernanceConfigurablePropertiesModule, governance_proposal::VoteType, - GovernanceModule, -}; -use multiversx_sc_scenario::{ - managed_address, managed_biguint, managed_buffer, managed_token_id, rust_biguint, - testing_framework::{BlockchainStateWrapper, ContractObjWrapper, TxResult}, - DebugApi, -}; - -static GOV_TOKEN_ID: &[u8] = b"GOV-123456"; -const QUORUM: u64 = 1_500; -const MIN_BALANCE_PROPOSAL: u64 = 500; -const VOTING_DELAY_BLOCKS: u64 = 10; -const VOTING_PERIOD_BLOCKS: u64 = 20; -const LOCKING_PERIOD_BLOCKS: u64 = 30; - -const INITIAL_GOV_TOKEN_BALANCE: u64 = 1_000; -const GAS_LIMIT: u64 = 1_000_000; - -pub struct Payment { - pub token: Vec, - pub nonce: u64, - pub amount: u64, -} - -pub struct GovSetup -where - GovBuilder: 'static + Copy + Fn() -> use_module::ContractObj, -{ - pub b_mock: BlockchainStateWrapper, - pub owner: Address, - pub first_user: Address, - pub second_user: Address, - pub third_user: Address, - pub gov_wrapper: ContractObjWrapper, GovBuilder>, - pub current_block: u64, -} - -impl GovSetup -where - GovBuilder: 'static + Copy + Fn() -> use_module::ContractObj, -{ - pub fn new(gov_builder: GovBuilder) -> Self { - let rust_zero = rust_biguint!(0); - let initial_gov = rust_biguint!(INITIAL_GOV_TOKEN_BALANCE); - - let mut b_mock = BlockchainStateWrapper::new(); - - let owner = b_mock.create_user_account(&rust_zero); - b_mock.set_esdt_balance(&owner, GOV_TOKEN_ID, &initial_gov); - - let first_user = b_mock.create_user_account(&rust_zero); - b_mock.set_esdt_balance(&first_user, GOV_TOKEN_ID, &initial_gov); - - let second_user = b_mock.create_user_account(&rust_zero); - b_mock.set_esdt_balance(&second_user, GOV_TOKEN_ID, &initial_gov); - - let third_user = b_mock.create_user_account(&rust_zero); - b_mock.set_esdt_balance(&third_user, GOV_TOKEN_ID, &initial_gov); - - let gov_wrapper = - b_mock.create_sc_account(&rust_zero, Some(&owner), gov_builder, "gov path"); - - b_mock - .execute_tx(&owner, &gov_wrapper, &rust_zero, |sc| { - sc.init_governance_module( - managed_token_id!(GOV_TOKEN_ID), - managed_biguint!(QUORUM), - managed_biguint!(MIN_BALANCE_PROPOSAL), - VOTING_DELAY_BLOCKS, - VOTING_PERIOD_BLOCKS, - LOCKING_PERIOD_BLOCKS, - ); - }) - .assert_ok(); - - b_mock.set_block_nonce(10); - - Self { - b_mock, - owner, - first_user, - second_user, - third_user, - gov_wrapper, - current_block: 10, - } - } - - pub fn propose( - &mut self, - proposer: &Address, - gov_token_amount: u64, - dest_address: &Address, - endpoint_name: &[u8], - args: Vec>, - ) -> (TxResult, usize) { - let mut proposal_id = 0; - let result = self.b_mock.execute_esdt_transfer( - proposer, - &self.gov_wrapper, - GOV_TOKEN_ID, - 0, - &rust_biguint!(gov_token_amount), - |sc| { - let mut args_managed = ManagedVec::new(); - for arg in args { - args_managed.push(managed_buffer!(&arg)); - } - - let mut actions = MultiValueEncoded::new(); - actions.push( - ( - GAS_LIMIT, - managed_address!(dest_address), - managed_buffer!(endpoint_name), - args_managed, - ) - .into(), - ); - - proposal_id = sc.propose(managed_buffer!(b"change quorum"), actions); - }, - ); - - (result, proposal_id) - } - - pub fn vote(&mut self, voter: &Address, proposal_id: usize, gov_token_amount: u64) -> TxResult { - self.b_mock.execute_esdt_transfer( - voter, - &self.gov_wrapper, - GOV_TOKEN_ID, - 0, - &rust_biguint!(gov_token_amount), - |sc| { - sc.vote(proposal_id, VoteType::UpVote); - }, - ) - } - - pub fn down_vote( - &mut self, - voter: &Address, - proposal_id: usize, - gov_token_amount: u64, - ) -> TxResult { - self.b_mock.execute_esdt_transfer( - voter, - &self.gov_wrapper, - GOV_TOKEN_ID, - 0, - &rust_biguint!(gov_token_amount), - |sc| { - sc.vote(proposal_id, VoteType::DownVote); - }, - ) - } - - pub fn down_veto_vote( - &mut self, - voter: &Address, - proposal_id: usize, - gov_token_amount: u64, - ) -> TxResult { - self.b_mock.execute_esdt_transfer( - voter, - &self.gov_wrapper, - GOV_TOKEN_ID, - 0, - &rust_biguint!(gov_token_amount), - |sc| { - sc.vote(proposal_id, VoteType::DownVetoVote); - }, - ) - } - - pub fn abstain_vote( - &mut self, - voter: &Address, - proposal_id: usize, - gov_token_amount: u64, - ) -> TxResult { - self.b_mock.execute_esdt_transfer( - voter, - &self.gov_wrapper, - GOV_TOKEN_ID, - 0, - &rust_biguint!(gov_token_amount), - |sc| { - sc.vote(proposal_id, VoteType::AbstainVote); - }, - ) - } - - pub fn queue(&mut self, proposal_id: usize) -> TxResult { - self.b_mock.execute_tx( - &self.first_user, - &self.gov_wrapper, - &rust_biguint!(0), - |sc| { - sc.queue(proposal_id); - }, - ) - } - - pub fn execute(&mut self, proposal_id: usize) -> TxResult { - self.b_mock.execute_tx( - &self.first_user, - &self.gov_wrapper, - &rust_biguint!(0), - |sc| { - sc.execute(proposal_id); - }, - ) - } - - pub fn cancel(&mut self, caller: &Address, proposal_id: usize) -> TxResult { - self.b_mock - .execute_tx(caller, &self.gov_wrapper, &rust_biguint!(0), |sc| { - sc.cancel(proposal_id); - }) - } - - pub fn increment_block_nonce(&mut self, inc_amount: u64) { - self.current_block += inc_amount; - self.b_mock.set_block_nonce(self.current_block); - } - - pub fn set_block_nonce(&mut self, block_nonce: u64) { - self.current_block = block_nonce; - self.b_mock.set_block_nonce(self.current_block); - } -} - -#[test] -fn init_gov_test() { - let _ = GovSetup::new(use_module::contract_obj); -} - -#[test] -fn change_gov_config_test() { - let mut gov_setup = GovSetup::new(use_module::contract_obj); - - let owner_addr = gov_setup.owner.clone(); - let first_user_addr = gov_setup.first_user.clone(); - let second_user_addr = gov_setup.second_user.clone(); - let third_user_addr = gov_setup.third_user.clone(); - let sc_addr = gov_setup.gov_wrapper.address_ref().clone(); - - let (result, proposal_id) = gov_setup.propose( - &first_user_addr, - 500, - &sc_addr, - b"changeQuorum", - vec![1_000u64.to_be_bytes().to_vec()], - ); - result.assert_ok(); - assert_eq!(proposal_id, 1); - - // vote too early - gov_setup - .vote(&second_user_addr, proposal_id, 999) - .assert_user_error("Proposal is not active"); - - gov_setup.increment_block_nonce(VOTING_DELAY_BLOCKS); - - gov_setup - .vote(&second_user_addr, proposal_id, 999) - .assert_ok(); - - // try execute before queue - gov_setup - .execute(proposal_id) - .assert_user_error("Can only execute queued proposals"); - - // try queue before voting ends - gov_setup - .queue(proposal_id) - .assert_user_error("Can only queue succeeded proposals"); - - gov_setup.increment_block_nonce(VOTING_PERIOD_BLOCKS); - - // try queue not enough votes - gov_setup - .queue(proposal_id) - .assert_user_error("Can only queue succeeded proposals"); - - // user 1 vote again - gov_setup.set_block_nonce(20); - gov_setup - .vote(&first_user_addr, proposal_id, 200) - .assert_ok(); - - // owner downvote - gov_setup - .down_vote(&owner_addr, proposal_id, 200) - .assert_ok(); - - // try queue too many downvotes - gov_setup.set_block_nonce(45); - gov_setup - .queue(proposal_id) - .assert_user_error("Can only queue succeeded proposals"); - - // user 1 vote again - gov_setup.set_block_nonce(20); - gov_setup - .vote(&first_user_addr, proposal_id, 200) - .assert_user_error("Already voted for this proposal"); - - // user 3 vote again - gov_setup - .vote(&third_user_addr, proposal_id, 200) - .assert_ok(); - - // queue ok - gov_setup.set_block_nonce(45); - gov_setup.queue(proposal_id).assert_ok(); - - // try execute too early - gov_setup - .execute(proposal_id) - .assert_user_error("Proposal is in timelock status. Try again later"); - - // execute ok - gov_setup.increment_block_nonce(LOCKING_PERIOD_BLOCKS); - gov_setup.execute(proposal_id).assert_ok(); - - // after execution, quorum changed from 1_500 to the proposed 1_000 - gov_setup - .b_mock - .execute_query(&gov_setup.gov_wrapper, |sc| { - assert_eq!(sc.quorum().get(), managed_biguint!(1_000)); - assert!(sc.proposals().item_is_empty(1)); - }) - .assert_ok(); - - gov_setup - .b_mock - .check_esdt_balance(&first_user_addr, GOV_TOKEN_ID, &rust_biguint!(300)); - gov_setup - .b_mock - .check_esdt_balance(&second_user_addr, GOV_TOKEN_ID, &rust_biguint!(1)); - gov_setup - .b_mock - .check_esdt_balance(&third_user_addr, GOV_TOKEN_ID, &rust_biguint!(800)); - gov_setup - .b_mock - .check_esdt_balance(&owner_addr, GOV_TOKEN_ID, &rust_biguint!(800)); -} - -#[test] -fn down_veto_gov_config_test() { - let mut gov_setup = GovSetup::new(use_module::contract_obj); - - let first_user_addr = gov_setup.first_user.clone(); - let second_user_addr = gov_setup.second_user.clone(); - let third_user_addr = gov_setup.third_user.clone(); - let sc_addr = gov_setup.gov_wrapper.address_ref().clone(); - - let (result, proposal_id) = gov_setup.propose( - &first_user_addr, - 500, - &sc_addr, - b"changeQuorum", - vec![1_000u64.to_be_bytes().to_vec()], - ); - result.assert_ok(); - assert_eq!(proposal_id, 1); - - gov_setup.increment_block_nonce(VOTING_DELAY_BLOCKS); - - gov_setup - .vote(&first_user_addr, proposal_id, 300) - .assert_ok(); - - gov_setup.increment_block_nonce(VOTING_PERIOD_BLOCKS); - - // user 1 vote again - gov_setup.set_block_nonce(20); - gov_setup - .vote(&second_user_addr, proposal_id, 200) - .assert_ok(); - - // user 3 vote again - gov_setup - .down_veto_vote(&third_user_addr, proposal_id, 200) - .assert_ok(); - - // Vote didn't succeed; - gov_setup.set_block_nonce(45); - gov_setup - .queue(proposal_id) - .assert_user_error("Can only queue succeeded proposals"); - - gov_setup - .b_mock - .check_esdt_balance(&first_user_addr, GOV_TOKEN_ID, &rust_biguint!(200)); - gov_setup - .b_mock - .check_esdt_balance(&second_user_addr, GOV_TOKEN_ID, &rust_biguint!(800)); - gov_setup - .b_mock - .check_esdt_balance(&third_user_addr, GOV_TOKEN_ID, &rust_biguint!(800)); -} - -#[test] -fn abstain_vote_gov_config_test() { - let mut gov_setup = GovSetup::new(use_module::contract_obj); - - let first_user_addr = gov_setup.first_user.clone(); - let second_user_addr = gov_setup.second_user.clone(); - let third_user_addr = gov_setup.third_user.clone(); - let sc_addr = gov_setup.gov_wrapper.address_ref().clone(); - - let (result, proposal_id) = gov_setup.propose( - &first_user_addr, - 500, - &sc_addr, - b"changeQuorum", - vec![1_000u64.to_be_bytes().to_vec()], - ); - result.assert_ok(); - assert_eq!(proposal_id, 1); - - gov_setup.increment_block_nonce(VOTING_DELAY_BLOCKS); - - gov_setup - .vote(&first_user_addr, proposal_id, 500) - .assert_ok(); - - gov_setup.increment_block_nonce(VOTING_PERIOD_BLOCKS); - - // user 1 vote again - gov_setup.set_block_nonce(20); - gov_setup - .down_vote(&second_user_addr, proposal_id, 400) - .assert_ok(); - - // user 3 vote again - gov_setup - .abstain_vote(&third_user_addr, proposal_id, 600) - .assert_ok(); - - // Vote didn't succeed; - gov_setup.set_block_nonce(45); - gov_setup.queue(proposal_id).assert_ok(); - - // execute ok - gov_setup.increment_block_nonce(LOCKING_PERIOD_BLOCKS); - gov_setup.execute(proposal_id).assert_ok(); - - // after execution, quorum changed from 1_500 to the proposed 1_000 - gov_setup - .b_mock - .execute_query(&gov_setup.gov_wrapper, |sc| { - assert_eq!(sc.quorum().get(), managed_biguint!(1_000)); - assert!(sc.proposals().item_is_empty(1)); - }) - .assert_ok(); - - gov_setup - .b_mock - .check_esdt_balance(&first_user_addr, GOV_TOKEN_ID, &rust_biguint!(0)); - gov_setup - .b_mock - .check_esdt_balance(&second_user_addr, GOV_TOKEN_ID, &rust_biguint!(600)); - gov_setup - .b_mock - .check_esdt_balance(&third_user_addr, GOV_TOKEN_ID, &rust_biguint!(400)); -} - -#[test] -fn gov_cancel_defeated_proposal_test() { - let mut gov_setup = GovSetup::new(use_module::contract_obj); - - let first_user_addr = gov_setup.first_user.clone(); - let second_user_addr = gov_setup.second_user.clone(); - let sc_addr = gov_setup.gov_wrapper.address_ref().clone(); - let (result, proposal_id) = gov_setup.propose( - &first_user_addr, - 500, - &sc_addr, - b"changeQuorum", - vec![1_000u64.to_be_bytes().to_vec()], - ); - result.assert_ok(); - assert_eq!(proposal_id, 1); - - gov_setup.increment_block_nonce(VOTING_DELAY_BLOCKS); - gov_setup - .down_vote(&second_user_addr, proposal_id, 999) - .assert_ok(); - - // try cancel too early - gov_setup - .cancel(&second_user_addr, proposal_id) - .assert_user_error("Action may not be cancelled"); - - gov_setup.increment_block_nonce(VOTING_PERIOD_BLOCKS); - gov_setup.cancel(&second_user_addr, proposal_id).assert_ok(); -} diff --git a/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs b/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs index 1e633b5db7..7b8b5ff71e 100644 --- a/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs +++ b/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs @@ -543,7 +543,60 @@ fn test_abstain_vote_gov_config() { } #[test] -fn test_gov_cancel_defeated_proposal() {} +fn test_gov_cancel_defeated_proposal() { + let mut world = setup(); + let use_module_whitebox = + WhiteboxContract::new(USE_MODULE_ADDRESS_EXPR, use_module::contract_obj); + + let mut current_block_nonce = 10; + + let proposal_id = propose( + &mut world, + &address_expr_to_address(FIRST_USER_ADDRESS_EXPR), + 500, + &address_expr_to_address(USE_MODULE_ADDRESS_EXPR), + b"changeQuorum", + vec![1_000u64.to_be_bytes().to_vec()], + ); + + assert_eq!(proposal_id, 1); + + current_block_nonce += VOTING_DELAY_BLOCKS; + world.set_state_step(SetStateStep::new().block_nonce(current_block_nonce)); + + world.whitebox_call( + &use_module_whitebox, + ScCallStep::new() + .from(SECOND_USER_ADDRESS_EXPR) + .esdt_transfer(GOV_TOKEN_ID, 0, rust_biguint!(999)), + |sc| { + sc.vote(proposal_id, VoteType::DownVote); + }, + ); + + // try cancel too early + world.whitebox_call_check( + &use_module_whitebox, + ScCallStep::new().from(SECOND_USER_ADDRESS_EXPR).no_expect(), + |sc| { + sc.cancel(proposal_id); + }, + |r| { + r.assert_user_error("Action may not be cancelled"); + }, + ); + + current_block_nonce += VOTING_PERIOD_BLOCKS; + world.set_state_step(SetStateStep::new().block_nonce(current_block_nonce)); + + world.whitebox_call( + &use_module_whitebox, + ScCallStep::new().from(SECOND_USER_ADDRESS_EXPR).no_expect(), + |sc| { + sc.cancel(proposal_id); + }, + ); +} fn address_expr_to_address(address_expr: &str) -> Address { AddressValue::from(address_expr).to_address() From d8d6e151fac9e5cfb618b9edcdb780fb25cc9151 Mon Sep 17 00:00:00 2001 From: Ovidiu Stinga Date: Tue, 22 Aug 2023 18:10:33 +0300 Subject: [PATCH 13/21] token merge module migration basic setup --- .../tests/token_merge_module_whitebox_test.rs | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 contracts/feature-tests/use-module/tests/token_merge_module_whitebox_test.rs diff --git a/contracts/feature-tests/use-module/tests/token_merge_module_whitebox_test.rs b/contracts/feature-tests/use-module/tests/token_merge_module_whitebox_test.rs new file mode 100644 index 0000000000..45edf1c7df --- /dev/null +++ b/contracts/feature-tests/use-module/tests/token_merge_module_whitebox_test.rs @@ -0,0 +1,41 @@ +#![allow(unused)] + +use multiversx_sc::types::Address; +use multiversx_sc_scenario::{scenario_model::AddressValue, ScenarioWorld}; + +const OWNER_ADDRESS_EXPR: &str = "address:owner"; + +const USE_MODULE_ADDRESS_EXPR: &str = "sc:use-module"; +const USE_MODULE_PATH_EXPR: &str = "file:output/use-module.wasm"; + +const MERGED_TOKEN_ID_EXPR: &str = "str:MERGED-123456"; +const MERGED_TOKEN_ID: &[u8] = b"MERGED-123456"; +const NFT_TOKEN_ID_EXPR: &str = "str:NFT-123456"; +const NFT_TOKEN_ID: &[u8] = b"NFT-123456"; +const FUNGIBLE_TOKEN_ID_EXPR: &str = "str:FUN-123456"; +const FUNGIBLE_TOKEN_ID: &[u8] = b"FUN-123456"; + +const NFT_AMOUNT: u64 = 1; +const FUNGIBLE_AMOUNT: u64 = 100; + +const FIRST_NFT_NONCE: u64 = 5; +const FIRST_ATTRIBUTES: &[u8] = b"FirstAttributes"; +const FIRST_ROYALTIES: u64 = 1_000; +const FIRST_URIS: &[&[u8]] = &[b"FirstUri", b"SecondUri"]; + +const SECOND_NFT_NONCE: u64 = 7; +const SECOND_ATTRIBUTES: &[u8] = b"SecondAttributes"; +const SECOND_ROYALTIES: u64 = 5_000; +const SECOND_URIS: &[&[u8]] = &[b"cool.com/safe_file.exe"]; + +fn world() -> ScenarioWorld { + let mut blockchain = ScenarioWorld::new(); + blockchain.set_current_dir_from_workspace("contracts/features-tests/use-module"); + + blockchain.register_contract(USE_MODULE_PATH_EXPR, use_module::ContractBuilder); + blockchain +} + +fn address_expr_to_address(address_expr: &str) -> Address { + AddressValue::from(address_expr).to_address() +} From 146ae9289810c70fa2842599a97a936ba34fa4a9 Mon Sep 17 00:00:00 2001 From: Ovidiu Stinga Date: Tue, 22 Aug 2023 18:12:29 +0300 Subject: [PATCH 14/21] more basic setup --- .../tests/token_merge_module_whitebox_test.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/contracts/feature-tests/use-module/tests/token_merge_module_whitebox_test.rs b/contracts/feature-tests/use-module/tests/token_merge_module_whitebox_test.rs index 45edf1c7df..3832ad7bbb 100644 --- a/contracts/feature-tests/use-module/tests/token_merge_module_whitebox_test.rs +++ b/contracts/feature-tests/use-module/tests/token_merge_module_whitebox_test.rs @@ -36,6 +36,24 @@ fn world() -> ScenarioWorld { blockchain } +#[test] +fn test_token_merge() {} + +#[test] +fn test_partial_split() {} + +#[test] +fn test_custom_attributes() {} + fn address_expr_to_address(address_expr: &str) -> Address { AddressValue::from(address_expr).to_address() } + +fn uris_to_vec(uris: &[&[u8]]) -> Vec> { + let mut out = Vec::new(); + for uri in uris { + out.push((*uri).to_vec()); + } + + out +} From f12b02d30a97cd58d313e3b0454db9cc0009a94e Mon Sep 17 00:00:00 2001 From: Ovidiu Stinga Date: Tue, 22 Aug 2023 18:31:42 +0300 Subject: [PATCH 15/21] first test attempt --- .../tests/token_merge_module_whitebox_test.rs | 98 ++++++++++++++++++- 1 file changed, 95 insertions(+), 3 deletions(-) diff --git a/contracts/feature-tests/use-module/tests/token_merge_module_whitebox_test.rs b/contracts/feature-tests/use-module/tests/token_merge_module_whitebox_test.rs index 3832ad7bbb..fb6e72f8d3 100644 --- a/contracts/feature-tests/use-module/tests/token_merge_module_whitebox_test.rs +++ b/contracts/feature-tests/use-module/tests/token_merge_module_whitebox_test.rs @@ -1,9 +1,16 @@ #![allow(unused)] -use multiversx_sc::types::Address; -use multiversx_sc_scenario::{scenario_model::AddressValue, ScenarioWorld}; +use multiversx_sc::{storage::mappers::StorageTokenWrapper, types::Address}; +use multiversx_sc_modules::token_merge::merged_token_setup::MergedTokenSetupModule; +use multiversx_sc_scenario::{ + managed_token_id, rust_biguint, + scenario_model::{Account, AddressValue, ScCallStep, SetStateStep}, + testing_framework::TxTokenTransfer, + ScenarioWorld, WhiteboxContract, +}; const OWNER_ADDRESS_EXPR: &str = "address:owner"; +const USER_ADDRESS_EXPR: &str = "address:user"; const USE_MODULE_ADDRESS_EXPR: &str = "sc:use-module"; const USE_MODULE_PATH_EXPR: &str = "file:output/use-module.wasm"; @@ -37,7 +44,92 @@ fn world() -> ScenarioWorld { } #[test] -fn test_token_merge() {} +fn test_token_merge() { + let mut world = world(); + + let use_module_whitebox = + WhiteboxContract::new(USE_MODULE_ADDRESS_EXPR, use_module::contract_obj); + let use_modue_code = world.code_expression(USE_MODULE_PATH_EXPR); + + let roles = vec![ + "ESDTRoleNFTCreate".to_string(), + "ESDTRoleNFTBurn".to_string(), + ]; + + world.set_state_step( + SetStateStep::new() + .put_account(OWNER_ADDRESS_EXPR, Account::new().nonce(1)) + .put_account( + USER_ADDRESS_EXPR, + Account::new() + .nonce(1) + .esdt_balance(FUNGIBLE_TOKEN_ID_EXPR, rust_biguint!(FUNGIBLE_AMOUNT)), + ) + .put_account( + USE_MODULE_ADDRESS_EXPR, + Account::new() + .nonce(1) + .code(use_modue_code) + .owner(OWNER_ADDRESS_EXPR) + .esdt_roles(MERGED_TOKEN_ID_EXPR, roles), + ), + ); + + world.whitebox_call( + &use_module_whitebox, + ScCallStep::new().from(OWNER_ADDRESS_EXPR), + |sc| { + sc.merged_token() + .set_token_id(managed_token_id!(MERGED_TOKEN_ID)); + let _ = sc + .mergeable_tokens_whitelist() + .insert(managed_token_id!(NFT_TOKEN_ID)); + let _ = sc + .mergeable_tokens_whitelist() + .insert(managed_token_id!(FUNGIBLE_TOKEN_ID)); + }, + ); + + // TODO: implement esdt_nft_balance_all_properties + // b_mock.set_nft_balance_all_properties( + // &user, + // NFT_TOKEN_ID, + // FIRST_NFT_NONCE, + // &rust_biguint!(NFT_AMOUNT), + // &FIRST_ATTRIBUTES.to_vec(), + // FIRST_ROYALTIES, + // None, + // None, + // None, + // &uris_to_vec(FIRST_URIS), + // ); + // b_mock.set_nft_balance_all_properties( + // &user, + // NFT_TOKEN_ID, + // SECOND_NFT_NONCE, + // &rust_biguint!(NFT_AMOUNT), + // &SECOND_ATTRIBUTES.to_vec(), + // SECOND_ROYALTIES, + // None, + // None, + // None, + // &uris_to_vec(SECOND_URIS), + // ); + + // merge two NFTs + let nft_transfers = vec![ + TxTokenTransfer { + token_identifier: NFT_TOKEN_ID.to_vec(), + nonce: FIRST_NFT_NONCE, + value: rust_biguint!(NFT_AMOUNT), + }, + TxTokenTransfer { + token_identifier: NFT_TOKEN_ID.to_vec(), + nonce: SECOND_NFT_NONCE, + value: rust_biguint!(NFT_AMOUNT), + }, + ]; +} #[test] fn test_partial_split() {} From 6118c2439e413695c356951cf1b9c05728fa5177 Mon Sep 17 00:00:00 2001 From: Ovidiu Stinga Date: Mon, 18 Sep 2023 23:12:03 +0300 Subject: [PATCH 16/21] whitebox test full + some set step extension for nft all properties --- .../tests/token_merge_module_whitebox_test.rs | 778 ++++++++++++++++-- .../scenario/model/account_data/account.rs | 36 + .../scenario/model/esdt_data/esdt_object.rs | 65 ++ 3 files changed, 832 insertions(+), 47 deletions(-) diff --git a/contracts/feature-tests/use-module/tests/token_merge_module_whitebox_test.rs b/contracts/feature-tests/use-module/tests/token_merge_module_whitebox_test.rs index fb6e72f8d3..abb0490ae9 100644 --- a/contracts/feature-tests/use-module/tests/token_merge_module_whitebox_test.rs +++ b/contracts/feature-tests/use-module/tests/token_merge_module_whitebox_test.rs @@ -1,13 +1,22 @@ -#![allow(unused)] - -use multiversx_sc::{storage::mappers::StorageTokenWrapper, types::Address}; -use multiversx_sc_modules::token_merge::merged_token_setup::MergedTokenSetupModule; +use multiversx_sc::{ + arrayvec::ArrayVec, + codec::{test_util::top_encode_to_vec_u8_or_panic, Empty}, + contract_base::ContractBase, + storage::mappers::StorageTokenWrapper, + types::{Address, EsdtTokenPayment, ManagedVec}, +}; +use multiversx_sc_modules::token_merge::{ + merged_token_instances::MergedTokenInstances, merged_token_setup::MergedTokenSetupModule, +}; use multiversx_sc_scenario::{ - managed_token_id, rust_biguint, - scenario_model::{Account, AddressValue, ScCallStep, SetStateStep}, + managed_address, managed_biguint, managed_token_id, rust_biguint, + scenario_model::{ + Account, AddressValue, CheckAccount, CheckStateStep, ScCallStep, SetStateStep, + }, testing_framework::TxTokenTransfer, ScenarioWorld, WhiteboxContract, }; +use use_module::token_merge_mod_impl::{CustomAttributes, TokenMergeModImpl}; const OWNER_ADDRESS_EXPR: &str = "address:owner"; const USER_ADDRESS_EXPR: &str = "address:user"; @@ -49,7 +58,7 @@ fn test_token_merge() { let use_module_whitebox = WhiteboxContract::new(USE_MODULE_ADDRESS_EXPR, use_module::contract_obj); - let use_modue_code = world.code_expression(USE_MODULE_PATH_EXPR); + let use_module_code = world.code_expression(USE_MODULE_PATH_EXPR); let roles = vec![ "ESDTRoleNFTCreate".to_string(), @@ -63,13 +72,33 @@ fn test_token_merge() { USER_ADDRESS_EXPR, Account::new() .nonce(1) - .esdt_balance(FUNGIBLE_TOKEN_ID_EXPR, rust_biguint!(FUNGIBLE_AMOUNT)), + .esdt_balance(FUNGIBLE_TOKEN_ID_EXPR, rust_biguint!(FUNGIBLE_AMOUNT)) + .esdt_nft_all_properties( + NFT_TOKEN_ID_EXPR, + FIRST_NFT_NONCE, + NFT_AMOUNT, + Some(FIRST_ATTRIBUTES), + FIRST_ROYALTIES, + None, + None, + Vec::from(FIRST_URIS), + ) + .esdt_nft_all_properties( + NFT_TOKEN_ID_EXPR, + SECOND_NFT_NONCE, + NFT_AMOUNT, + Some(SECOND_ATTRIBUTES), + SECOND_ROYALTIES, + None, + None, + Vec::from(SECOND_URIS), + ), ) .put_account( USE_MODULE_ADDRESS_EXPR, Account::new() .nonce(1) - .code(use_modue_code) + .code(use_module_code) .owner(OWNER_ADDRESS_EXPR) .esdt_roles(MERGED_TOKEN_ID_EXPR, roles), ), @@ -90,34 +119,8 @@ fn test_token_merge() { }, ); - // TODO: implement esdt_nft_balance_all_properties - // b_mock.set_nft_balance_all_properties( - // &user, - // NFT_TOKEN_ID, - // FIRST_NFT_NONCE, - // &rust_biguint!(NFT_AMOUNT), - // &FIRST_ATTRIBUTES.to_vec(), - // FIRST_ROYALTIES, - // None, - // None, - // None, - // &uris_to_vec(FIRST_URIS), - // ); - // b_mock.set_nft_balance_all_properties( - // &user, - // NFT_TOKEN_ID, - // SECOND_NFT_NONCE, - // &rust_biguint!(NFT_AMOUNT), - // &SECOND_ATTRIBUTES.to_vec(), - // SECOND_ROYALTIES, - // None, - // None, - // None, - // &uris_to_vec(SECOND_URIS), - // ); - // merge two NFTs - let nft_transfers = vec![ + let _nft_transfers = vec![ TxTokenTransfer { token_identifier: NFT_TOKEN_ID.to_vec(), nonce: FIRST_NFT_NONCE, @@ -129,23 +132,704 @@ fn test_token_merge() { value: rust_biguint!(NFT_AMOUNT), }, ]; + + // TODO: change after multi_esdt_transfer implementation + world.whitebox_call( + &use_module_whitebox, + ScCallStep::new() + .from(USER_ADDRESS_EXPR) + .esdt_transfer(NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT) + .esdt_transfer(NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT), + |sc| { + let merged_token = sc.merge_tokens_endpoint(); + assert_eq!( + merged_token.token_identifier, + managed_token_id!(MERGED_TOKEN_ID) + ); + assert_eq!(merged_token.token_nonce, 1); + assert_eq!(merged_token.amount, managed_biguint!(NFT_AMOUNT)); + + let merged_token_data = sc.blockchain().get_esdt_token_data( + &managed_address!(&address_expr_to_address(USER_ADDRESS_EXPR)), + &managed_token_id!(MERGED_TOKEN_ID), + 1, + ); + let mut expected_uri = ArrayVec::new(); + expected_uri.push(EsdtTokenPayment::new( + managed_token_id!(NFT_TOKEN_ID), + FIRST_NFT_NONCE, + managed_biguint!(NFT_AMOUNT), + )); + expected_uri.push(EsdtTokenPayment::new( + managed_token_id!(NFT_TOKEN_ID), + SECOND_NFT_NONCE, + managed_biguint!(NFT_AMOUNT), + )); + + let actual_uri = MergedTokenInstances::decode_from_first_uri(&merged_token_data.uris); + assert_eq!(expected_uri, actual_uri.into_instances()); + + assert_eq!( + merged_token_data.royalties, + managed_biguint!(SECOND_ROYALTIES) + ); + }, + ); + + world.check_state_step(CheckStateStep::new().put_account( + USER_ADDRESS_EXPR, + CheckAccount::new().esdt_nft_balance_and_attributes( + MERGED_TOKEN_ID_EXPR, + 1, + NFT_AMOUNT, + Option::<&Empty>::None, + ), + )); + + world.check_state_step(CheckStateStep::new().put_account( + USE_MODULE_ADDRESS_EXPR, + CheckAccount::new().esdt_nft_balance_and_attributes( + NFT_TOKEN_ID_EXPR, + FIRST_NFT_NONCE, + NFT_AMOUNT, + Some(FIRST_ATTRIBUTES), + ), + )); + + world.check_state_step(CheckStateStep::new().put_account( + USE_MODULE_ADDRESS_EXPR, + CheckAccount::new().esdt_nft_balance_and_attributes( + NFT_TOKEN_ID_EXPR, + SECOND_NFT_NONCE, + NFT_AMOUNT, + Some(SECOND_ATTRIBUTES), + ), + )); + + // split nfts + world.whitebox_call( + &use_module_whitebox, + ScCallStep::new().from(USER_ADDRESS_EXPR).esdt_transfer( + MERGED_TOKEN_ID_EXPR, + 1, + NFT_AMOUNT, + ), + |sc| { + let output_tokens = sc.split_tokens_endpoint(); + let mut expected_output_tokens = ManagedVec::new(); + expected_output_tokens.push(EsdtTokenPayment::new( + managed_token_id!(NFT_TOKEN_ID), + FIRST_NFT_NONCE, + managed_biguint!(NFT_AMOUNT), + )); + expected_output_tokens.push(EsdtTokenPayment::new( + managed_token_id!(NFT_TOKEN_ID), + SECOND_NFT_NONCE, + managed_biguint!(NFT_AMOUNT), + )); + assert_eq!(output_tokens, expected_output_tokens); + }, + ); + + world.check_state_step(CheckStateStep::new().put_account( + USER_ADDRESS_EXPR, + CheckAccount::new().esdt_nft_balance_and_attributes( + NFT_TOKEN_ID_EXPR, + FIRST_NFT_NONCE, + NFT_AMOUNT, + Some(FIRST_ATTRIBUTES), + ), + )); + + world.check_state_step(CheckStateStep::new().put_account( + USER_ADDRESS_EXPR, + CheckAccount::new().esdt_nft_balance_and_attributes( + NFT_TOKEN_ID_EXPR, + SECOND_NFT_NONCE, + NFT_AMOUNT, + Some(SECOND_ATTRIBUTES), + ), + )); + + // merge the NFT with fungible + let _esdt_transfers = vec![ + TxTokenTransfer { + token_identifier: NFT_TOKEN_ID.to_vec(), + nonce: FIRST_NFT_NONCE, + value: rust_biguint!(NFT_AMOUNT), + }, + TxTokenTransfer { + token_identifier: FUNGIBLE_TOKEN_ID.to_vec(), + nonce: 0, + value: rust_biguint!(FUNGIBLE_AMOUNT), + }, + ]; + + // TODO: change after multi_esdt_transfer implementation + world.whitebox_call( + &use_module_whitebox, + ScCallStep::new() + .from(USER_ADDRESS_EXPR) + .esdt_transfer(NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT) + .esdt_transfer(FUNGIBLE_TOKEN_ID_EXPR, 0, FUNGIBLE_AMOUNT), + |sc| { + let merged_token = sc.merge_tokens_endpoint(); + assert_eq!( + merged_token.token_identifier, + managed_token_id!(MERGED_TOKEN_ID) + ); + assert_eq!(merged_token.token_nonce, 2); + assert_eq!(merged_token.amount, managed_biguint!(NFT_AMOUNT)); + + let merged_token_data = sc.blockchain().get_esdt_token_data( + &managed_address!(&address_expr_to_address(USER_ADDRESS_EXPR)), + &managed_token_id!(MERGED_TOKEN_ID), + 2, + ); + let mut expected_uri = ArrayVec::new(); + expected_uri.push(EsdtTokenPayment::new( + managed_token_id!(NFT_TOKEN_ID), + FIRST_NFT_NONCE, + managed_biguint!(NFT_AMOUNT), + )); + expected_uri.push(EsdtTokenPayment::new( + managed_token_id!(FUNGIBLE_TOKEN_ID), + 0, + managed_biguint!(FUNGIBLE_AMOUNT), + )); + + let actual_uri = MergedTokenInstances::decode_from_first_uri(&merged_token_data.uris); + assert_eq!(expected_uri, actual_uri.into_instances()); + + assert_eq!( + merged_token_data.royalties, + managed_biguint!(FIRST_ROYALTIES) + ); + }, + ); + + world.check_state_step(CheckStateStep::new().put_account( + USER_ADDRESS_EXPR, + CheckAccount::new().esdt_nft_balance_and_attributes( + MERGED_TOKEN_ID_EXPR, + 2, + NFT_AMOUNT, + Option::<&Empty>::None, + ), + )); + + // merge NFT with an already merged token + let _combined_transfers = vec![ + TxTokenTransfer { + token_identifier: NFT_TOKEN_ID.to_vec(), + nonce: SECOND_NFT_NONCE, + value: rust_biguint!(NFT_AMOUNT), + }, + TxTokenTransfer { + token_identifier: MERGED_TOKEN_ID.to_vec(), + nonce: 2, + value: rust_biguint!(NFT_AMOUNT), + }, + ]; + + // TODO: change after multi_esdt_transfer implementation + world.whitebox_call( + &use_module_whitebox, + ScCallStep::new() + .from(USER_ADDRESS_EXPR) + .esdt_transfer(NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT) + .esdt_transfer(MERGED_TOKEN_ID_EXPR, 2, NFT_AMOUNT), + |sc| { + let merged_token = sc.merge_tokens_endpoint(); + assert_eq!( + merged_token.token_identifier, + managed_token_id!(MERGED_TOKEN_ID) + ); + assert_eq!(merged_token.token_nonce, 3); + assert_eq!(merged_token.amount, managed_biguint!(NFT_AMOUNT)); + + let merged_token_data = sc.blockchain().get_esdt_token_data( + &managed_address!(&address_expr_to_address(USER_ADDRESS_EXPR)), + &managed_token_id!(MERGED_TOKEN_ID), + 3, + ); + let mut expected_uri = ArrayVec::new(); + expected_uri.push(EsdtTokenPayment::new( + managed_token_id!(NFT_TOKEN_ID), + FIRST_NFT_NONCE, + managed_biguint!(NFT_AMOUNT), + )); + expected_uri.push(EsdtTokenPayment::new( + managed_token_id!(FUNGIBLE_TOKEN_ID), + 0, + managed_biguint!(FUNGIBLE_AMOUNT), + )); + expected_uri.push(EsdtTokenPayment::new( + managed_token_id!(NFT_TOKEN_ID), + SECOND_NFT_NONCE, + managed_biguint!(NFT_AMOUNT), + )); + + let actual_uri = MergedTokenInstances::decode_from_first_uri(&merged_token_data.uris); + assert_eq!(expected_uri, actual_uri.into_instances()); + + assert_eq!( + merged_token_data.royalties, + managed_biguint!(SECOND_ROYALTIES) + ); + }, + ); + + world.check_state_step(CheckStateStep::new().put_account( + USER_ADDRESS_EXPR, + CheckAccount::new().esdt_nft_balance_and_attributes( + MERGED_TOKEN_ID_EXPR, + 3, + NFT_AMOUNT, + Option::<&Empty>::None, + ), + )); + + world.whitebox_call( + &use_module_whitebox, + ScCallStep::new().from(USER_ADDRESS_EXPR).esdt_transfer( + MERGED_TOKEN_ID_EXPR, + 3, + NFT_AMOUNT, + ), + |sc| { + let output_tokens = sc.split_tokens_endpoint(); + let mut expected_output_tokens = ManagedVec::new(); + expected_output_tokens.push(EsdtTokenPayment::new( + managed_token_id!(NFT_TOKEN_ID), + FIRST_NFT_NONCE, + managed_biguint!(NFT_AMOUNT), + )); + expected_output_tokens.push(EsdtTokenPayment::new( + managed_token_id!(FUNGIBLE_TOKEN_ID), + 0, + managed_biguint!(FUNGIBLE_AMOUNT), + )); + expected_output_tokens.push(EsdtTokenPayment::new( + managed_token_id!(NFT_TOKEN_ID), + SECOND_NFT_NONCE, + managed_biguint!(NFT_AMOUNT), + )); + + assert_eq!(output_tokens, expected_output_tokens); + }, + ); + + world.check_state_step(CheckStateStep::new().put_account( + USER_ADDRESS_EXPR, + CheckAccount::new().esdt_nft_balance_and_attributes( + NFT_TOKEN_ID_EXPR, + FIRST_NFT_NONCE, + NFT_AMOUNT, + Some(FIRST_ATTRIBUTES), + ), + )); + + world.check_state_step(CheckStateStep::new().put_account( + USER_ADDRESS_EXPR, + CheckAccount::new().esdt_nft_balance_and_attributes( + NFT_TOKEN_ID_EXPR, + SECOND_NFT_NONCE, + NFT_AMOUNT, + Some(SECOND_ATTRIBUTES), + ), + )); + + world.check_state_step(CheckStateStep::new().put_account( + USER_ADDRESS_EXPR, + CheckAccount::new().esdt_balance(FUNGIBLE_TOKEN_ID_EXPR, FUNGIBLE_AMOUNT), + )); } #[test] -fn test_partial_split() {} +fn test_partial_split() { + let mut world = world(); -#[test] -fn test_custom_attributes() {} + let use_module_whitebox = + WhiteboxContract::new(USE_MODULE_ADDRESS_EXPR, use_module::contract_obj); + let use_module_code = world.code_expression(USE_MODULE_PATH_EXPR); -fn address_expr_to_address(address_expr: &str) -> Address { - AddressValue::from(address_expr).to_address() + let roles = vec![ + "ESDTRoleNFTCreate".to_string(), + "ESDTRoleNFTBurn".to_string(), + ]; + + world.set_state_step( + SetStateStep::new() + .put_account(OWNER_ADDRESS_EXPR, Account::new().nonce(1)) + .put_account( + USER_ADDRESS_EXPR, + Account::new() + .nonce(1) + .esdt_balance(FUNGIBLE_TOKEN_ID_EXPR, rust_biguint!(FUNGIBLE_AMOUNT)) + .esdt_nft_all_properties( + NFT_TOKEN_ID_EXPR, + FIRST_NFT_NONCE, + NFT_AMOUNT, + Some(FIRST_ATTRIBUTES), + FIRST_ROYALTIES, + None, + None, + Vec::from(FIRST_URIS), + ) + .esdt_nft_all_properties( + NFT_TOKEN_ID_EXPR, + SECOND_NFT_NONCE, + NFT_AMOUNT, + Some(SECOND_ATTRIBUTES), + SECOND_ROYALTIES, + None, + None, + Vec::from(SECOND_URIS), + ), + ) + .put_account( + USE_MODULE_ADDRESS_EXPR, + Account::new() + .nonce(1) + .code(use_module_code) + .owner(OWNER_ADDRESS_EXPR) + .esdt_roles(MERGED_TOKEN_ID_EXPR, roles), + ), + ); + + world.whitebox_call( + &use_module_whitebox, + ScCallStep::new().from(OWNER_ADDRESS_EXPR), + |sc| { + sc.merged_token() + .set_token_id(managed_token_id!(MERGED_TOKEN_ID)); + let _ = sc + .mergeable_tokens_whitelist() + .insert(managed_token_id!(NFT_TOKEN_ID)); + let _ = sc + .mergeable_tokens_whitelist() + .insert(managed_token_id!(FUNGIBLE_TOKEN_ID)); + }, + ); + + // merge 2 NFTs and a fungible token + let _esdt_transfers = vec![ + TxTokenTransfer { + token_identifier: NFT_TOKEN_ID.to_vec(), + nonce: FIRST_NFT_NONCE, + value: rust_biguint!(NFT_AMOUNT), + }, + TxTokenTransfer { + token_identifier: NFT_TOKEN_ID.to_vec(), + nonce: SECOND_NFT_NONCE, + value: rust_biguint!(NFT_AMOUNT), + }, + TxTokenTransfer { + token_identifier: FUNGIBLE_TOKEN_ID.to_vec(), + nonce: 0, + value: rust_biguint!(FUNGIBLE_AMOUNT), + }, + ]; + + // TODO: change after multi_esdt_transfer implementation + world.whitebox_call( + &use_module_whitebox, + ScCallStep::new() + .from(USER_ADDRESS_EXPR) + .esdt_transfer(NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT) + .esdt_transfer(NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT) + .esdt_transfer(FUNGIBLE_TOKEN_ID_EXPR, 0, FUNGIBLE_AMOUNT), + |sc| { + let merged_token = sc.merge_tokens_endpoint(); + assert_eq!( + merged_token.token_identifier, + managed_token_id!(MERGED_TOKEN_ID) + ); + assert_eq!(merged_token.token_nonce, 1); + assert_eq!(merged_token.amount, managed_biguint!(NFT_AMOUNT)); + + let merged_token_data = sc.blockchain().get_esdt_token_data( + &managed_address!(&address_expr_to_address(USER_ADDRESS_EXPR)), + &managed_token_id!(MERGED_TOKEN_ID), + 1, + ); + let mut expected_uri = ArrayVec::new(); + expected_uri.push(EsdtTokenPayment::new( + managed_token_id!(NFT_TOKEN_ID), + FIRST_NFT_NONCE, + managed_biguint!(NFT_AMOUNT), + )); + expected_uri.push(EsdtTokenPayment::new( + managed_token_id!(NFT_TOKEN_ID), + SECOND_NFT_NONCE, + managed_biguint!(NFT_AMOUNT), + )); + expected_uri.push(EsdtTokenPayment::new( + managed_token_id!(FUNGIBLE_TOKEN_ID), + 0, + managed_biguint!(FUNGIBLE_AMOUNT), + )); + + let actual_uri = MergedTokenInstances::decode_from_first_uri(&merged_token_data.uris); + assert_eq!(expected_uri, actual_uri.into_instances()); + }, + ); + + // split part of the fungible token + world.whitebox_call( + &use_module_whitebox, + ScCallStep::new().from(USER_ADDRESS_EXPR).esdt_transfer( + MERGED_TOKEN_ID_EXPR, + 1, + NFT_AMOUNT, + ), + |sc| { + let mut tokens_to_remove = ManagedVec::new(); + tokens_to_remove.push(EsdtTokenPayment::new( + managed_token_id!(FUNGIBLE_TOKEN_ID), + 0, + managed_biguint!(40), + )); + let output_payments = sc.split_token_partial_endpoint(tokens_to_remove); + + let mut expected_output_payments = ManagedVec::new(); + expected_output_payments.push(EsdtTokenPayment::new( + managed_token_id!(FUNGIBLE_TOKEN_ID), + 0, + managed_biguint!(40), + )); + expected_output_payments.push(EsdtTokenPayment::new( + managed_token_id!(MERGED_TOKEN_ID), + 2, + managed_biguint!(NFT_AMOUNT), + )); + assert_eq!(output_payments, expected_output_payments); + }, + ); + + // fully remove instance + world.whitebox_call( + &use_module_whitebox, + ScCallStep::new().from(USER_ADDRESS_EXPR).esdt_transfer( + MERGED_TOKEN_ID_EXPR, + 2, + NFT_AMOUNT, + ), + |sc| { + let mut tokens_to_remove = ManagedVec::new(); + tokens_to_remove.push(EsdtTokenPayment::new( + managed_token_id!(NFT_TOKEN_ID), + FIRST_NFT_NONCE, + managed_biguint!(NFT_AMOUNT), + )); + let output_payments = sc.split_token_partial_endpoint(tokens_to_remove); + + let mut expected_output_payments = ManagedVec::new(); + expected_output_payments.push(EsdtTokenPayment::new( + managed_token_id!(NFT_TOKEN_ID), + FIRST_NFT_NONCE, + managed_biguint!(NFT_AMOUNT), + )); + expected_output_payments.push(EsdtTokenPayment::new( + managed_token_id!(MERGED_TOKEN_ID), + 3, + managed_biguint!(NFT_AMOUNT), + )); + assert_eq!(output_payments, expected_output_payments); + + // check newest token attributes + let merged_token_data = sc.blockchain().get_esdt_token_data( + &managed_address!(&address_expr_to_address(USER_ADDRESS_EXPR)), + &managed_token_id!(MERGED_TOKEN_ID), + 3, + ); + let mut expected_uri = ArrayVec::new(); + expected_uri.push(EsdtTokenPayment::new( + managed_token_id!(NFT_TOKEN_ID), + SECOND_NFT_NONCE, + managed_biguint!(NFT_AMOUNT), + )); + expected_uri.push(EsdtTokenPayment::new( + managed_token_id!(FUNGIBLE_TOKEN_ID), + 0, + managed_biguint!(FUNGIBLE_AMOUNT - 40), + )); + + let actual_uri = MergedTokenInstances::decode_from_first_uri(&merged_token_data.uris); + assert_eq!(expected_uri, actual_uri.into_instances()); + + assert_eq!( + merged_token_data.royalties, + managed_biguint!(SECOND_ROYALTIES) + ); + }, + ); } -fn uris_to_vec(uris: &[&[u8]]) -> Vec> { - let mut out = Vec::new(); - for uri in uris { - out.push((*uri).to_vec()); - } +#[test] +fn test_custom_attributes() { + let mut world = world(); + + let use_module_whitebox = + WhiteboxContract::new(USE_MODULE_ADDRESS_EXPR, use_module::contract_obj); + let use_module_code = world.code_expression(USE_MODULE_PATH_EXPR); + + let roles = vec![ + "ESDTRoleNFTCreate".to_string(), + "ESDTRoleNFTBurn".to_string(), + ]; - out + world.set_state_step( + SetStateStep::new() + .put_account(OWNER_ADDRESS_EXPR, Account::new().nonce(1)) + .put_account( + USER_ADDRESS_EXPR, + Account::new() + .nonce(1) + .esdt_balance(FUNGIBLE_TOKEN_ID_EXPR, rust_biguint!(FUNGIBLE_AMOUNT)) + .esdt_nft_all_properties( + NFT_TOKEN_ID_EXPR, + FIRST_NFT_NONCE, + NFT_AMOUNT, + Some(FIRST_ATTRIBUTES), + FIRST_ROYALTIES, + None, + None, + Vec::from(FIRST_URIS), + ) + .esdt_nft_all_properties( + NFT_TOKEN_ID_EXPR, + SECOND_NFT_NONCE, + NFT_AMOUNT, + Some(SECOND_ATTRIBUTES), + SECOND_ROYALTIES, + None, + None, + Vec::from(SECOND_URIS), + ), + ) + .put_account( + USE_MODULE_ADDRESS_EXPR, + Account::new() + .nonce(1) + .code(use_module_code) + .owner(OWNER_ADDRESS_EXPR) + .esdt_roles(MERGED_TOKEN_ID_EXPR, roles), + ), + ); + + world.whitebox_call( + &use_module_whitebox, + ScCallStep::new().from(OWNER_ADDRESS_EXPR), + |sc| { + sc.merged_token() + .set_token_id(managed_token_id!(MERGED_TOKEN_ID)); + let _ = sc + .mergeable_tokens_whitelist() + .insert(managed_token_id!(NFT_TOKEN_ID)); + let _ = sc + .mergeable_tokens_whitelist() + .insert(managed_token_id!(FUNGIBLE_TOKEN_ID)); + }, + ); + + // merge two NFTs + let _nft_transfers = vec![ + TxTokenTransfer { + token_identifier: NFT_TOKEN_ID.to_vec(), + nonce: FIRST_NFT_NONCE, + value: rust_biguint!(NFT_AMOUNT), + }, + TxTokenTransfer { + token_identifier: NFT_TOKEN_ID.to_vec(), + nonce: SECOND_NFT_NONCE, + value: rust_biguint!(NFT_AMOUNT), + }, + ]; + + let expected_attributes = CustomAttributes { + first: 5u32, + second: 10u64, + }; + + // TODO: change after multi_esdt_transfer implementation + world.whitebox_call( + &use_module_whitebox, + ScCallStep::new() + .from(USER_ADDRESS_EXPR) + .esdt_transfer(NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT) + .esdt_transfer(NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT), + |sc| { + let merged_token = sc.merge_tokens_custom_attributes_endpoint(); + assert_eq!( + merged_token.token_identifier, + managed_token_id!(MERGED_TOKEN_ID) + ); + assert_eq!(merged_token.token_nonce, 1); + assert_eq!(merged_token.amount, managed_biguint!(NFT_AMOUNT)); + + let merged_token_data = sc.blockchain().get_esdt_token_data( + &managed_address!(&address_expr_to_address(USER_ADDRESS_EXPR)), + &managed_token_id!(MERGED_TOKEN_ID), + 1, + ); + let mut expected_uri = ArrayVec::new(); + expected_uri.push(EsdtTokenPayment::new( + managed_token_id!(NFT_TOKEN_ID), + FIRST_NFT_NONCE, + managed_biguint!(NFT_AMOUNT), + )); + expected_uri.push(EsdtTokenPayment::new( + managed_token_id!(NFT_TOKEN_ID), + SECOND_NFT_NONCE, + managed_biguint!(NFT_AMOUNT), + )); + + let actual_uri = MergedTokenInstances::decode_from_first_uri(&merged_token_data.uris); + assert_eq!(expected_uri, actual_uri.into_instances()); + + let actual_attributes: CustomAttributes = merged_token_data.decode_attributes(); + assert_eq!(expected_attributes, actual_attributes); + + assert_eq!( + merged_token_data.royalties, + managed_biguint!(SECOND_ROYALTIES) + ); + }, + ); + + world.check_state_step(CheckStateStep::new().put_account( + USER_ADDRESS_EXPR, + CheckAccount::new().esdt_nft_balance_and_attributes( + MERGED_TOKEN_ID_EXPR, + 1, + NFT_AMOUNT, + Some(top_encode_to_vec_u8_or_panic(&expected_attributes)), + ), + )); + + world.check_state_step(CheckStateStep::new().put_account( + USE_MODULE_ADDRESS_EXPR, + CheckAccount::new().esdt_nft_balance_and_attributes( + NFT_TOKEN_ID_EXPR, + FIRST_NFT_NONCE, + NFT_AMOUNT, + Some(FIRST_ATTRIBUTES), + ), + )); + + world.check_state_step(CheckStateStep::new().put_account( + USE_MODULE_ADDRESS_EXPR, + CheckAccount::new().esdt_nft_balance_and_attributes( + NFT_TOKEN_ID_EXPR, + SECOND_NFT_NONCE, + NFT_AMOUNT, + Some(SECOND_ATTRIBUTES), + ), + )); +} + +fn address_expr_to_address(address_expr: &str) -> Address { + AddressValue::from(address_expr).to_address() } diff --git a/framework/scenario/src/scenario/model/account_data/account.rs b/framework/scenario/src/scenario/model/account_data/account.rs index 75c3fccf86..0c456b84bb 100644 --- a/framework/scenario/src/scenario/model/account_data/account.rs +++ b/framework/scenario/src/scenario/model/account_data/account.rs @@ -84,6 +84,42 @@ impl Account { self } + pub fn esdt_nft_all_properties( + mut self, + token_id_expr: K, + nonce_expr: N, + balance_expr: V, + opt_attributes_expr: Option, + royalties_expr: N, + creator_expr: Option, + hash_expr: Option, + uris_expr: Vec, + ) -> Self + where + BytesKey: From, + U64Value: From, + BigUintValue: From, + BytesValue: From, + { + let token_id = BytesKey::from(token_id_expr); + + let esdt_obj_ref = self + .get_esdt_data_or_create(&token_id) + .get_mut_esdt_object(); + + esdt_obj_ref.ovidiu( + nonce_expr, + balance_expr, + opt_attributes_expr, + royalties_expr, + creator_expr, + hash_expr, + uris_expr, + ); + + self + } + pub fn esdt_nft_last_nonce(mut self, token_id_expr: K, last_nonce_expr: N) -> Self where BytesKey: From, diff --git a/framework/scenario/src/scenario/model/esdt_data/esdt_object.rs b/framework/scenario/src/scenario/model/esdt_data/esdt_object.rs index 13ff58fe53..7305a38b9e 100644 --- a/framework/scenario/src/scenario/model/esdt_data/esdt_object.rs +++ b/framework/scenario/src/scenario/model/esdt_data/esdt_object.rs @@ -52,6 +52,71 @@ impl EsdtObject { } } + pub fn ovidiu( + &mut self, + nonce_expr: N, + balance_expr: V, + opt_attributes_expr: Option, + royalties_expr: N, + creator_expr: Option, + hash_expr: Option, + uris_expr: Vec, + ) where + U64Value: From, + BigUintValue: From, + BytesValue: From, + { + let inst_for_nonce = self.get_or_insert_instance_for_nonce(nonce_expr); + + let balance = BigUintValue::from(balance_expr); + if balance.value > 0u64.into() { + inst_for_nonce.balance = Some(balance); + } else { + inst_for_nonce.balance = None; + } + + if let Some(attributes) = opt_attributes_expr { + let attributes = BytesValue::from(attributes); + if !attributes.value.is_empty() { + inst_for_nonce.attributes = Some(attributes); + } else { + inst_for_nonce.attributes = None; + } + } + + let royalties = U64Value::from(royalties_expr); + if royalties.value > 0 { + inst_for_nonce.royalties = Some(royalties); + } else { + inst_for_nonce.royalties = None; + } + + if let Some(creator_expr) = creator_expr { + let creator = BytesValue::from(creator_expr); + if !creator.value.is_empty() { + inst_for_nonce.creator = Some(creator); + } else { + inst_for_nonce.creator = None; + } + } + + if let Some(hash) = hash_expr { + let hash = BytesValue::from(hash); + if !hash.value.is_empty() { + inst_for_nonce.hash = Some(hash); + } else { + inst_for_nonce.hash = None; + } + } + + if !uris_expr.is_empty() { + inst_for_nonce.uri = uris_expr + .into_iter() + .map(|uri| BytesValue::from(uri)) + .collect(); + } + } + pub fn set_last_nonce(&mut self, last_nonce_expr: N) where U64Value: From, From 6d985f382c31c26a4153c188fe9316b86bf1f331 Mon Sep 17 00:00:00 2001 From: Ovidiu Stinga Date: Mon, 18 Sep 2023 23:13:22 +0300 Subject: [PATCH 17/21] remove old whitebox legacy --- .../tests/token_merge_module_legacy_test.rs | 726 ------------------ 1 file changed, 726 deletions(-) delete mode 100644 contracts/feature-tests/use-module/tests/token_merge_module_legacy_test.rs diff --git a/contracts/feature-tests/use-module/tests/token_merge_module_legacy_test.rs b/contracts/feature-tests/use-module/tests/token_merge_module_legacy_test.rs deleted file mode 100644 index a2520439ed..0000000000 --- a/contracts/feature-tests/use-module/tests/token_merge_module_legacy_test.rs +++ /dev/null @@ -1,726 +0,0 @@ -#![allow(deprecated)] // TODO: migrate tests - -use multiversx_sc::{ - arrayvec::ArrayVec, - codec::Empty, - contract_base::ContractBase, - storage::mappers::StorageTokenWrapper, - types::{EsdtLocalRole, EsdtTokenPayment, ManagedVec}, -}; -use multiversx_sc_modules::token_merge::{ - merged_token_instances::MergedTokenInstances, merged_token_setup::MergedTokenSetupModule, -}; -use multiversx_sc_scenario::{ - managed_address, managed_biguint, managed_token_id, rust_biguint, - testing_framework::{BlockchainStateWrapper, TxTokenTransfer}, -}; -use use_module::token_merge_mod_impl::{CustomAttributes, TokenMergeModImpl}; - -static MERGED_TOKEN_ID: &[u8] = b"MERGED-123456"; -static NFT_TOKEN_ID: &[u8] = b"NFT-123456"; -static FUNGIBLE_TOKEN_ID: &[u8] = b"FUN-123456"; - -const NFT_AMOUNT: u64 = 1; -const FUNGIBLE_AMOUNT: u64 = 100; - -const FIRST_NFT_NONCE: u64 = 5; -static FIRST_ATTRIBUTES: &[u8] = b"FirstAttributes"; -const FIRST_ROYALTIES: u64 = 1_000; -static FIRST_URIS: &[&[u8]] = &[b"FirstUri", b"SecondUri"]; - -const SECOND_NFT_NONCE: u64 = 7; -static SECOND_ATTRIBUTES: &[u8] = b"SecondAttributes"; -const SECOND_ROYALTIES: u64 = 5_000; -static SECOND_URIS: &[&[u8]] = &[b"cool.com/safe_file.exe"]; - -#[test] -fn test_token_merge() { - let rust_zero = rust_biguint!(0); - let mut b_mock = BlockchainStateWrapper::new(); - let owner = b_mock.create_user_account(&rust_zero); - let user = b_mock.create_user_account(&rust_zero); - let merging_sc = b_mock.create_sc_account( - &rust_zero, - Some(&owner), - use_module::contract_obj, - "wasm path", - ); - - b_mock - .execute_tx(&owner, &merging_sc, &rust_zero, |sc| { - sc.merged_token() - .set_token_id(managed_token_id!(MERGED_TOKEN_ID)); - let _ = sc - .mergeable_tokens_whitelist() - .insert(managed_token_id!(NFT_TOKEN_ID)); - let _ = sc - .mergeable_tokens_whitelist() - .insert(managed_token_id!(FUNGIBLE_TOKEN_ID)); - }) - .assert_ok(); - b_mock.set_esdt_local_roles( - merging_sc.address_ref(), - MERGED_TOKEN_ID, - &[EsdtLocalRole::NftCreate, EsdtLocalRole::NftBurn], - ); - - b_mock.set_esdt_balance(&user, FUNGIBLE_TOKEN_ID, &rust_biguint!(FUNGIBLE_AMOUNT)); - b_mock.set_nft_balance_all_properties( - &user, - NFT_TOKEN_ID, - FIRST_NFT_NONCE, - &rust_biguint!(NFT_AMOUNT), - &FIRST_ATTRIBUTES.to_vec(), - FIRST_ROYALTIES, - None, - None, - None, - &uris_to_vec(FIRST_URIS), - ); - b_mock.set_nft_balance_all_properties( - &user, - NFT_TOKEN_ID, - SECOND_NFT_NONCE, - &rust_biguint!(NFT_AMOUNT), - &SECOND_ATTRIBUTES.to_vec(), - SECOND_ROYALTIES, - None, - None, - None, - &uris_to_vec(SECOND_URIS), - ); - - // merge two NFTs - let nft_transfers = vec![ - TxTokenTransfer { - token_identifier: NFT_TOKEN_ID.to_vec(), - nonce: FIRST_NFT_NONCE, - value: rust_biguint!(NFT_AMOUNT), - }, - TxTokenTransfer { - token_identifier: NFT_TOKEN_ID.to_vec(), - nonce: SECOND_NFT_NONCE, - value: rust_biguint!(NFT_AMOUNT), - }, - ]; - b_mock - .execute_esdt_multi_transfer(&user, &merging_sc, &nft_transfers, |sc| { - let merged_token = sc.merge_tokens_endpoint(); - assert_eq!( - merged_token.token_identifier, - managed_token_id!(MERGED_TOKEN_ID) - ); - assert_eq!(merged_token.token_nonce, 1); - assert_eq!(merged_token.amount, managed_biguint!(NFT_AMOUNT)); - - let merged_token_data = sc.blockchain().get_esdt_token_data( - &managed_address!(&user), - &managed_token_id!(MERGED_TOKEN_ID), - 1, - ); - let mut expected_uri = ArrayVec::new(); - expected_uri.push(EsdtTokenPayment::new( - managed_token_id!(NFT_TOKEN_ID), - FIRST_NFT_NONCE, - managed_biguint!(NFT_AMOUNT), - )); - expected_uri.push(EsdtTokenPayment::new( - managed_token_id!(NFT_TOKEN_ID), - SECOND_NFT_NONCE, - managed_biguint!(NFT_AMOUNT), - )); - - let actual_uri = MergedTokenInstances::decode_from_first_uri(&merged_token_data.uris); - assert_eq!(expected_uri, actual_uri.into_instances()); - - assert_eq!( - merged_token_data.royalties, - managed_biguint!(SECOND_ROYALTIES) - ); - }) - .assert_ok(); - - b_mock.check_nft_balance( - &user, - MERGED_TOKEN_ID, - 1, - &rust_biguint!(NFT_AMOUNT), - Option::<&Empty>::None, - ); - b_mock.check_nft_balance( - merging_sc.address_ref(), - NFT_TOKEN_ID, - FIRST_NFT_NONCE, - &rust_biguint!(NFT_AMOUNT), - Option::<&Empty>::None, - ); - b_mock.check_nft_balance( - merging_sc.address_ref(), - NFT_TOKEN_ID, - SECOND_NFT_NONCE, - &rust_biguint!(NFT_AMOUNT), - Option::<&Empty>::None, - ); - - // split nfts - b_mock - .execute_esdt_transfer( - &user, - &merging_sc, - MERGED_TOKEN_ID, - 1, - &rust_biguint!(NFT_AMOUNT), - |sc| { - let output_tokens = sc.split_tokens_endpoint(); - let mut expected_output_tokens = ManagedVec::new(); - expected_output_tokens.push(EsdtTokenPayment::new( - managed_token_id!(NFT_TOKEN_ID), - FIRST_NFT_NONCE, - managed_biguint!(NFT_AMOUNT), - )); - expected_output_tokens.push(EsdtTokenPayment::new( - managed_token_id!(NFT_TOKEN_ID), - SECOND_NFT_NONCE, - managed_biguint!(NFT_AMOUNT), - )); - assert_eq!(output_tokens, expected_output_tokens); - }, - ) - .assert_ok(); - - b_mock.check_nft_balance( - &user, - NFT_TOKEN_ID, - FIRST_NFT_NONCE, - &rust_biguint!(NFT_AMOUNT), - Option::<&Empty>::None, - ); - b_mock.check_nft_balance( - &user, - NFT_TOKEN_ID, - SECOND_NFT_NONCE, - &rust_biguint!(NFT_AMOUNT), - Option::<&Empty>::None, - ); - - // merge the NFT with fungible - let esdt_transfers = vec![ - TxTokenTransfer { - token_identifier: NFT_TOKEN_ID.to_vec(), - nonce: FIRST_NFT_NONCE, - value: rust_biguint!(NFT_AMOUNT), - }, - TxTokenTransfer { - token_identifier: FUNGIBLE_TOKEN_ID.to_vec(), - nonce: 0, - value: rust_biguint!(FUNGIBLE_AMOUNT), - }, - ]; - b_mock - .execute_esdt_multi_transfer(&user, &merging_sc, &esdt_transfers, |sc| { - let merged_token = sc.merge_tokens_endpoint(); - assert_eq!( - merged_token.token_identifier, - managed_token_id!(MERGED_TOKEN_ID) - ); - assert_eq!(merged_token.token_nonce, 2); - assert_eq!(merged_token.amount, managed_biguint!(NFT_AMOUNT)); - - let merged_token_data = sc.blockchain().get_esdt_token_data( - &managed_address!(&user), - &managed_token_id!(MERGED_TOKEN_ID), - 2, - ); - let mut expected_uri = ArrayVec::new(); - expected_uri.push(EsdtTokenPayment::new( - managed_token_id!(NFT_TOKEN_ID), - FIRST_NFT_NONCE, - managed_biguint!(NFT_AMOUNT), - )); - expected_uri.push(EsdtTokenPayment::new( - managed_token_id!(FUNGIBLE_TOKEN_ID), - 0, - managed_biguint!(FUNGIBLE_AMOUNT), - )); - - let actual_uri = MergedTokenInstances::decode_from_first_uri(&merged_token_data.uris); - assert_eq!(expected_uri, actual_uri.into_instances()); - - assert_eq!( - merged_token_data.royalties, - managed_biguint!(FIRST_ROYALTIES) - ); - }) - .assert_ok(); - - b_mock.check_nft_balance( - &user, - MERGED_TOKEN_ID, - 2, - &rust_biguint!(NFT_AMOUNT), - Option::<&Empty>::None, - ); - - // merge NFT with an already merged token - let combined_transfers = vec![ - TxTokenTransfer { - token_identifier: NFT_TOKEN_ID.to_vec(), - nonce: SECOND_NFT_NONCE, - value: rust_biguint!(NFT_AMOUNT), - }, - TxTokenTransfer { - token_identifier: MERGED_TOKEN_ID.to_vec(), - nonce: 2, - value: rust_biguint!(NFT_AMOUNT), - }, - ]; - b_mock - .execute_esdt_multi_transfer(&user, &merging_sc, &combined_transfers, |sc| { - let merged_token = sc.merge_tokens_endpoint(); - assert_eq!( - merged_token.token_identifier, - managed_token_id!(MERGED_TOKEN_ID) - ); - assert_eq!(merged_token.token_nonce, 3); - assert_eq!(merged_token.amount, managed_biguint!(NFT_AMOUNT)); - - let merged_token_data = sc.blockchain().get_esdt_token_data( - &managed_address!(&user), - &managed_token_id!(MERGED_TOKEN_ID), - 3, - ); - let mut expected_uri = ArrayVec::new(); - expected_uri.push(EsdtTokenPayment::new( - managed_token_id!(NFT_TOKEN_ID), - FIRST_NFT_NONCE, - managed_biguint!(NFT_AMOUNT), - )); - expected_uri.push(EsdtTokenPayment::new( - managed_token_id!(FUNGIBLE_TOKEN_ID), - 0, - managed_biguint!(FUNGIBLE_AMOUNT), - )); - expected_uri.push(EsdtTokenPayment::new( - managed_token_id!(NFT_TOKEN_ID), - SECOND_NFT_NONCE, - managed_biguint!(NFT_AMOUNT), - )); - - let actual_uri = MergedTokenInstances::decode_from_first_uri(&merged_token_data.uris); - assert_eq!(expected_uri, actual_uri.into_instances()); - - assert_eq!( - merged_token_data.royalties, - managed_biguint!(SECOND_ROYALTIES) - ); - }) - .assert_ok(); - - b_mock.check_nft_balance( - &user, - MERGED_TOKEN_ID, - 3, - &rust_biguint!(NFT_AMOUNT), - Option::<&Empty>::None, - ); - - // split the 3 merged tokens - b_mock - .execute_esdt_transfer( - &user, - &merging_sc, - MERGED_TOKEN_ID, - 3, - &rust_biguint!(NFT_AMOUNT), - |sc| { - let output_tokens = sc.split_tokens_endpoint(); - let mut expected_output_tokens = ManagedVec::new(); - expected_output_tokens.push(EsdtTokenPayment::new( - managed_token_id!(NFT_TOKEN_ID), - FIRST_NFT_NONCE, - managed_biguint!(NFT_AMOUNT), - )); - expected_output_tokens.push(EsdtTokenPayment::new( - managed_token_id!(FUNGIBLE_TOKEN_ID), - 0, - managed_biguint!(FUNGIBLE_AMOUNT), - )); - expected_output_tokens.push(EsdtTokenPayment::new( - managed_token_id!(NFT_TOKEN_ID), - SECOND_NFT_NONCE, - managed_biguint!(NFT_AMOUNT), - )); - - assert_eq!(output_tokens, expected_output_tokens); - }, - ) - .assert_ok(); - - b_mock.check_nft_balance( - &user, - NFT_TOKEN_ID, - FIRST_NFT_NONCE, - &rust_biguint!(NFT_AMOUNT), - Option::<&Empty>::None, - ); - b_mock.check_nft_balance( - &user, - NFT_TOKEN_ID, - SECOND_NFT_NONCE, - &rust_biguint!(NFT_AMOUNT), - Option::<&Empty>::None, - ); - b_mock.check_esdt_balance(&user, FUNGIBLE_TOKEN_ID, &rust_biguint!(FUNGIBLE_AMOUNT)); -} - -#[test] -fn partial_split_test() { - let rust_zero = rust_biguint!(0); - let mut b_mock = BlockchainStateWrapper::new(); - let owner = b_mock.create_user_account(&rust_zero); - let user = b_mock.create_user_account(&rust_zero); - let merging_sc = b_mock.create_sc_account( - &rust_zero, - Some(&owner), - use_module::contract_obj, - "wasm path", - ); - - b_mock - .execute_tx(&owner, &merging_sc, &rust_zero, |sc| { - sc.merged_token() - .set_token_id(managed_token_id!(MERGED_TOKEN_ID)); - let _ = sc - .mergeable_tokens_whitelist() - .insert(managed_token_id!(NFT_TOKEN_ID)); - let _ = sc - .mergeable_tokens_whitelist() - .insert(managed_token_id!(FUNGIBLE_TOKEN_ID)); - }) - .assert_ok(); - b_mock.set_esdt_local_roles( - merging_sc.address_ref(), - MERGED_TOKEN_ID, - &[EsdtLocalRole::NftCreate, EsdtLocalRole::NftBurn], - ); - - b_mock.set_esdt_balance(&user, FUNGIBLE_TOKEN_ID, &rust_biguint!(FUNGIBLE_AMOUNT)); - b_mock.set_nft_balance_all_properties( - &user, - NFT_TOKEN_ID, - FIRST_NFT_NONCE, - &rust_biguint!(NFT_AMOUNT), - &FIRST_ATTRIBUTES.to_vec(), - FIRST_ROYALTIES, - None, - None, - None, - &uris_to_vec(FIRST_URIS), - ); - b_mock.set_nft_balance_all_properties( - &user, - NFT_TOKEN_ID, - SECOND_NFT_NONCE, - &rust_biguint!(NFT_AMOUNT), - &SECOND_ATTRIBUTES.to_vec(), - SECOND_ROYALTIES, - None, - None, - None, - &uris_to_vec(SECOND_URIS), - ); - - // merge 2 NFTs and a fungible token - let esdt_transfers = vec![ - TxTokenTransfer { - token_identifier: NFT_TOKEN_ID.to_vec(), - nonce: FIRST_NFT_NONCE, - value: rust_biguint!(NFT_AMOUNT), - }, - TxTokenTransfer { - token_identifier: NFT_TOKEN_ID.to_vec(), - nonce: SECOND_NFT_NONCE, - value: rust_biguint!(NFT_AMOUNT), - }, - TxTokenTransfer { - token_identifier: FUNGIBLE_TOKEN_ID.to_vec(), - nonce: 0, - value: rust_biguint!(FUNGIBLE_AMOUNT), - }, - ]; - b_mock - .execute_esdt_multi_transfer(&user, &merging_sc, &esdt_transfers, |sc| { - let merged_token = sc.merge_tokens_endpoint(); - assert_eq!( - merged_token.token_identifier, - managed_token_id!(MERGED_TOKEN_ID) - ); - assert_eq!(merged_token.token_nonce, 1); - assert_eq!(merged_token.amount, managed_biguint!(NFT_AMOUNT)); - - let merged_token_data = sc.blockchain().get_esdt_token_data( - &managed_address!(&user), - &managed_token_id!(MERGED_TOKEN_ID), - 1, - ); - let mut expected_uri = ArrayVec::new(); - expected_uri.push(EsdtTokenPayment::new( - managed_token_id!(NFT_TOKEN_ID), - FIRST_NFT_NONCE, - managed_biguint!(NFT_AMOUNT), - )); - expected_uri.push(EsdtTokenPayment::new( - managed_token_id!(NFT_TOKEN_ID), - SECOND_NFT_NONCE, - managed_biguint!(NFT_AMOUNT), - )); - expected_uri.push(EsdtTokenPayment::new( - managed_token_id!(FUNGIBLE_TOKEN_ID), - 0, - managed_biguint!(FUNGIBLE_AMOUNT), - )); - - let actual_uri = MergedTokenInstances::decode_from_first_uri(&merged_token_data.uris); - assert_eq!(expected_uri, actual_uri.into_instances()); - }) - .assert_ok(); - - // split part of the fungible token - b_mock - .execute_esdt_transfer( - &user, - &merging_sc, - MERGED_TOKEN_ID, - 1, - &rust_biguint!(NFT_AMOUNT), - |sc| { - let mut tokens_to_remove = ManagedVec::new(); - tokens_to_remove.push(EsdtTokenPayment::new( - managed_token_id!(FUNGIBLE_TOKEN_ID), - 0, - managed_biguint!(40), - )); - let output_payments = sc.split_token_partial_endpoint(tokens_to_remove); - - let mut expected_output_payments = ManagedVec::new(); - expected_output_payments.push(EsdtTokenPayment::new( - managed_token_id!(FUNGIBLE_TOKEN_ID), - 0, - managed_biguint!(40), - )); - expected_output_payments.push(EsdtTokenPayment::new( - managed_token_id!(MERGED_TOKEN_ID), - 2, - managed_biguint!(NFT_AMOUNT), - )); - assert_eq!(output_payments, expected_output_payments); - }, - ) - .assert_ok(); - - // fully remove instance - b_mock - .execute_esdt_transfer( - &user, - &merging_sc, - MERGED_TOKEN_ID, - 2, - &rust_biguint!(NFT_AMOUNT), - |sc| { - let mut tokens_to_remove = ManagedVec::new(); - tokens_to_remove.push(EsdtTokenPayment::new( - managed_token_id!(NFT_TOKEN_ID), - FIRST_NFT_NONCE, - managed_biguint!(NFT_AMOUNT), - )); - let output_payments = sc.split_token_partial_endpoint(tokens_to_remove); - - let mut expected_output_payments = ManagedVec::new(); - expected_output_payments.push(EsdtTokenPayment::new( - managed_token_id!(NFT_TOKEN_ID), - FIRST_NFT_NONCE, - managed_biguint!(NFT_AMOUNT), - )); - expected_output_payments.push(EsdtTokenPayment::new( - managed_token_id!(MERGED_TOKEN_ID), - 3, - managed_biguint!(NFT_AMOUNT), - )); - assert_eq!(output_payments, expected_output_payments); - - // check newest token attributes - let merged_token_data = sc.blockchain().get_esdt_token_data( - &managed_address!(&user), - &managed_token_id!(MERGED_TOKEN_ID), - 3, - ); - let mut expected_uri = ArrayVec::new(); - expected_uri.push(EsdtTokenPayment::new( - managed_token_id!(NFT_TOKEN_ID), - SECOND_NFT_NONCE, - managed_biguint!(NFT_AMOUNT), - )); - expected_uri.push(EsdtTokenPayment::new( - managed_token_id!(FUNGIBLE_TOKEN_ID), - 0, - managed_biguint!(FUNGIBLE_AMOUNT - 40), - )); - - let actual_uri = - MergedTokenInstances::decode_from_first_uri(&merged_token_data.uris); - assert_eq!(expected_uri, actual_uri.into_instances()); - - assert_eq!( - merged_token_data.royalties, - managed_biguint!(SECOND_ROYALTIES) - ); - }, - ) - .assert_ok(); -} - -#[test] -fn custom_attributes_test() { - let rust_zero = rust_biguint!(0); - let mut b_mock = BlockchainStateWrapper::new(); - let owner = b_mock.create_user_account(&rust_zero); - let user = b_mock.create_user_account(&rust_zero); - let merging_sc = b_mock.create_sc_account( - &rust_zero, - Some(&owner), - use_module::contract_obj, - "wasm path", - ); - - b_mock - .execute_tx(&owner, &merging_sc, &rust_zero, |sc| { - sc.merged_token() - .set_token_id(managed_token_id!(MERGED_TOKEN_ID)); - let _ = sc - .mergeable_tokens_whitelist() - .insert(managed_token_id!(NFT_TOKEN_ID)); - let _ = sc - .mergeable_tokens_whitelist() - .insert(managed_token_id!(FUNGIBLE_TOKEN_ID)); - }) - .assert_ok(); - b_mock.set_esdt_local_roles( - merging_sc.address_ref(), - MERGED_TOKEN_ID, - &[EsdtLocalRole::NftCreate, EsdtLocalRole::NftBurn], - ); - - b_mock.set_esdt_balance(&user, FUNGIBLE_TOKEN_ID, &rust_biguint!(FUNGIBLE_AMOUNT)); - b_mock.set_nft_balance_all_properties( - &user, - NFT_TOKEN_ID, - FIRST_NFT_NONCE, - &rust_biguint!(NFT_AMOUNT), - &FIRST_ATTRIBUTES.to_vec(), - FIRST_ROYALTIES, - None, - None, - None, - &uris_to_vec(FIRST_URIS), - ); - b_mock.set_nft_balance_all_properties( - &user, - NFT_TOKEN_ID, - SECOND_NFT_NONCE, - &rust_biguint!(NFT_AMOUNT), - &SECOND_ATTRIBUTES.to_vec(), - SECOND_ROYALTIES, - None, - None, - None, - &uris_to_vec(SECOND_URIS), - ); - - // merge two NFTs - let nft_transfers = vec![ - TxTokenTransfer { - token_identifier: NFT_TOKEN_ID.to_vec(), - nonce: FIRST_NFT_NONCE, - value: rust_biguint!(NFT_AMOUNT), - }, - TxTokenTransfer { - token_identifier: NFT_TOKEN_ID.to_vec(), - nonce: SECOND_NFT_NONCE, - value: rust_biguint!(NFT_AMOUNT), - }, - ]; - b_mock - .execute_esdt_multi_transfer(&user, &merging_sc, &nft_transfers, |sc| { - let merged_token = sc.merge_tokens_custom_attributes_endpoint(); - assert_eq!( - merged_token.token_identifier, - managed_token_id!(MERGED_TOKEN_ID) - ); - assert_eq!(merged_token.token_nonce, 1); - assert_eq!(merged_token.amount, managed_biguint!(NFT_AMOUNT)); - - let merged_token_data = sc.blockchain().get_esdt_token_data( - &managed_address!(&user), - &managed_token_id!(MERGED_TOKEN_ID), - 1, - ); - let mut expected_uri = ArrayVec::new(); - expected_uri.push(EsdtTokenPayment::new( - managed_token_id!(NFT_TOKEN_ID), - FIRST_NFT_NONCE, - managed_biguint!(NFT_AMOUNT), - )); - expected_uri.push(EsdtTokenPayment::new( - managed_token_id!(NFT_TOKEN_ID), - SECOND_NFT_NONCE, - managed_biguint!(NFT_AMOUNT), - )); - - let actual_uri = MergedTokenInstances::decode_from_first_uri(&merged_token_data.uris); - assert_eq!(expected_uri, actual_uri.into_instances()); - - let expected_attributes = CustomAttributes { - first: 5u32, - second: 10u64, - }; - let actual_attributes: CustomAttributes = merged_token_data.decode_attributes(); - assert_eq!(expected_attributes, actual_attributes); - - assert_eq!( - merged_token_data.royalties, - managed_biguint!(SECOND_ROYALTIES) - ); - }) - .assert_ok(); - - b_mock.check_nft_balance( - &user, - MERGED_TOKEN_ID, - 1, - &rust_biguint!(NFT_AMOUNT), - Option::<&Empty>::None, - ); - b_mock.check_nft_balance( - merging_sc.address_ref(), - NFT_TOKEN_ID, - FIRST_NFT_NONCE, - &rust_biguint!(NFT_AMOUNT), - Option::<&Empty>::None, - ); - b_mock.check_nft_balance( - merging_sc.address_ref(), - NFT_TOKEN_ID, - SECOND_NFT_NONCE, - &rust_biguint!(NFT_AMOUNT), - Option::<&Empty>::None, - ); -} - -fn uris_to_vec(uris: &[&[u8]]) -> Vec> { - let mut out = Vec::new(); - for uri in uris { - out.push((*uri).to_vec()); - } - - out -} From bd0e84edd5c7def6c150701c86e0add2492e3b45 Mon Sep 17 00:00:00 2001 From: Ovidiu Stinga Date: Thu, 21 Sep 2023 10:36:54 +0300 Subject: [PATCH 18/21] fix clippy issues --- framework/scenario/src/scenario/model/account_data/account.rs | 3 ++- framework/scenario/src/scenario/model/esdt_data/esdt_object.rs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/framework/scenario/src/scenario/model/account_data/account.rs b/framework/scenario/src/scenario/model/account_data/account.rs index 0c456b84bb..912d8d94f5 100644 --- a/framework/scenario/src/scenario/model/account_data/account.rs +++ b/framework/scenario/src/scenario/model/account_data/account.rs @@ -84,6 +84,7 @@ impl Account { self } + #[allow(clippy::too_many_arguments)] pub fn esdt_nft_all_properties( mut self, token_id_expr: K, @@ -107,7 +108,7 @@ impl Account { .get_esdt_data_or_create(&token_id) .get_mut_esdt_object(); - esdt_obj_ref.ovidiu( + esdt_obj_ref.set_token_all_properties( nonce_expr, balance_expr, opt_attributes_expr, diff --git a/framework/scenario/src/scenario/model/esdt_data/esdt_object.rs b/framework/scenario/src/scenario/model/esdt_data/esdt_object.rs index 7305a38b9e..f8298e2b8c 100644 --- a/framework/scenario/src/scenario/model/esdt_data/esdt_object.rs +++ b/framework/scenario/src/scenario/model/esdt_data/esdt_object.rs @@ -52,7 +52,8 @@ impl EsdtObject { } } - pub fn ovidiu( + #[allow(clippy::too_many_arguments)] + pub fn set_token_all_properties( &mut self, nonce_expr: N, balance_expr: V, From 63d6f9d1e1bffaf8547377da9f1564b46c64593d Mon Sep 17 00:00:00 2001 From: Ovidiu Stinga Date: Thu, 21 Sep 2023 17:52:51 +0300 Subject: [PATCH 19/21] refactor tests --- .../tests/token_merge_module_whitebox_test.rs | 122 ++++++++---------- 1 file changed, 55 insertions(+), 67 deletions(-) diff --git a/contracts/feature-tests/use-module/tests/token_merge_module_whitebox_test.rs b/contracts/feature-tests/use-module/tests/token_merge_module_whitebox_test.rs index abb0490ae9..09cb4bda5c 100644 --- a/contracts/feature-tests/use-module/tests/token_merge_module_whitebox_test.rs +++ b/contracts/feature-tests/use-module/tests/token_merge_module_whitebox_test.rs @@ -11,9 +11,8 @@ use multiversx_sc_modules::token_merge::{ use multiversx_sc_scenario::{ managed_address, managed_biguint, managed_token_id, rust_biguint, scenario_model::{ - Account, AddressValue, CheckAccount, CheckStateStep, ScCallStep, SetStateStep, + Account, AddressValue, CheckAccount, CheckStateStep, ScCallStep, SetStateStep, TxESDT, }, - testing_framework::TxTokenTransfer, ScenarioWorld, WhiteboxContract, }; use use_module::token_merge_mod_impl::{CustomAttributes, TokenMergeModImpl}; @@ -120,26 +119,24 @@ fn test_token_merge() { ); // merge two NFTs - let _nft_transfers = vec![ - TxTokenTransfer { - token_identifier: NFT_TOKEN_ID.to_vec(), - nonce: FIRST_NFT_NONCE, - value: rust_biguint!(NFT_AMOUNT), + let nft_transfers = vec![ + TxESDT { + esdt_token_identifier: NFT_TOKEN_ID.into(), + nonce: FIRST_NFT_NONCE.into(), + esdt_value: NFT_AMOUNT.into(), }, - TxTokenTransfer { - token_identifier: NFT_TOKEN_ID.to_vec(), - nonce: SECOND_NFT_NONCE, - value: rust_biguint!(NFT_AMOUNT), + TxESDT { + esdt_token_identifier: NFT_TOKEN_ID.into(), + nonce: SECOND_NFT_NONCE.into(), + esdt_value: NFT_AMOUNT.into(), }, ]; - // TODO: change after multi_esdt_transfer implementation world.whitebox_call( &use_module_whitebox, ScCallStep::new() .from(USER_ADDRESS_EXPR) - .esdt_transfer(NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT) - .esdt_transfer(NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT), + .multi_esdt_transfer(nft_transfers.clone()), |sc| { let merged_token = sc.merge_tokens_endpoint(); assert_eq!( @@ -252,26 +249,24 @@ fn test_token_merge() { )); // merge the NFT with fungible - let _esdt_transfers = vec![ - TxTokenTransfer { - token_identifier: NFT_TOKEN_ID.to_vec(), - nonce: FIRST_NFT_NONCE, - value: rust_biguint!(NFT_AMOUNT), + let esdt_transfers = vec![ + TxESDT { + esdt_token_identifier: NFT_TOKEN_ID.into(), + nonce: FIRST_NFT_NONCE.into(), + esdt_value: NFT_AMOUNT.into(), }, - TxTokenTransfer { - token_identifier: FUNGIBLE_TOKEN_ID.to_vec(), - nonce: 0, - value: rust_biguint!(FUNGIBLE_AMOUNT), + TxESDT { + esdt_token_identifier: FUNGIBLE_TOKEN_ID.into(), + nonce: 0u64.into(), + esdt_value: FUNGIBLE_AMOUNT.into(), }, ]; - // TODO: change after multi_esdt_transfer implementation world.whitebox_call( &use_module_whitebox, ScCallStep::new() .from(USER_ADDRESS_EXPR) - .esdt_transfer(NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT) - .esdt_transfer(FUNGIBLE_TOKEN_ID_EXPR, 0, FUNGIBLE_AMOUNT), + .multi_esdt_transfer(esdt_transfers.clone()), |sc| { let merged_token = sc.merge_tokens_endpoint(); assert_eq!( @@ -319,26 +314,24 @@ fn test_token_merge() { )); // merge NFT with an already merged token - let _combined_transfers = vec![ - TxTokenTransfer { - token_identifier: NFT_TOKEN_ID.to_vec(), - nonce: SECOND_NFT_NONCE, - value: rust_biguint!(NFT_AMOUNT), + let combined_transfers = vec![ + TxESDT { + esdt_token_identifier: NFT_TOKEN_ID.into(), + nonce: SECOND_NFT_NONCE.into(), + esdt_value: NFT_AMOUNT.into(), }, - TxTokenTransfer { - token_identifier: MERGED_TOKEN_ID.to_vec(), - nonce: 2, - value: rust_biguint!(NFT_AMOUNT), + TxESDT { + esdt_token_identifier: MERGED_TOKEN_ID.into(), + nonce: 2u64.into(), + esdt_value: NFT_AMOUNT.into(), }, ]; - // TODO: change after multi_esdt_transfer implementation world.whitebox_call( &use_module_whitebox, ScCallStep::new() .from(USER_ADDRESS_EXPR) - .esdt_transfer(NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT) - .esdt_transfer(MERGED_TOKEN_ID_EXPR, 2, NFT_AMOUNT), + .multi_esdt_transfer(combined_transfers.clone()), |sc| { let merged_token = sc.merge_tokens_endpoint(); assert_eq!( @@ -514,32 +507,29 @@ fn test_partial_split() { ); // merge 2 NFTs and a fungible token - let _esdt_transfers = vec![ - TxTokenTransfer { - token_identifier: NFT_TOKEN_ID.to_vec(), - nonce: FIRST_NFT_NONCE, - value: rust_biguint!(NFT_AMOUNT), + let esdt_transfers = vec![ + TxESDT { + esdt_token_identifier: NFT_TOKEN_ID.into(), + nonce: FIRST_NFT_NONCE.into(), + esdt_value: NFT_AMOUNT.into(), }, - TxTokenTransfer { - token_identifier: NFT_TOKEN_ID.to_vec(), - nonce: SECOND_NFT_NONCE, - value: rust_biguint!(NFT_AMOUNT), + TxESDT { + esdt_token_identifier: NFT_TOKEN_ID.into(), + nonce: SECOND_NFT_NONCE.into(), + esdt_value: NFT_AMOUNT.into(), }, - TxTokenTransfer { - token_identifier: FUNGIBLE_TOKEN_ID.to_vec(), - nonce: 0, - value: rust_biguint!(FUNGIBLE_AMOUNT), + TxESDT { + esdt_token_identifier: FUNGIBLE_TOKEN_ID.into(), + nonce: 064.into(), + esdt_value: FUNGIBLE_AMOUNT.into(), }, ]; - // TODO: change after multi_esdt_transfer implementation world.whitebox_call( &use_module_whitebox, ScCallStep::new() .from(USER_ADDRESS_EXPR) - .esdt_transfer(NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT) - .esdt_transfer(NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT) - .esdt_transfer(FUNGIBLE_TOKEN_ID_EXPR, 0, FUNGIBLE_AMOUNT), + .multi_esdt_transfer(esdt_transfers.clone()), |sc| { let merged_token = sc.merge_tokens_endpoint(); assert_eq!( @@ -735,16 +725,16 @@ fn test_custom_attributes() { ); // merge two NFTs - let _nft_transfers = vec![ - TxTokenTransfer { - token_identifier: NFT_TOKEN_ID.to_vec(), - nonce: FIRST_NFT_NONCE, - value: rust_biguint!(NFT_AMOUNT), + let nft_transfers = vec![ + TxESDT { + esdt_token_identifier: NFT_TOKEN_ID.into(), + nonce: FIRST_NFT_NONCE.into(), + esdt_value: NFT_AMOUNT.into(), }, - TxTokenTransfer { - token_identifier: NFT_TOKEN_ID.to_vec(), - nonce: SECOND_NFT_NONCE, - value: rust_biguint!(NFT_AMOUNT), + TxESDT { + esdt_token_identifier: NFT_TOKEN_ID.into(), + nonce: SECOND_NFT_NONCE.into(), + esdt_value: NFT_AMOUNT.into(), }, ]; @@ -753,13 +743,11 @@ fn test_custom_attributes() { second: 10u64, }; - // TODO: change after multi_esdt_transfer implementation world.whitebox_call( &use_module_whitebox, ScCallStep::new() .from(USER_ADDRESS_EXPR) - .esdt_transfer(NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT) - .esdt_transfer(NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT), + .multi_esdt_transfer(nft_transfers.clone()), |sc| { let merged_token = sc.merge_tokens_custom_attributes_endpoint(); assert_eq!( From 01b0499794de9951d6a4796b3f602df9a9b718d5 Mon Sep 17 00:00:00 2001 From: Ovidiu Stinga Date: Thu, 21 Sep 2023 18:01:25 +0300 Subject: [PATCH 20/21] clippy fixes --- .../use-module/tests/token_merge_module_whitebox_test.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/feature-tests/use-module/tests/token_merge_module_whitebox_test.rs b/contracts/feature-tests/use-module/tests/token_merge_module_whitebox_test.rs index 09cb4bda5c..ae54b9209f 100644 --- a/contracts/feature-tests/use-module/tests/token_merge_module_whitebox_test.rs +++ b/contracts/feature-tests/use-module/tests/token_merge_module_whitebox_test.rs @@ -520,7 +520,7 @@ fn test_partial_split() { }, TxESDT { esdt_token_identifier: FUNGIBLE_TOKEN_ID.into(), - nonce: 064.into(), + nonce: 0u64.into(), esdt_value: FUNGIBLE_AMOUNT.into(), }, ]; From 04decffd15b4c215412b7879dc12182e3cd1b845 Mon Sep 17 00:00:00 2001 From: Ovidiu Stinga Date: Fri, 22 Sep 2023 12:28:01 +0300 Subject: [PATCH 21/21] remove rust_biguint macro from tests --- .../tests/forwarder_whitebox_test.rs | 4 +- .../tests/transfer_role_whitebox_test.rs | 22 +++---- .../tests/gov_module_whitebox_test.rs | 58 +++++++++---------- .../tests/staking_module_whitebox_test.rs | 24 ++++---- .../tests/token_merge_module_whitebox_test.rs | 8 +-- 5 files changed, 58 insertions(+), 58 deletions(-) diff --git a/contracts/feature-tests/composability/forwarder/tests/forwarder_whitebox_test.rs b/contracts/feature-tests/composability/forwarder/tests/forwarder_whitebox_test.rs index efd969a716..56f383eb75 100644 --- a/contracts/feature-tests/composability/forwarder/tests/forwarder_whitebox_test.rs +++ b/contracts/feature-tests/composability/forwarder/tests/forwarder_whitebox_test.rs @@ -1,7 +1,7 @@ use forwarder::nft::{Color, ForwarderNftModule}; use multiversx_sc::{contract_base::ContractBase, types::Address}; use multiversx_sc_scenario::{ - managed_address, managed_biguint, managed_token_id, rust_biguint, + managed_address, managed_biguint, managed_token_id, scenario_model::{ Account, AddressValue, CheckAccount, CheckStateStep, ScCallStep, SetStateStep, }, @@ -88,7 +88,7 @@ fn test_nft_update_attributes_and_send() { &forwarder_whitebox, ScCallStep::new() .from(USER_ADDRESS_EXPR) - .esdt_transfer(NFT_TOKEN_ID, 1, rust_biguint!(1)), + .esdt_transfer(NFT_TOKEN_ID, 1, "1"), |sc| { sc.nft_update_attributes(managed_token_id!(NFT_TOKEN_ID), 1, new_attributes); diff --git a/contracts/feature-tests/composability/transfer-role-features/tests/transfer_role_whitebox_test.rs b/contracts/feature-tests/composability/transfer-role-features/tests/transfer_role_whitebox_test.rs index 7294fa76b4..c5af4e7712 100644 --- a/contracts/feature-tests/composability/transfer-role-features/tests/transfer_role_whitebox_test.rs +++ b/contracts/feature-tests/composability/transfer-role-features/tests/transfer_role_whitebox_test.rs @@ -3,7 +3,7 @@ use multiversx_sc::types::{ }; use multiversx_sc_modules::transfer_role_proxy::TransferRoleProxyModule; use multiversx_sc_scenario::{ - managed_address, managed_biguint, managed_buffer, managed_token_id, rust_biguint, + managed_address, managed_biguint, managed_buffer, managed_token_id, scenario_model::{ Account, AddressValue, CheckAccount, CheckStateStep, ScCallStep, ScDeployStep, SetStateStep, }, @@ -95,7 +95,7 @@ fn test_transfer_role() { ScCallStep::new().from(USER_ADDRESS_EXPR).esdt_transfer( TRANSFER_TOKEN_ID, 0, - rust_biguint!(100), + "100", ), |sc| { let payments = ManagedVec::from_single_item(EsdtTokenPayment::new( @@ -114,11 +114,11 @@ fn test_transfer_role() { world.check_state_step(CheckStateStep::new().put_account( USER_ADDRESS_EXPR, - CheckAccount::new().esdt_balance(TRANSFER_TOKEN_ID_EXPR, &rust_biguint!(900)), + CheckAccount::new().esdt_balance(TRANSFER_TOKEN_ID_EXPR, "900"), )); world.check_state_step(CheckStateStep::new().put_account( OWNER_ADDRESS_EXPR, - CheckAccount::new().esdt_balance(TRANSFER_TOKEN_ID_EXPR, &rust_biguint!(100)), + CheckAccount::new().esdt_balance(TRANSFER_TOKEN_ID_EXPR, "100"), )); // transfer to user - err, not whitelisted @@ -126,7 +126,7 @@ fn test_transfer_role() { &transfer_role_features_whitebox, ScCallStep::new() .from(USER_ADDRESS_EXPR) - .esdt_transfer(TRANSFER_TOKEN_ID, 0, rust_biguint!(100)) + .esdt_transfer(TRANSFER_TOKEN_ID, 0, "100") .no_expect(), |sc| { let payments = ManagedVec::from_single_item(EsdtTokenPayment::new( @@ -152,7 +152,7 @@ fn test_transfer_role() { ScCallStep::new().from(USER_ADDRESS_EXPR).esdt_transfer( TRANSFER_TOKEN_ID, 0, - rust_biguint!(100), + "100", ), |sc| { let payments = ManagedVec::from_single_item(EsdtTokenPayment::new( @@ -173,11 +173,11 @@ fn test_transfer_role() { world.check_state_step(CheckStateStep::new().put_account( USER_ADDRESS_EXPR, - CheckAccount::new().esdt_balance(TRANSFER_TOKEN_ID_EXPR, &rust_biguint!(800)), + CheckAccount::new().esdt_balance(TRANSFER_TOKEN_ID_EXPR, "800"), )); world.check_state_step(CheckStateStep::new().put_account( VAULT_ADDRESS_EXPR, - CheckAccount::new().esdt_balance(TRANSFER_TOKEN_ID_EXPR, &rust_biguint!(100)), + CheckAccount::new().esdt_balance(TRANSFER_TOKEN_ID_EXPR, "100"), )); // transfer to sc - reject @@ -186,7 +186,7 @@ fn test_transfer_role() { ScCallStep::new().from(USER_ADDRESS_EXPR).esdt_transfer( TRANSFER_TOKEN_ID, 0, - rust_biguint!(100), + "100", ), |sc| { let payments = ManagedVec::from_single_item(EsdtTokenPayment::new( @@ -207,11 +207,11 @@ fn test_transfer_role() { world.check_state_step(CheckStateStep::new().put_account( USER_ADDRESS_EXPR, - CheckAccount::new().esdt_balance(TRANSFER_TOKEN_ID_EXPR, &rust_biguint!(800)), + CheckAccount::new().esdt_balance(TRANSFER_TOKEN_ID_EXPR, "800"), )); world.check_state_step(CheckStateStep::new().put_account( VAULT_ADDRESS_EXPR, - CheckAccount::new().esdt_balance(TRANSFER_TOKEN_ID_EXPR, &rust_biguint!(100)), + CheckAccount::new().esdt_balance(TRANSFER_TOKEN_ID_EXPR, "100"), )); } diff --git a/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs b/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs index 7b8b5ff71e..3329b748d9 100644 --- a/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs +++ b/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs @@ -4,7 +4,7 @@ use multiversx_sc_modules::governance::{ GovernanceModule, }; use multiversx_sc_scenario::{ - managed_address, managed_biguint, managed_buffer, managed_token_id, rust_biguint, + managed_address, managed_biguint, managed_buffer, managed_token_id, scenario_model::{ Account, AddressValue, CheckAccount, CheckStateStep, ScCallStep, ScDeployStep, SetStateStep, }, @@ -53,26 +53,26 @@ fn setup() -> ScenarioWorld { OWNER_ADDRESS_EXPR, Account::new() .nonce(1) - .esdt_balance(GOV_TOKEN_ID_EXPR, rust_biguint!(INITIAL_GOV_TOKEN_BALANCE)), + .esdt_balance(GOV_TOKEN_ID_EXPR, INITIAL_GOV_TOKEN_BALANCE), ) .new_address(OWNER_ADDRESS_EXPR, 1, USE_MODULE_ADDRESS_EXPR) .put_account( FIRST_USER_ADDRESS_EXPR, Account::new() .nonce(1) - .esdt_balance(GOV_TOKEN_ID_EXPR, rust_biguint!(INITIAL_GOV_TOKEN_BALANCE)), + .esdt_balance(GOV_TOKEN_ID_EXPR, INITIAL_GOV_TOKEN_BALANCE), ) .put_account( SECOND_USER_ADDRESS_EXPR, Account::new() .nonce(1) - .esdt_balance(GOV_TOKEN_ID_EXPR, rust_biguint!(INITIAL_GOV_TOKEN_BALANCE)), + .esdt_balance(GOV_TOKEN_ID_EXPR, INITIAL_GOV_TOKEN_BALANCE), ) .put_account( THIRD_USER_ADDRESS_EXPR, Account::new() .nonce(1) - .esdt_balance(GOV_TOKEN_ID_EXPR, rust_biguint!(INITIAL_GOV_TOKEN_BALANCE)), + .esdt_balance(GOV_TOKEN_ID_EXPR, INITIAL_GOV_TOKEN_BALANCE), ), ); @@ -121,7 +121,7 @@ pub fn propose( ScCallStep::new().from(proposer).esdt_transfer( GOV_TOKEN_ID, 0, - &rust_biguint!(gov_token_amount), + gov_token_amount, ), |sc| { let mut args_managed = ManagedVec::new(); @@ -176,7 +176,7 @@ fn test_change_gov_config() { &use_module_whitebox, ScCallStep::new() .from(SECOND_USER_ADDRESS_EXPR) - .esdt_transfer(GOV_TOKEN_ID, 0, rust_biguint!(999)) + .esdt_transfer(GOV_TOKEN_ID, 0, "999") .no_expect(), |sc| { sc.vote(proposal_id, VoteType::UpVote); @@ -193,7 +193,7 @@ fn test_change_gov_config() { &use_module_whitebox, ScCallStep::new() .from(SECOND_USER_ADDRESS_EXPR) - .esdt_transfer(GOV_TOKEN_ID, 0, rust_biguint!(999)), + .esdt_transfer(GOV_TOKEN_ID, 0, "999"), |sc| { sc.vote(proposal_id, VoteType::UpVote); }, @@ -245,7 +245,7 @@ fn test_change_gov_config() { &use_module_whitebox, ScCallStep::new() .from(FIRST_USER_ADDRESS_EXPR) - .esdt_transfer(GOV_TOKEN_ID, 0, rust_biguint!(200)), + .esdt_transfer(GOV_TOKEN_ID, 0, "200"), |sc| { sc.vote(proposal_id, VoteType::UpVote); }, @@ -257,7 +257,7 @@ fn test_change_gov_config() { ScCallStep::new().from(OWNER_ADDRESS_EXPR).esdt_transfer( GOV_TOKEN_ID, 0, - rust_biguint!(200), + "200", ), |sc| { sc.vote(proposal_id, VoteType::DownVote); @@ -285,7 +285,7 @@ fn test_change_gov_config() { &use_module_whitebox, ScCallStep::new() .from(FIRST_USER_ADDRESS_EXPR) - .esdt_transfer(GOV_TOKEN_ID, 0, rust_biguint!(200)) + .esdt_transfer(GOV_TOKEN_ID, 0, "200") .no_expect(), |sc| { sc.vote(proposal_id, VoteType::UpVote); @@ -300,7 +300,7 @@ fn test_change_gov_config() { &use_module_whitebox, ScCallStep::new() .from(THIRD_USER_ADDRESS_EXPR) - .esdt_transfer(GOV_TOKEN_ID, 0, rust_biguint!(200)), + .esdt_transfer(GOV_TOKEN_ID, 0, "200"), |sc| { sc.vote(proposal_id, VoteType::UpVote); }, @@ -348,19 +348,19 @@ fn test_change_gov_config() { world.check_state_step(CheckStateStep::new().put_account( FIRST_USER_ADDRESS_EXPR, - CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, rust_biguint!(300)), + CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, "300"), )); world.check_state_step(CheckStateStep::new().put_account( SECOND_USER_ADDRESS_EXPR, - CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, rust_biguint!(1)), + CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, "1"), )); world.check_state_step(CheckStateStep::new().put_account( THIRD_USER_ADDRESS_EXPR, - CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, rust_biguint!(800)), + CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, "800"), )); world.check_state_step(CheckStateStep::new().put_account( OWNER_ADDRESS_EXPR, - CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, rust_biguint!(800)), + CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, "800"), )); } @@ -390,7 +390,7 @@ fn test_down_veto_gov_config() { &use_module_whitebox, ScCallStep::new() .from(FIRST_USER_ADDRESS_EXPR) - .esdt_transfer(GOV_TOKEN_ID, 0, rust_biguint!(300)), + .esdt_transfer(GOV_TOKEN_ID, 0, "300"), |sc| { sc.vote(proposal_id, VoteType::UpVote); }, @@ -402,7 +402,7 @@ fn test_down_veto_gov_config() { &use_module_whitebox, ScCallStep::new() .from(SECOND_USER_ADDRESS_EXPR) - .esdt_transfer(GOV_TOKEN_ID, 0, rust_biguint!(200)), + .esdt_transfer(GOV_TOKEN_ID, 0, "200"), |sc| { sc.vote(proposal_id, VoteType::UpVote); }, @@ -412,7 +412,7 @@ fn test_down_veto_gov_config() { &use_module_whitebox, ScCallStep::new() .from(THIRD_USER_ADDRESS_EXPR) - .esdt_transfer(GOV_TOKEN_ID, 0, rust_biguint!(200)), + .esdt_transfer(GOV_TOKEN_ID, 0, "200"), |sc| { sc.vote(proposal_id, VoteType::DownVetoVote); }, @@ -434,15 +434,15 @@ fn test_down_veto_gov_config() { world.check_state_step(CheckStateStep::new().put_account( FIRST_USER_ADDRESS_EXPR, - CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, rust_biguint!(200)), + CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, "200"), )); world.check_state_step(CheckStateStep::new().put_account( SECOND_USER_ADDRESS_EXPR, - CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, rust_biguint!(800)), + CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, "800"), )); world.check_state_step(CheckStateStep::new().put_account( THIRD_USER_ADDRESS_EXPR, - CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, rust_biguint!(800)), + CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, "800"), )); } @@ -472,7 +472,7 @@ fn test_abstain_vote_gov_config() { &use_module_whitebox, ScCallStep::new() .from(FIRST_USER_ADDRESS_EXPR) - .esdt_transfer(GOV_TOKEN_ID, 0, rust_biguint!(500)), + .esdt_transfer(GOV_TOKEN_ID, 0, "500"), |sc| { sc.vote(proposal_id, VoteType::UpVote); }, @@ -484,7 +484,7 @@ fn test_abstain_vote_gov_config() { &use_module_whitebox, ScCallStep::new() .from(SECOND_USER_ADDRESS_EXPR) - .esdt_transfer(GOV_TOKEN_ID, 0, rust_biguint!(400)), + .esdt_transfer(GOV_TOKEN_ID, 0, "400"), |sc| { sc.vote(proposal_id, VoteType::DownVote); }, @@ -494,7 +494,7 @@ fn test_abstain_vote_gov_config() { &use_module_whitebox, ScCallStep::new() .from(THIRD_USER_ADDRESS_EXPR) - .esdt_transfer(GOV_TOKEN_ID, 0, rust_biguint!(600)), + .esdt_transfer(GOV_TOKEN_ID, 0, "600"), |sc| { sc.vote(proposal_id, VoteType::AbstainVote); }, @@ -530,15 +530,15 @@ fn test_abstain_vote_gov_config() { world.check_state_step(CheckStateStep::new().put_account( FIRST_USER_ADDRESS_EXPR, - CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, rust_biguint!(0)), + CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, "0"), )); world.check_state_step(CheckStateStep::new().put_account( SECOND_USER_ADDRESS_EXPR, - CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, rust_biguint!(600)), + CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, "600"), )); world.check_state_step(CheckStateStep::new().put_account( THIRD_USER_ADDRESS_EXPR, - CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, rust_biguint!(400)), + CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, "400"), )); } @@ -568,7 +568,7 @@ fn test_gov_cancel_defeated_proposal() { &use_module_whitebox, ScCallStep::new() .from(SECOND_USER_ADDRESS_EXPR) - .esdt_transfer(GOV_TOKEN_ID, 0, rust_biguint!(999)), + .esdt_transfer(GOV_TOKEN_ID, 0, "999"), |sc| { sc.vote(proposal_id, VoteType::DownVote); }, diff --git a/contracts/feature-tests/use-module/tests/staking_module_whitebox_test.rs b/contracts/feature-tests/use-module/tests/staking_module_whitebox_test.rs index 7fe9e993d5..920701173e 100644 --- a/contracts/feature-tests/use-module/tests/staking_module_whitebox_test.rs +++ b/contracts/feature-tests/use-module/tests/staking_module_whitebox_test.rs @@ -1,7 +1,7 @@ use multiversx_sc::types::{Address, EgldOrEsdtTokenIdentifier, ManagedVec}; use multiversx_sc_modules::staking::StakingModule; use multiversx_sc_scenario::{ - managed_address, managed_biguint, managed_token_id, rust_biguint, + managed_address, managed_biguint, managed_token_id, scenario_model::{ Account, AddressValue, CheckAccount, CheckStateStep, ScCallStep, ScDeployStep, SetStateStep, }, @@ -44,25 +44,25 @@ fn test_staking_module() { ALICE_ADDRESS_EXPR, Account::new() .nonce(1) - .esdt_balance(STAKING_TOKEN_ID_EXPR, rust_biguint!(INITIAL_BALANCE)), + .esdt_balance(STAKING_TOKEN_ID_EXPR, INITIAL_BALANCE), ) .put_account( BOB_ADDRESS_EXPR, Account::new() .nonce(1) - .esdt_balance(STAKING_TOKEN_ID_EXPR, rust_biguint!(INITIAL_BALANCE)), + .esdt_balance(STAKING_TOKEN_ID_EXPR, INITIAL_BALANCE), ) .put_account( CAROL_ADDRESS_EXPR, Account::new() .nonce(1) - .esdt_balance(STAKING_TOKEN_ID_EXPR, rust_biguint!(INITIAL_BALANCE)), + .esdt_balance(STAKING_TOKEN_ID_EXPR, INITIAL_BALANCE), ) .put_account( EVE_ADDRESS_EXPR, Account::new() .nonce(1) - .esdt_balance(STAKING_TOKEN_ID_EXPR, rust_biguint!(INITIAL_BALANCE)), + .esdt_balance(STAKING_TOKEN_ID_EXPR, INITIAL_BALANCE), ), ); @@ -101,7 +101,7 @@ fn test_staking_module() { &use_module_whitebox, ScCallStep::new() .from(EVE_ADDRESS_EXPR) - .esdt_transfer(STAKING_TOKEN_ID, 0, rust_biguint!(REQUIRED_STAKE_AMOUNT)) + .esdt_transfer(STAKING_TOKEN_ID, 0, REQUIRED_STAKE_AMOUNT) .no_expect(), |sc| sc.stake(), |r| { @@ -115,7 +115,7 @@ fn test_staking_module() { ScCallStep::new().from(ALICE_ADDRESS_EXPR).esdt_transfer( STAKING_TOKEN_ID, 0, - rust_biguint!(REQUIRED_STAKE_AMOUNT / 2), + REQUIRED_STAKE_AMOUNT / 2, ), |sc| sc.stake(), ); @@ -135,7 +135,7 @@ fn test_staking_module() { ScCallStep::new().from(BOB_ADDRESS_EXPR).esdt_transfer( STAKING_TOKEN_ID, 0, - rust_biguint!(REQUIRED_STAKE_AMOUNT), + REQUIRED_STAKE_AMOUNT, ), |sc| sc.stake(), ); @@ -145,7 +145,7 @@ fn test_staking_module() { ScCallStep::new().from(CAROL_ADDRESS_EXPR).esdt_transfer( STAKING_TOKEN_ID, 0, - rust_biguint!(REQUIRED_STAKE_AMOUNT), + REQUIRED_STAKE_AMOUNT, ), |sc| sc.stake(), ); @@ -176,7 +176,7 @@ fn test_staking_module() { ScCallStep::new().from(ALICE_ADDRESS_EXPR).esdt_transfer( STAKING_TOKEN_ID, 0, - rust_biguint!(REQUIRED_STAKE_AMOUNT), + REQUIRED_STAKE_AMOUNT, ), |sc| { sc.stake(); @@ -206,7 +206,7 @@ fn test_staking_module() { world.check_state_step(CheckStateStep::new().put_account( ALICE_ADDRESS_EXPR, - CheckAccount::new().esdt_balance(STAKING_TOKEN_ID_EXPR, rust_biguint!(1_000_000)), + CheckAccount::new().esdt_balance(STAKING_TOKEN_ID_EXPR, "1_000_000"), )); // alice vote to slash bob @@ -390,7 +390,7 @@ fn test_staking_module() { ALICE_ADDRESS_EXPR, CheckAccount::new().esdt_balance( STAKING_TOKEN_ID_EXPR, - rust_biguint!(INITIAL_BALANCE - SLASH_AMOUNT), + INITIAL_BALANCE - SLASH_AMOUNT, ), )); } diff --git a/contracts/feature-tests/use-module/tests/token_merge_module_whitebox_test.rs b/contracts/feature-tests/use-module/tests/token_merge_module_whitebox_test.rs index ae54b9209f..a4a0666d08 100644 --- a/contracts/feature-tests/use-module/tests/token_merge_module_whitebox_test.rs +++ b/contracts/feature-tests/use-module/tests/token_merge_module_whitebox_test.rs @@ -9,7 +9,7 @@ use multiversx_sc_modules::token_merge::{ merged_token_instances::MergedTokenInstances, merged_token_setup::MergedTokenSetupModule, }; use multiversx_sc_scenario::{ - managed_address, managed_biguint, managed_token_id, rust_biguint, + managed_address, managed_biguint, managed_token_id, scenario_model::{ Account, AddressValue, CheckAccount, CheckStateStep, ScCallStep, SetStateStep, TxESDT, }, @@ -71,7 +71,7 @@ fn test_token_merge() { USER_ADDRESS_EXPR, Account::new() .nonce(1) - .esdt_balance(FUNGIBLE_TOKEN_ID_EXPR, rust_biguint!(FUNGIBLE_AMOUNT)) + .esdt_balance(FUNGIBLE_TOKEN_ID_EXPR, FUNGIBLE_AMOUNT) .esdt_nft_all_properties( NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, @@ -459,7 +459,7 @@ fn test_partial_split() { USER_ADDRESS_EXPR, Account::new() .nonce(1) - .esdt_balance(FUNGIBLE_TOKEN_ID_EXPR, rust_biguint!(FUNGIBLE_AMOUNT)) + .esdt_balance(FUNGIBLE_TOKEN_ID_EXPR, FUNGIBLE_AMOUNT) .esdt_nft_all_properties( NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, @@ -677,7 +677,7 @@ fn test_custom_attributes() { USER_ADDRESS_EXPR, Account::new() .nonce(1) - .esdt_balance(FUNGIBLE_TOKEN_ID_EXPR, rust_biguint!(FUNGIBLE_AMOUNT)) + .esdt_balance(FUNGIBLE_TOKEN_ID_EXPR, FUNGIBLE_AMOUNT) .esdt_nft_all_properties( NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE,