From 865040c8408c4d0aa4b8103e97322688dc8bc91a Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Fri, 12 Jul 2024 03:29:42 +0200 Subject: [PATCH 01/92] impl tries --- .../adder/tests/adder_whitebox_test.rs | 46 ++++++- framework/scenario/src/facade/world_tx.rs | 2 + .../facade/world_tx/scenario_tx_whitebox.rs | 117 ++++++++++++++++++ 3 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 framework/scenario/src/facade/world_tx/scenario_tx_whitebox.rs diff --git a/contracts/examples/adder/tests/adder_whitebox_test.rs b/contracts/examples/adder/tests/adder_whitebox_test.rs index 9e7abe4a51..54610cbbad 100644 --- a/contracts/examples/adder/tests/adder_whitebox_test.rs +++ b/contracts/examples/adder/tests/adder_whitebox_test.rs @@ -2,11 +2,14 @@ use adder::*; use multiversx_sc_scenario::imports::*; const ADDER_PATH_EXPR: &str = "mxsc:output/adder.mxsc.json"; +const OWNER: TestAddress = TestAddress::new("owner"); +const ADDER_ADDRESS: TestSCAddress = TestSCAddress::new("adder"); +const CODE_PATH: MxscPath = MxscPath::new("mxsc:output/adder.mxsc.json"); fn world() -> ScenarioWorld { let mut blockchain = ScenarioWorld::new(); - blockchain.register_contract("mxsc:output/adder.mxsc.json", adder::ContractBuilder); + blockchain.register_contract(CODE_PATH, adder::ContractBuilder); blockchain } @@ -47,3 +50,44 @@ fn adder_whitebox() { ), ); } + +#[test] +fn adder_whitebox_unified() { + let mut world = world(); + + world.account(OWNER).nonce(1); + + let _new_address = world + .tx() + .from(OWNER) + .raw_deploy() + .code(CODE_PATH) + .new_address(ADDER_ADDRESS) + .with_result(ExpectError(0, "ok")) + .returns(ReturnsNewBech32Address) + .whitebox(adder::contract_obj::(), |sc| { + sc.init(5u32.into()); + }); + + world + .tx() + .from(OWNER) + .to(ADDER_ADDRESS) + .raw_call("") + .returns(ExpectError(0u64, "ok")) + .whitebox(adder::contract_obj::(), |sc| { + sc.add(5u32.into()); + }); + + let _raw_response = world + .query() + .to(ADDER_ADDRESS) + .raw_call("") + .returns(ReturnsRawResult) + .whitebox(adder::contract_obj::(), |sc| { + let sum = sc.sum().get(); + assert_eq!(sum, BigUint::from(10u64)); + }); + + assert_eq!(new_address, ADDER_ADDRESS); +} diff --git a/framework/scenario/src/facade/world_tx.rs b/framework/scenario/src/facade/world_tx.rs index a2d7373a42..d052614297 100644 --- a/framework/scenario/src/facade/world_tx.rs +++ b/framework/scenario/src/facade/world_tx.rs @@ -5,7 +5,9 @@ mod scenario_query_call; mod scenario_rh_impl; mod scenario_set_state; mod scenario_tx_env; +mod scenario_tx_whitebox; pub use scenario_exec_call::ScenarioEnvExec; pub use scenario_query_call::ScenarioEnvQuery; pub use scenario_tx_env::{ScenarioTxEnv, ScenarioTxEnvData, ScenarioTxRun}; +pub use scenario_tx_whitebox::ScenarioTxWhitebox; diff --git a/framework/scenario/src/facade/world_tx/scenario_tx_whitebox.rs b/framework/scenario/src/facade/world_tx/scenario_tx_whitebox.rs new file mode 100644 index 0000000000..933af47cc5 --- /dev/null +++ b/framework/scenario/src/facade/world_tx/scenario_tx_whitebox.rs @@ -0,0 +1,117 @@ +use crate::scenario::tx_to_step::TxToQueryStep; +use crate::ScenarioEnvQuery; +use crate::{ + imports::StaticApi, + scenario::{run_vm::ScenarioVMRunner, tx_to_step::TxToStep}, + scenario_model::TxResponse, + ScenarioEnvExec, +}; +use multiversx_sc::{ + tuple_util::NestedTupleFlatten, + types::{ + Code, DeployCall, FunctionCall, RHListExec, Tx, TxCodeValue, TxFromSpecified, TxNoPayment, + TxPayment, TxToSpecified, + }, +}; + +pub trait ScenarioTxWhitebox { + type Returns; + fn whitebox( + self, + contract_obj: ContractObj, + f: F, + ) -> Self::Returns; +} + +pub struct ContractObj +where + A: multiversx_sc::api::VMApi, +{ + _phantom: core::marker::PhantomData, +} + +impl<'w, From, Payment, CodeValue, RH> ScenarioTxWhitebox + for Tx< + ScenarioEnvExec<'w>, + From, + (), + Payment, + (), + DeployCall, Code>, + RH, + > +where + From: TxFromSpecified>, + Payment: TxNoPayment>, + CodeValue: TxCodeValue>, + RH: RHListExec>, + RH::ListReturns: NestedTupleFlatten, +{ + type Returns = ::Unpacked; + + fn whitebox( + self, + contract_obj: ContractObj, + f: F, + ) -> Self::Returns { + let step_wrapper = self.tx_to_step(); + + let mut scenario_vm_runner = ScenarioVMRunner::new(); + let (_new_addr, _tx_result) = + scenario_vm_runner.perform_sc_deploy_lambda(&step_wrapper.step, || f(contract_obj)); + + step_wrapper.process_result() + } +} + +impl<'w, From, To, Payment, RH> ScenarioTxWhitebox + for Tx, From, To, Payment, (), FunctionCall, RH> +where + From: TxFromSpecified>, + To: TxToSpecified>, + Payment: TxPayment>, + RH: RHListExec>, + RH::ListReturns: NestedTupleFlatten, +{ + type Returns = ::Unpacked; + + fn whitebox( + self, + contract_obj: ContractObj, + f: F, + ) -> Self::Returns { + let step_wrapper = self.tx_to_step(); + let _tx_result = self + .env + .world + .get_mut_debugger_backend() + .vm_runner + .perform_sc_call_lambda(&step_wrapper.step, || f(contract_obj)); + + step_wrapper.process_result() + } +} + +impl<'w, To, Payment, RH> ScenarioTxWhitebox + for Tx, (), To, Payment, (), FunctionCall, RH> +where + To: TxToSpecified>, + Payment: TxNoPayment>, + RH: RHListExec>, + RH::ListReturns: NestedTupleFlatten, +{ + type Returns = ::Unpacked; + + fn whitebox( + self, + contract_obj: ContractObj, + f: F, + ) -> Self::Returns { + let step_wrapper = self.tx_to_query_step(); + + let mut scenario_vm_runner = ScenarioVMRunner::new(); + let _tx_result = + scenario_vm_runner.perform_sc_query_lambda(&step_wrapper.step, || f(contract_obj)); + step_wrapper.process_result() + } +} From dbdb627f41e35c2c4ae18f9d552060c8d748c2e7 Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Fri, 12 Jul 2024 17:53:41 +0200 Subject: [PATCH 02/92] fix debugger backend issue --- .../adder/tests/adder_whitebox_test.rs | 4 +-- .../facade/world_tx/scenario_tx_whitebox.rs | 34 ++++++++----------- 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/contracts/examples/adder/tests/adder_whitebox_test.rs b/contracts/examples/adder/tests/adder_whitebox_test.rs index 54610cbbad..92f13a2bb3 100644 --- a/contracts/examples/adder/tests/adder_whitebox_test.rs +++ b/contracts/examples/adder/tests/adder_whitebox_test.rs @@ -69,6 +69,8 @@ fn adder_whitebox_unified() { sc.init(5u32.into()); }); + assert_eq!(_new_address, ADDER_ADDRESS.to_address().into()); + world .tx() .from(OWNER) @@ -88,6 +90,4 @@ fn adder_whitebox_unified() { let sum = sc.sum().get(); assert_eq!(sum, BigUint::from(10u64)); }); - - assert_eq!(new_address, ADDER_ADDRESS); } diff --git a/framework/scenario/src/facade/world_tx/scenario_tx_whitebox.rs b/framework/scenario/src/facade/world_tx/scenario_tx_whitebox.rs index 933af47cc5..0d9040a2ee 100644 --- a/framework/scenario/src/facade/world_tx/scenario_tx_whitebox.rs +++ b/framework/scenario/src/facade/world_tx/scenario_tx_whitebox.rs @@ -1,10 +1,7 @@ use crate::scenario::tx_to_step::TxToQueryStep; use crate::ScenarioEnvQuery; use crate::{ - imports::StaticApi, - scenario::{run_vm::ScenarioVMRunner, tx_to_step::TxToStep}, - scenario_model::TxResponse, - ScenarioEnvExec, + imports::StaticApi, scenario::tx_to_step::TxToStep, scenario_model::TxResponse, ScenarioEnvExec, }; use multiversx_sc::{ tuple_util::NestedTupleFlatten, @@ -23,13 +20,6 @@ pub trait ScenarioTxWhitebox { ) -> Self::Returns; } -pub struct ContractObj -where - A: multiversx_sc::api::VMApi, -{ - _phantom: core::marker::PhantomData, -} - impl<'w, From, Payment, CodeValue, RH> ScenarioTxWhitebox for Tx< ScenarioEnvExec<'w>, @@ -55,10 +45,12 @@ where f: F, ) -> Self::Returns { let step_wrapper = self.tx_to_step(); - - let mut scenario_vm_runner = ScenarioVMRunner::new(); - let (_new_addr, _tx_result) = - scenario_vm_runner.perform_sc_deploy_lambda(&step_wrapper.step, || f(contract_obj)); + let (_new_addr, _tx_result) = step_wrapper + .env + .world + .get_mut_debugger_backend() + .vm_runner + .perform_sc_deploy_lambda(&step_wrapper.step, || f(contract_obj)); step_wrapper.process_result() } @@ -81,7 +73,7 @@ where f: F, ) -> Self::Returns { let step_wrapper = self.tx_to_step(); - let _tx_result = self + let _tx_result = step_wrapper .env .world .get_mut_debugger_backend() @@ -109,9 +101,13 @@ where ) -> Self::Returns { let step_wrapper = self.tx_to_query_step(); - let mut scenario_vm_runner = ScenarioVMRunner::new(); - let _tx_result = - scenario_vm_runner.perform_sc_query_lambda(&step_wrapper.step, || f(contract_obj)); + let _tx_result = step_wrapper + .env + .world + .get_mut_debugger_backend() + .vm_runner + .perform_sc_query_lambda(&step_wrapper.step, || f(contract_obj)); + step_wrapper.process_result() } } From dfb43b9c4a222ebae7977de7ef21de3a6d03e31c Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Fri, 12 Jul 2024 20:24:20 +0200 Subject: [PATCH 03/92] changed contract obj api --- contracts/examples/adder/tests/adder_whitebox_test.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/contracts/examples/adder/tests/adder_whitebox_test.rs b/contracts/examples/adder/tests/adder_whitebox_test.rs index 92f13a2bb3..726e1ab18a 100644 --- a/contracts/examples/adder/tests/adder_whitebox_test.rs +++ b/contracts/examples/adder/tests/adder_whitebox_test.rs @@ -65,8 +65,8 @@ fn adder_whitebox_unified() { .new_address(ADDER_ADDRESS) .with_result(ExpectError(0, "ok")) .returns(ReturnsNewBech32Address) - .whitebox(adder::contract_obj::(), |sc| { - sc.init(5u32.into()); + .whitebox(adder::contract_obj::(), |sc| { + sc.init(BigUint::from(5u64)); }); assert_eq!(_new_address, ADDER_ADDRESS.to_address().into()); @@ -77,8 +77,8 @@ fn adder_whitebox_unified() { .to(ADDER_ADDRESS) .raw_call("") .returns(ExpectError(0u64, "ok")) - .whitebox(adder::contract_obj::(), |sc| { - sc.add(5u32.into()); + .whitebox(adder::contract_obj::(), |sc| { + sc.add(BigUint::from(5u64)); }); let _raw_response = world @@ -86,7 +86,7 @@ fn adder_whitebox_unified() { .to(ADDER_ADDRESS) .raw_call("") .returns(ReturnsRawResult) - .whitebox(adder::contract_obj::(), |sc| { + .whitebox(adder::contract_obj::(), |sc| { let sum = sc.sum().get(); assert_eq!(sum, BigUint::from(10u64)); }); From 3fc34101fb85f911cde6825815431145af2a8d9e Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Wed, 31 Jul 2024 16:46:13 +0300 Subject: [PATCH 04/92] return new node id on insert element --- .../src/storage/mappers/ordered_binary_tree_mapper.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/framework/base/src/storage/mappers/ordered_binary_tree_mapper.rs b/framework/base/src/storage/mappers/ordered_binary_tree_mapper.rs index 064e90551c..2425c59049 100644 --- a/framework/base/src/storage/mappers/ordered_binary_tree_mapper.rs +++ b/framework/base/src/storage/mappers/ordered_binary_tree_mapper.rs @@ -232,7 +232,7 @@ where opt_predecessor } - pub fn insert_element(&mut self, new_data: T) { + pub fn insert_element(&mut self, new_data: T) -> u64 { let new_node_id = self.get_and_increment_last_id(); let mut new_node = OrderedBinaryTreeNode::new(new_node_id, new_data); @@ -243,7 +243,7 @@ where let current_node = unsafe { opt_current_node.unwrap_unchecked() }; if new_node.data == current_node.data { - return; + return 0u64; } if new_node.data < current_node.data { @@ -266,7 +266,7 @@ where let root_key = self.build_root_key(); storage_set(root_key.as_ref(), &new_node); - return; + return 0u64; } let mut new_node_parent = unsafe { opt_new_node_parent.unwrap_unchecked() }; @@ -278,6 +278,8 @@ where self.set_item(new_node_id, &new_node); self.set_item(new_node_parent.current_node_id, &new_node_parent); + + new_node_id } pub fn delete_node(&mut self, data: T) { From b98c1f712b13678d69e9804ad4a4817b53356375 Mon Sep 17 00:00:00 2001 From: Andrei Vasilescu Date: Mon, 12 Aug 2024 15:50:43 +0300 Subject: [PATCH 05/92] pem wallet generation --- Cargo.lock | 1 + framework/meta/Cargo.toml | 4 ++ framework/meta/src/cli/cli_args_standalone.rs | 58 +++++++++++++++++++ framework/meta/src/cli/cli_standalone_main.rs | 4 ++ framework/meta/src/cmd.rs | 1 + framework/meta/src/cmd/wallet.rs | 53 +++++++++++++++++ 6 files changed, 121 insertions(+) create mode 100644 framework/meta/src/cmd/wallet.rs diff --git a/Cargo.lock b/Cargo.lock index abeb3c37e1..4ae509e714 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -1996,6 +1996,7 @@ dependencies = [ "multiversx-sc", "multiversx-sc-meta-lib", "multiversx-sc-snippets", + "multiversx-sdk", "pathdiff", "reqwest", "ruplacer", diff --git a/framework/meta/Cargo.toml b/framework/meta/Cargo.toml index bd6775ed1a..0aebe72194 100644 --- a/framework/meta/Cargo.toml +++ b/framework/meta/Cargo.toml @@ -52,3 +52,7 @@ features = ["alloc", "num-bigint"] [dependencies.multiversx-sc-snippets] version = "=0.52.3" path = "../snippets" + +[dependencies.multiversx-sdk] +version = "=0.5.0" +path = "../../sdk/core" diff --git a/framework/meta/src/cli/cli_args_standalone.rs b/framework/meta/src/cli/cli_args_standalone.rs index 335afe41ea..38857c6f9e 100644 --- a/framework/meta/src/cli/cli_args_standalone.rs +++ b/framework/meta/src/cli/cli_args_standalone.rs @@ -75,6 +75,12 @@ pub enum StandaloneCliAction { about = "Generates a report on the local depedencies of contract crates. Will explore indirect depdencies too." )] LocalDeps(LocalDepsArgs), + + #[command( + name = "wallet", + about = "Generates a new wallet or performs actions on an existing wallet." + )] + Wallet(WalletArgs), } #[derive(Default, Clone, PartialEq, Eq, Debug, Args)] @@ -348,3 +354,55 @@ pub struct AccountArgs { #[arg(long = "address", verbatim_doc_comment)] pub address: String, } + +#[derive(Clone, PartialEq, Eq, Debug, Subcommand)] +pub enum WalletAction { + #[command(name = "new", about = "Creates a new wallet")] + New(WalletNewArgs), + + #[command(name = "convert", about = "Converts a wallet")] + Convert(WalletConvertArgs), +} + +#[derive(Default, Clone, PartialEq, Eq, Debug, ValueEnum)] +pub enum WalletFormat { + #[default] + Pem, +} + +#[derive(Default, Clone, PartialEq, Eq, Debug, ValueEnum)] +pub enum WalletConvertFormat { + #[default] + Bech32, + + Hex, +} + +#[derive(Default, Clone, PartialEq, Eq, Debug, Parser)] +#[command(propagate_version = true)] +pub struct WalletArgs { + #[command(subcommand)] + pub command: Option, +} + +#[derive(Default, Clone, PartialEq, Eq, Debug, Args)] +pub struct WalletNewArgs { + /// The type of wallet to create. + #[arg(long = "format", verbatim_doc_comment)] + pub wallet_format: Option, + + /// The name of the wallet to create. + #[arg(long = "outfile", verbatim_doc_comment)] + pub outfile: Option, + // #[arg(long = "address-hrp")] + // pub address_hrp: Option, +} + +#[derive(Default, Clone, PartialEq, Eq, Debug, Args)] +pub struct WalletConvertArgs { + #[arg(long = "from", verbatim_doc_comment)] + pub from: Option, + + #[arg(long = "to", verbatim_doc_comment)] + pub to: Option, +} diff --git a/framework/meta/src/cli/cli_standalone_main.rs b/framework/meta/src/cli/cli_standalone_main.rs index 6c8c6a67b0..5100750abc 100644 --- a/framework/meta/src/cli/cli_standalone_main.rs +++ b/framework/meta/src/cli/cli_standalone_main.rs @@ -1,5 +1,6 @@ use crate::cli::{StandaloneCliAction, StandaloneCliArgs}; use crate::cmd::retrieve_address::retrieve_address; +use crate::cmd::wallet::wallet; use clap::Parser; use crate::cmd::all::call_all_meta; @@ -41,6 +42,9 @@ pub async fn cli_main_standalone() { Some(StandaloneCliAction::LocalDeps(args)) => { local_deps(args); }, + Some(StandaloneCliAction::Wallet(args)) => { + wallet(args); + }, None => {}, } } diff --git a/framework/meta/src/cmd.rs b/framework/meta/src/cmd.rs index a588f90162..8053a2113e 100644 --- a/framework/meta/src/cmd.rs +++ b/framework/meta/src/cmd.rs @@ -9,3 +9,4 @@ pub mod template; pub mod test; pub mod test_coverage; pub mod upgrade; +pub mod wallet; diff --git a/framework/meta/src/cmd/wallet.rs b/framework/meta/src/cmd/wallet.rs new file mode 100644 index 0000000000..4ad0a3f7d9 --- /dev/null +++ b/framework/meta/src/cmd/wallet.rs @@ -0,0 +1,53 @@ +use std::{fs::File, io::Write}; + +use crate::cli::{WalletAction, WalletArgs, WalletConvertArgs, WalletFormat, WalletNewArgs}; +use multiversx_sdk::{data::address::Address, wallet::Wallet}; + +pub fn wallet(args: &WalletArgs) { + let command = args + .command + .as_ref() + .expect("command expected after `wallet`"); + match command { + WalletAction::New(new_args) => new(new_args), + WalletAction::Convert(convert_args) => convert(convert_args), + } +} + +fn convert(convert_args: &WalletConvertArgs) { + todo!() +} + +fn new(new_args: &WalletNewArgs) { + let format = new_args + .wallet_format + .as_ref() + .expect("wallet format is required"); + let outfile = new_args.outfile.as_ref().expect("output file is required"); + + match format { + WalletFormat::Pem => { + let mnemonic = Wallet::generate_mnemonic(); + let private_key = Wallet::get_private_key_from_mnemonic(mnemonic, 0u32, 0u32); + let pk_str: &str = &private_key.to_string(); + let wallet = Wallet::from_private_key(pk_str).unwrap(); + let address = wallet.address(); + + println!("Wallet address: {}", address); + + generate_pem(&address, pk_str, outfile); + }, + } +} + +fn generate_pem(address: &Address, private_key: &str, outfile: &String) { + let pem_content = format!( + "-----BEGIN PRIVATE KEY for {}-----\n{}\n-----END PRIVATE KEY for {}-----", + address.to_bech32_string().unwrap(), + private_key, + address.to_bech32_string().unwrap() + ); + + let mut file = File::create(outfile).unwrap(); + file.write_all(pem_content.as_bytes()).unwrap() +} From b530c1f6a712538be16e01c47a541e1c6cafd74d Mon Sep 17 00:00:00 2001 From: Andrei Vasilescu Date: Mon, 12 Aug 2024 18:52:33 +0300 Subject: [PATCH 06/92] [WIP] generated pem file --- Cargo.lock | 19 +++-- framework/meta/Cargo.toml | 1 + framework/meta/src/cli/cli_args_standalone.rs | 32 +++----- framework/meta/src/cmd/wallet.rs | 77 +++++++++++++++++-- 4 files changed, 95 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4ae509e714..08f2acc6ae 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -195,6 +195,12 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + [[package]] name = "base64" version = "0.22.1" @@ -1988,6 +1994,7 @@ dependencies = [ name = "multiversx-sc-meta" version = "0.52.3" dependencies = [ + "base64 0.13.1", "clap", "colored", "common-path", @@ -2038,7 +2045,7 @@ dependencies = [ name = "multiversx-sc-scenario" version = "0.52.3" dependencies = [ - "base64", + "base64 0.22.1", "bech32", "colored", "hex", @@ -2062,7 +2069,7 @@ dependencies = [ name = "multiversx-sc-snippets" version = "0.52.3" dependencies = [ - "base64", + "base64 0.22.1", "env_logger", "futures", "hex", @@ -2086,7 +2093,7 @@ name = "multiversx-sdk" version = "0.5.0" dependencies = [ "anyhow", - "base64", + "base64 0.22.1", "bech32", "bip39", "hex", @@ -2424,7 +2431,7 @@ version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae" dependencies = [ - "base64", + "base64 0.22.1", "serde", ] @@ -2756,7 +2763,7 @@ version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" dependencies = [ - "base64", + "base64 0.22.1", "bytes", "encoding_rs", "futures-channel", @@ -2926,7 +2933,7 @@ version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" dependencies = [ - "base64", + "base64 0.22.1", "rustls-pki-types", ] diff --git a/framework/meta/Cargo.toml b/framework/meta/Cargo.toml index 0aebe72194..c59184d411 100644 --- a/framework/meta/Cargo.toml +++ b/framework/meta/Cargo.toml @@ -39,6 +39,7 @@ zip = { version = "2.1", features = ["deflate"], default-features = false } copy_dir = "0.1.2" pathdiff = "0.2.1" common-path = "1.0.0" +base64 = "0.13" [dependencies.multiversx-sc-meta-lib] version = "=0.52.3" diff --git a/framework/meta/src/cli/cli_args_standalone.rs b/framework/meta/src/cli/cli_args_standalone.rs index 38857c6f9e..d670987338 100644 --- a/framework/meta/src/cli/cli_args_standalone.rs +++ b/framework/meta/src/cli/cli_args_standalone.rs @@ -364,20 +364,6 @@ pub enum WalletAction { Convert(WalletConvertArgs), } -#[derive(Default, Clone, PartialEq, Eq, Debug, ValueEnum)] -pub enum WalletFormat { - #[default] - Pem, -} - -#[derive(Default, Clone, PartialEq, Eq, Debug, ValueEnum)] -pub enum WalletConvertFormat { - #[default] - Bech32, - - Hex, -} - #[derive(Default, Clone, PartialEq, Eq, Debug, Parser)] #[command(propagate_version = true)] pub struct WalletArgs { @@ -389,20 +375,24 @@ pub struct WalletArgs { pub struct WalletNewArgs { /// The type of wallet to create. #[arg(long = "format", verbatim_doc_comment)] - pub wallet_format: Option, + pub wallet_format: Option, /// The name of the wallet to create. #[arg(long = "outfile", verbatim_doc_comment)] pub outfile: Option, - // #[arg(long = "address-hrp")] - // pub address_hrp: Option, } #[derive(Default, Clone, PartialEq, Eq, Debug, Args)] pub struct WalletConvertArgs { - #[arg(long = "from", verbatim_doc_comment)] - pub from: Option, + #[arg(long = "in-format", verbatim_doc_comment)] + pub from: Option, - #[arg(long = "to", verbatim_doc_comment)] - pub to: Option, + #[arg(long = "out-format", verbatim_doc_comment)] + pub to: Option, + + #[arg(long = "infile", verbatim_doc_comment)] + pub infile: Option, + + #[arg(long = "outfile", verbatim_doc_comment)] + pub outfile: Option, } diff --git a/framework/meta/src/cmd/wallet.rs b/framework/meta/src/cmd/wallet.rs index 4ad0a3f7d9..b1fdddee9c 100644 --- a/framework/meta/src/cmd/wallet.rs +++ b/framework/meta/src/cmd/wallet.rs @@ -1,6 +1,12 @@ -use std::{fs::File, io::Write}; +use base64; +use core::str; +use std::{ + fs::{self, File}, + io::Write, +}; -use crate::cli::{WalletAction, WalletArgs, WalletConvertArgs, WalletFormat, WalletNewArgs}; +use crate::cli::{WalletAction, WalletArgs, WalletConvertArgs, WalletNewArgs}; +use multiversx_sc_snippets::{hex, imports::Bech32Address}; use multiversx_sdk::{data::address::Address, wallet::Wallet}; pub fn wallet(args: &WalletArgs) { @@ -15,7 +21,46 @@ pub fn wallet(args: &WalletArgs) { } fn convert(convert_args: &WalletConvertArgs) { - todo!() + let infile = convert_args + .infile + .as_ref() + .expect("input file is required"); + let outfile = convert_args.outfile.as_ref(); + let in_format = convert_args + .from + .as_ref() + .expect("input format is required"); + let out_format = convert_args.to.as_ref().expect("output format is required"); + + let in_address = fs::read_to_string(infile).unwrap(); + let mut out_addr: String = String::from(""); + + match (in_format.as_str(), out_format.as_str()) { + ("address-bech32", "address-hex") => { + out_addr = Bech32Address::from_bech32_string(in_address).to_hex(); + }, + ("address-hex", "address-bech32") => { + // out_addr = Bech32Address::from(in_address).to_bech32_string(); + let bytes_from_hex: [u8; 64] = hex::decode(in_address).unwrap().try_into().unwrap(); + out_addr = Bech32Address::from_bech32_string( + str::from_utf8(&bytes_from_hex).unwrap().to_string(), + ) + .to_bech32_string(); + }, + _ => { + println!("Unsupported conversion"); + }, + } + + match outfile { + Some(outfile) => { + let mut file = File::create(outfile).unwrap(); + file.write_all(out_addr.as_bytes()).unwrap(); + }, + None => { + println!("{}", out_addr); + }, + } } fn new(new_args: &WalletNewArgs) { @@ -25,8 +70,8 @@ fn new(new_args: &WalletNewArgs) { .expect("wallet format is required"); let outfile = new_args.outfile.as_ref().expect("output file is required"); - match format { - WalletFormat::Pem => { + match format.as_str() { + "pem" => { let mnemonic = Wallet::generate_mnemonic(); let private_key = Wallet::get_private_key_from_mnemonic(mnemonic, 0u32, 0u32); let pk_str: &str = &private_key.to_string(); @@ -37,14 +82,32 @@ fn new(new_args: &WalletNewArgs) { generate_pem(&address, pk_str, outfile); }, + _ => { + println!("Unsupported wallet format"); + }, } } fn generate_pem(address: &Address, private_key: &str, outfile: &String) { + println!("{private_key}"); + let private_key_hex_encoded = hex::encode(private_key.as_bytes()); + println!("HEX {private_key_hex_encoded}"); + // let priv_key_bytes = private_key_hex_encoded.as_bytes(); + let private_key_base64 = base64::encode(&private_key_hex_encoded.as_bytes()); + println!("B64 {private_key_base64}"); + + // Split the base64 string into 64-character lines + let formatted_key = private_key_base64 + .as_bytes() + .chunks(64) + .map(|chunk| std::str::from_utf8(chunk).unwrap()) + .collect::>() + .join("\n"); + let pem_content = format!( - "-----BEGIN PRIVATE KEY for {}-----\n{}\n-----END PRIVATE KEY for {}-----", + "-----BEGIN PRIVATE KEY for {}-----\n{}\n-----END PRIVATE KEY for {}-----\n", address.to_bech32_string().unwrap(), - private_key, + formatted_key, address.to_bech32_string().unwrap() ); From d5be23d47cd28e9aae627899dc80d85302d2e5c6 Mon Sep 17 00:00:00 2001 From: Andrei Vasilescu Date: Tue, 13 Aug 2024 13:09:31 +0300 Subject: [PATCH 07/92] demo wallet creation & conversion --- framework/meta/src/cli/cli_args_standalone.rs | 4 +- framework/meta/src/cmd/wallet.rs | 105 ++++++++++-------- 2 files changed, 59 insertions(+), 50 deletions(-) diff --git a/framework/meta/src/cli/cli_args_standalone.rs b/framework/meta/src/cli/cli_args_standalone.rs index d670987338..59cb0a4d86 100644 --- a/framework/meta/src/cli/cli_args_standalone.rs +++ b/framework/meta/src/cli/cli_args_standalone.rs @@ -385,10 +385,10 @@ pub struct WalletNewArgs { #[derive(Default, Clone, PartialEq, Eq, Debug, Args)] pub struct WalletConvertArgs { #[arg(long = "in-format", verbatim_doc_comment)] - pub from: Option, + pub from: String, #[arg(long = "out-format", verbatim_doc_comment)] - pub to: Option, + pub to: String, #[arg(long = "infile", verbatim_doc_comment)] pub infile: Option, diff --git a/framework/meta/src/cmd/wallet.rs b/framework/meta/src/cmd/wallet.rs index b1fdddee9c..bdddf81b60 100644 --- a/framework/meta/src/cmd/wallet.rs +++ b/framework/meta/src/cmd/wallet.rs @@ -1,13 +1,14 @@ use base64; use core::str; +use multiversx_sc::types; use std::{ fs::{self, File}, - io::Write, + io::{self, Read, Write}, }; use crate::cli::{WalletAction, WalletArgs, WalletConvertArgs, WalletNewArgs}; use multiversx_sc_snippets::{hex, imports::Bech32Address}; -use multiversx_sdk::{data::address::Address, wallet::Wallet}; +use multiversx_sdk::{crypto::public_key::PublicKey, data::address::Address, wallet::Wallet}; pub fn wallet(args: &WalletArgs) { let command = args @@ -21,31 +22,37 @@ pub fn wallet(args: &WalletArgs) { } fn convert(convert_args: &WalletConvertArgs) { - let infile = convert_args - .infile - .as_ref() - .expect("input file is required"); + let infile = convert_args.infile.as_ref(); let outfile = convert_args.outfile.as_ref(); - let in_format = convert_args - .from - .as_ref() - .expect("input format is required"); - let out_format = convert_args.to.as_ref().expect("output format is required"); + let in_format = &convert_args.from; + let out_format = &convert_args.to; + + let mut in_address = String::new(); + let mut out_address: String = String::new(); + + match infile { + Some(file) => in_address = fs::read_to_string(file).unwrap(), + None => { + println!("Insert text below. Press 'Ctrl-D' (Linux / MacOS) or 'Ctrl-Z' (Windows) when done."); + _ = io::stdin().read_to_string(&mut in_address).unwrap() + }, + } - let in_address = fs::read_to_string(infile).unwrap(); - let mut out_addr: String = String::from(""); + in_address = in_address.replace('\n', ""); match (in_format.as_str(), out_format.as_str()) { ("address-bech32", "address-hex") => { - out_addr = Bech32Address::from_bech32_string(in_address).to_hex(); + out_address = Bech32Address::from_bech32_string(in_address).to_hex(); }, ("address-hex", "address-bech32") => { - // out_addr = Bech32Address::from(in_address).to_bech32_string(); - let bytes_from_hex: [u8; 64] = hex::decode(in_address).unwrap().try_into().unwrap(); - out_addr = Bech32Address::from_bech32_string( - str::from_utf8(&bytes_from_hex).unwrap().to_string(), - ) - .to_bech32_string(); + let bytes_from_hex = hex::decode(in_address).unwrap(); + let bytes_arr: [u8; 32] = bytes_from_hex.try_into().unwrap(); + + let addr = types::Address::from(&bytes_arr); + out_address = Bech32Address::from(addr).to_bech32_str().to_string(); + }, + ("", _) | (_, "") => { + println!("error: the following arguments are required: --in-format, --out-format"); }, _ => { println!("Unsupported conversion"); @@ -55,49 +62,51 @@ fn convert(convert_args: &WalletConvertArgs) { match outfile { Some(outfile) => { let mut file = File::create(outfile).unwrap(); - file.write_all(out_addr.as_bytes()).unwrap(); + out_address.push('\n'); + file.write_all(out_address.as_bytes()).unwrap(); }, None => { - println!("{}", out_addr); + println!("{}", out_address); }, } } fn new(new_args: &WalletNewArgs) { - let format = new_args - .wallet_format - .as_ref() - .expect("wallet format is required"); - let outfile = new_args.outfile.as_ref().expect("output file is required"); + let format = new_args.wallet_format.as_ref(); + let outfile = new_args.outfile.as_ref(); + let mnemonic = Wallet::generate_mnemonic(); + println!("Mnemonic: {}", mnemonic); - match format.as_str() { - "pem" => { - let mnemonic = Wallet::generate_mnemonic(); - let private_key = Wallet::get_private_key_from_mnemonic(mnemonic, 0u32, 0u32); - let pk_str: &str = &private_key.to_string(); - let wallet = Wallet::from_private_key(pk_str).unwrap(); - let address = wallet.address(); + let private_key = Wallet::get_private_key_from_mnemonic(mnemonic, 0u32, 0u32); + let public_key = PublicKey::from(&private_key); - println!("Wallet address: {}", address); + let public_key_str: &str = &public_key.to_string(); + let private_key_str: &str = &private_key.to_string(); - generate_pem(&address, pk_str, outfile); - }, - _ => { - println!("Unsupported wallet format"); - }, + let wallet = Wallet::from_private_key(private_key_str).unwrap(); + let address = wallet.address(); + + println!("Wallet address: {}", address); + + if let Some(f) = format { + match (f.as_str(), outfile) { + ("pem", Some(file)) => { + generate_pem(&address, private_key_str, public_key_str, file); + }, + ("pem", None) => { + println!("Output file is required for PEM format"); + }, + _ => {}, + } } } -fn generate_pem(address: &Address, private_key: &str, outfile: &String) { - println!("{private_key}"); - let private_key_hex_encoded = hex::encode(private_key.as_bytes()); - println!("HEX {private_key_hex_encoded}"); - // let priv_key_bytes = private_key_hex_encoded.as_bytes(); - let private_key_base64 = base64::encode(&private_key_hex_encoded.as_bytes()); - println!("B64 {private_key_base64}"); +fn generate_pem(address: &Address, private_key: &str, public_key: &str, outfile: &String) { + let concat_keys = format!("{}{}", private_key, public_key); + let concat_keys_b64 = base64::encode(concat_keys); // Split the base64 string into 64-character lines - let formatted_key = private_key_base64 + let formatted_key = concat_keys_b64 .as_bytes() .chunks(64) .map(|chunk| std::str::from_utf8(chunk).unwrap()) From 47ef8de7f75ed1c031b448d00579debefa2e0941 Mon Sep 17 00:00:00 2001 From: Andrei Vasilescu Date: Tue, 13 Aug 2024 17:03:47 +0300 Subject: [PATCH 08/92] added bech32 command and updated conversion --- framework/meta/Cargo.toml | 2 +- framework/meta/src/cli/cli_args_standalone.rs | 17 ++- framework/meta/src/cmd/wallet.rs | 132 +++++++++++------- 3 files changed, 101 insertions(+), 50 deletions(-) diff --git a/framework/meta/Cargo.toml b/framework/meta/Cargo.toml index c59184d411..63625c1746 100644 --- a/framework/meta/Cargo.toml +++ b/framework/meta/Cargo.toml @@ -39,7 +39,7 @@ zip = { version = "2.1", features = ["deflate"], default-features = false } copy_dir = "0.1.2" pathdiff = "0.2.1" common-path = "1.0.0" -base64 = "0.13" +bip39 = "2.0.0" [dependencies.multiversx-sc-meta-lib] version = "=0.52.3" diff --git a/framework/meta/src/cli/cli_args_standalone.rs b/framework/meta/src/cli/cli_args_standalone.rs index 59cb0a4d86..104feac18d 100644 --- a/framework/meta/src/cli/cli_args_standalone.rs +++ b/framework/meta/src/cli/cli_args_standalone.rs @@ -360,15 +360,20 @@ pub enum WalletAction { #[command(name = "new", about = "Creates a new wallet")] New(WalletNewArgs), + #[command( + name = "bech32", + about = "Encodes/decodes a bech32 address to/from hex" + )] + Bech32(WalletBech32Args), #[command(name = "convert", about = "Converts a wallet")] Convert(WalletConvertArgs), } -#[derive(Default, Clone, PartialEq, Eq, Debug, Parser)] +#[derive(Clone, PartialEq, Eq, Debug, Parser)] #[command(propagate_version = true)] pub struct WalletArgs { #[command(subcommand)] - pub command: Option, + pub command: WalletAction, } #[derive(Default, Clone, PartialEq, Eq, Debug, Args)] @@ -396,3 +401,11 @@ pub struct WalletConvertArgs { #[arg(long = "outfile", verbatim_doc_comment)] pub outfile: Option, } + +#[derive(Default, Clone, PartialEq, Eq, Debug, Args)] +pub struct WalletBech32Args { + #[arg(long = "encode", verbatim_doc_comment)] + pub hex_address: Option, + #[arg(long = "decode", verbatim_doc_comment)] + pub bech32_address: Option, +} diff --git a/framework/meta/src/cmd/wallet.rs b/framework/meta/src/cmd/wallet.rs index bdddf81b60..7ed5ea58bb 100644 --- a/framework/meta/src/cmd/wallet.rs +++ b/framework/meta/src/cmd/wallet.rs @@ -1,4 +1,3 @@ -use base64; use core::str; use multiversx_sc::types; use std::{ @@ -6,17 +5,17 @@ use std::{ io::{self, Read, Write}, }; -use crate::cli::{WalletAction, WalletArgs, WalletConvertArgs, WalletNewArgs}; +use crate::cli::{WalletAction, WalletArgs, WalletBech32Args, WalletConvertArgs, WalletNewArgs}; +use bip39::Mnemonic; use multiversx_sc_snippets::{hex, imports::Bech32Address}; -use multiversx_sdk::{crypto::public_key::PublicKey, data::address::Address, wallet::Wallet}; - +use multiversx_sdk::{ + crypto::public_key::PublicKey, data::address::Address, utils::base64_encode, wallet::Wallet, +}; pub fn wallet(args: &WalletArgs) { - let command = args - .command - .as_ref() - .expect("command expected after `wallet`"); + let command = &args.command; match command { WalletAction::New(new_args) => new(new_args), + WalletAction::Bech32(bech32_args) => bech32_conversion(bech32_args), WalletAction::Convert(convert_args) => convert(convert_args), } } @@ -27,71 +26,105 @@ fn convert(convert_args: &WalletConvertArgs) { let in_format = &convert_args.from; let out_format = &convert_args.to; - let mut in_address = String::new(); - let mut out_address: String = String::new(); - - match infile { - Some(file) => in_address = fs::read_to_string(file).unwrap(), - None => { - println!("Insert text below. Press 'Ctrl-D' (Linux / MacOS) or 'Ctrl-Z' (Windows) when done."); - _ = io::stdin().read_to_string(&mut in_address).unwrap() - }, - } - - in_address = in_address.replace('\n', ""); + let mut mnemonic_str = String::new(); match (in_format.as_str(), out_format.as_str()) { - ("address-bech32", "address-hex") => { - out_address = Bech32Address::from_bech32_string(in_address).to_hex(); - }, - ("address-hex", "address-bech32") => { - let bytes_from_hex = hex::decode(in_address).unwrap(); - let bytes_arr: [u8; 32] = bytes_from_hex.try_into().unwrap(); - - let addr = types::Address::from(&bytes_arr); - out_address = Bech32Address::from(addr).to_bech32_str().to_string(); - }, - ("", _) | (_, "") => { - println!("error: the following arguments are required: --in-format, --out-format"); + ("mnemonic", "pem") => match infile { + Some(file) => { + mnemonic_str = fs::read_to_string(file).unwrap(); + mnemonic_str = mnemonic_str.replace('\n', ""); + }, + None => { + println!("Insert text below. Press 'Ctrl-D' (Linux / MacOS) or 'Ctrl-Z' (Windows) when done."); + _ = io::stdin().read_to_string(&mut mnemonic_str).unwrap() + }, }, _ => { println!("Unsupported conversion"); }, } + let mnemonic = Mnemonic::parse(mnemonic_str).unwrap(); + + let (private_key_str, public_key_str) = get_wallet_keys(mnemonic); + let address = get_wallet_address(private_key_str.as_str()); + match outfile { Some(outfile) => { - let mut file = File::create(outfile).unwrap(); - out_address.push('\n'); - file.write_all(out_address.as_bytes()).unwrap(); + generate_pem( + &address, + private_key_str.as_str(), + public_key_str.as_str(), + outfile, + ); }, None => { - println!("{}", out_address); + let pem_content = + generate_pem_content(&address, private_key_str.as_str(), public_key_str.as_str()); + print!("{}", pem_content); }, } } -fn new(new_args: &WalletNewArgs) { - let format = new_args.wallet_format.as_ref(); - let outfile = new_args.outfile.as_ref(); - let mnemonic = Wallet::generate_mnemonic(); - println!("Mnemonic: {}", mnemonic); +fn bech32_conversion(bech32_args: &WalletBech32Args) { + let encode_address = bech32_args.hex_address.as_ref(); + let decode_address = bech32_args.bech32_address.as_ref(); + + match (encode_address, decode_address) { + (Some(hex), None) => { + let bytes_from_hex = hex::decode(hex).unwrap(); + let bytes_arr: [u8; 32] = bytes_from_hex.try_into().unwrap(); + let addr = types::Address::from(&bytes_arr); + let bech32_addr = Bech32Address::from(addr).to_bech32_str().to_string(); + println!("{}", bech32_addr); + }, + (None, Some(bech32)) => { + let hex_addr = Bech32Address::from_bech32_string(bech32.to_string()).to_hex(); + println!("{}", hex_addr); + }, + (Some(_), Some(_)) => { + println!("error: only one of --encode or --decode can be used in the same command"); + }, + _ => {}, + } +} + +fn get_wallet_keys(mnemonic: Mnemonic) -> (String, String) { let private_key = Wallet::get_private_key_from_mnemonic(mnemonic, 0u32, 0u32); let public_key = PublicKey::from(&private_key); let public_key_str: &str = &public_key.to_string(); let private_key_str: &str = &private_key.to_string(); - let wallet = Wallet::from_private_key(private_key_str).unwrap(); - let address = wallet.address(); + (private_key_str.to_string(), public_key_str.to_string()) +} + +fn get_wallet_address(private_key: &str) -> Address { + let wallet = Wallet::from_private_key(private_key).unwrap(); + wallet.address() +} + +fn new(new_args: &WalletNewArgs) { + let format = new_args.wallet_format.as_ref(); + let outfile = new_args.outfile.as_ref(); + let mnemonic = Wallet::generate_mnemonic(); + println!("Mnemonic: {}", mnemonic); + + let (private_key_str, public_key_str) = get_wallet_keys(mnemonic); + let address = get_wallet_address(private_key_str.as_str()); println!("Wallet address: {}", address); if let Some(f) = format { match (f.as_str(), outfile) { ("pem", Some(file)) => { - generate_pem(&address, private_key_str, public_key_str, file); + generate_pem( + &address, + private_key_str.as_str(), + public_key_str.as_str(), + file, + ); }, ("pem", None) => { println!("Output file is required for PEM format"); @@ -102,8 +135,14 @@ fn new(new_args: &WalletNewArgs) { } fn generate_pem(address: &Address, private_key: &str, public_key: &str, outfile: &String) { + let pem_content = generate_pem_content(address, private_key, public_key); + let mut file = File::create(outfile).unwrap(); + file.write_all(pem_content.as_bytes()).unwrap() +} + +fn generate_pem_content(address: &Address, private_key: &str, public_key: &str) -> String { let concat_keys = format!("{}{}", private_key, public_key); - let concat_keys_b64 = base64::encode(concat_keys); + let concat_keys_b64 = base64_encode(concat_keys); // Split the base64 string into 64-character lines let formatted_key = concat_keys_b64 @@ -120,6 +159,5 @@ fn generate_pem(address: &Address, private_key: &str, public_key: &str, outfile: address.to_bech32_string().unwrap() ); - let mut file = File::create(outfile).unwrap(); - file.write_all(pem_content.as_bytes()).unwrap() + pem_content } From eba0141dee9f708136bf2560255decb736be56b4 Mon Sep 17 00:00:00 2001 From: Andrei Vasilescu Date: Tue, 13 Aug 2024 17:50:45 +0300 Subject: [PATCH 09/92] deleted unnecessary dependency --- framework/meta/Cargo.toml | 4 ---- framework/meta/src/cmd/wallet.rs | 4 ++-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/framework/meta/Cargo.toml b/framework/meta/Cargo.toml index 63625c1746..fba796a3d0 100644 --- a/framework/meta/Cargo.toml +++ b/framework/meta/Cargo.toml @@ -53,7 +53,3 @@ features = ["alloc", "num-bigint"] [dependencies.multiversx-sc-snippets] version = "=0.52.3" path = "../snippets" - -[dependencies.multiversx-sdk] -version = "=0.5.0" -path = "../../sdk/core" diff --git a/framework/meta/src/cmd/wallet.rs b/framework/meta/src/cmd/wallet.rs index 7ed5ea58bb..7fcf28899a 100644 --- a/framework/meta/src/cmd/wallet.rs +++ b/framework/meta/src/cmd/wallet.rs @@ -7,10 +7,10 @@ use std::{ use crate::cli::{WalletAction, WalletArgs, WalletBech32Args, WalletConvertArgs, WalletNewArgs}; use bip39::Mnemonic; -use multiversx_sc_snippets::{hex, imports::Bech32Address}; -use multiversx_sdk::{ +use multiversx_sc_snippets::sdk::{ crypto::public_key::PublicKey, data::address::Address, utils::base64_encode, wallet::Wallet, }; +use multiversx_sc_snippets::{hex, imports::Bech32Address}; pub fn wallet(args: &WalletArgs) { let command = &args.command; match command { From a483001be5dc472771410353520663b01d2acc67 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Tue, 13 Aug 2024 18:46:24 +0300 Subject: [PATCH 10/92] unified syntax - whitebox fix --- .../adder/tests/adder_whitebox_test.rs | 10 ++-- .../facade/world_tx/scenario_tx_whitebox.rs | 53 +++++++++++++++---- 2 files changed, 48 insertions(+), 15 deletions(-) diff --git a/contracts/examples/adder/tests/adder_whitebox_test.rs b/contracts/examples/adder/tests/adder_whitebox_test.rs index 726e1ab18a..407f19440f 100644 --- a/contracts/examples/adder/tests/adder_whitebox_test.rs +++ b/contracts/examples/adder/tests/adder_whitebox_test.rs @@ -57,26 +57,24 @@ fn adder_whitebox_unified() { world.account(OWNER).nonce(1); - let _new_address = world + let new_address = world .tx() .from(OWNER) .raw_deploy() .code(CODE_PATH) .new_address(ADDER_ADDRESS) - .with_result(ExpectError(0, "ok")) .returns(ReturnsNewBech32Address) .whitebox(adder::contract_obj::(), |sc| { - sc.init(BigUint::from(5u64)); + sc.init(BigUint::from(3u64)); }); - assert_eq!(_new_address, ADDER_ADDRESS.to_address().into()); + assert_eq!(new_address, ADDER_ADDRESS.to_address().into()); world .tx() .from(OWNER) .to(ADDER_ADDRESS) .raw_call("") - .returns(ExpectError(0u64, "ok")) .whitebox(adder::contract_obj::(), |sc| { sc.add(BigUint::from(5u64)); }); @@ -88,6 +86,6 @@ fn adder_whitebox_unified() { .returns(ReturnsRawResult) .whitebox(adder::contract_obj::(), |sc| { let sum = sc.sum().get(); - assert_eq!(sum, BigUint::from(10u64)); + assert_eq!(sum, BigUint::from(8u64)); }); } diff --git a/framework/scenario/src/facade/world_tx/scenario_tx_whitebox.rs b/framework/scenario/src/facade/world_tx/scenario_tx_whitebox.rs index 0d9040a2ee..406e109266 100644 --- a/framework/scenario/src/facade/world_tx/scenario_tx_whitebox.rs +++ b/framework/scenario/src/facade/world_tx/scenario_tx_whitebox.rs @@ -1,8 +1,10 @@ +use crate::debug_executor::contract_instance_wrapped_execution; use crate::scenario::tx_to_step::TxToQueryStep; use crate::ScenarioEnvQuery; use crate::{ imports::StaticApi, scenario::tx_to_step::TxToStep, scenario_model::TxResponse, ScenarioEnvExec, }; +use multiversx_chain_vm::tx_mock::TxFunctionName; use multiversx_sc::{ tuple_util::NestedTupleFlatten, types::{ @@ -44,14 +46,22 @@ where contract_obj: ContractObj, f: F, ) -> Self::Returns { - let step_wrapper = self.tx_to_step(); - let (_new_addr, _tx_result) = step_wrapper + let mut step_wrapper = self.tx_to_step(); + let (new_address, tx_result) = step_wrapper .env .world .get_mut_debugger_backend() .vm_runner - .perform_sc_deploy_lambda(&step_wrapper.step, || f(contract_obj)); + .perform_sc_deploy_lambda(&step_wrapper.step, || { + contract_instance_wrapped_execution(true, || { + f(contract_obj); + Ok(()) + }); + }); + let mut response = TxResponse::from_tx_result(tx_result); + response.new_deployed_address = Some(new_address); + step_wrapper.step.save_response(response); step_wrapper.process_result() } } @@ -72,14 +82,27 @@ where contract_obj: ContractObj, f: F, ) -> Self::Returns { - let step_wrapper = self.tx_to_step(); - let _tx_result = step_wrapper + let mut step_wrapper = self.tx_to_step(); + + // no endpoint is called per se, but if it is empty, the VM thinks it is a simple transfer of value + if step_wrapper.step.tx.function.is_empty() { + step_wrapper.step.tx.function = TxFunctionName::WHITEBOX_CALL.to_string(); + } + + let tx_result = step_wrapper .env .world .get_mut_debugger_backend() .vm_runner - .perform_sc_call_lambda(&step_wrapper.step, || f(contract_obj)); + .perform_sc_call_lambda(&step_wrapper.step, || { + contract_instance_wrapped_execution(true, || { + f(contract_obj); + Ok(()) + }); + }); + let response = TxResponse::from_tx_result(tx_result); + step_wrapper.step.save_response(response); step_wrapper.process_result() } } @@ -99,15 +122,27 @@ where contract_obj: ContractObj, f: F, ) -> Self::Returns { - let step_wrapper = self.tx_to_query_step(); + let mut step_wrapper = self.tx_to_query_step(); + + // no endpoint is called per se, but if it is empty, the VM thinks it is a simple transfer of value + if step_wrapper.step.tx.function.is_empty() { + step_wrapper.step.tx.function = TxFunctionName::WHITEBOX_CALL.to_string(); + } - let _tx_result = step_wrapper + let tx_result = step_wrapper .env .world .get_mut_debugger_backend() .vm_runner - .perform_sc_query_lambda(&step_wrapper.step, || f(contract_obj)); + .perform_sc_query_lambda(&step_wrapper.step, || { + contract_instance_wrapped_execution(true, || { + f(contract_obj); + Ok(()) + }); + }); + let response = TxResponse::from_tx_result(tx_result); + step_wrapper.step.save_response(response); step_wrapper.process_result() } } From 9f922b899f5c8221517b57e0e656c9e74295f5c9 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Tue, 13 Aug 2024 19:59:54 +0300 Subject: [PATCH 11/92] unified syntax - whitebox contract_obj cleanup --- .../adder/tests/adder_whitebox_test.rs | 6 +-- .../facade/world_tx/scenario_tx_whitebox.rs | 48 +++++++++++++------ 2 files changed, 36 insertions(+), 18 deletions(-) diff --git a/contracts/examples/adder/tests/adder_whitebox_test.rs b/contracts/examples/adder/tests/adder_whitebox_test.rs index 407f19440f..ee93c7d94b 100644 --- a/contracts/examples/adder/tests/adder_whitebox_test.rs +++ b/contracts/examples/adder/tests/adder_whitebox_test.rs @@ -64,7 +64,7 @@ fn adder_whitebox_unified() { .code(CODE_PATH) .new_address(ADDER_ADDRESS) .returns(ReturnsNewBech32Address) - .whitebox(adder::contract_obj::(), |sc| { + .whitebox(adder::contract_obj, |sc| { sc.init(BigUint::from(3u64)); }); @@ -75,7 +75,7 @@ fn adder_whitebox_unified() { .from(OWNER) .to(ADDER_ADDRESS) .raw_call("") - .whitebox(adder::contract_obj::(), |sc| { + .whitebox(adder::contract_obj, |sc| { sc.add(BigUint::from(5u64)); }); @@ -84,7 +84,7 @@ fn adder_whitebox_unified() { .to(ADDER_ADDRESS) .raw_call("") .returns(ReturnsRawResult) - .whitebox(adder::contract_obj::(), |sc| { + .whitebox(adder::contract_obj, |sc| { let sum = sc.sum().get(); assert_eq!(sum, BigUint::from(8u64)); }); diff --git a/framework/scenario/src/facade/world_tx/scenario_tx_whitebox.rs b/framework/scenario/src/facade/world_tx/scenario_tx_whitebox.rs index 406e109266..503cfa1d9c 100644 --- a/framework/scenario/src/facade/world_tx/scenario_tx_whitebox.rs +++ b/framework/scenario/src/facade/world_tx/scenario_tx_whitebox.rs @@ -1,10 +1,11 @@ use crate::debug_executor::contract_instance_wrapped_execution; use crate::scenario::tx_to_step::TxToQueryStep; -use crate::ScenarioEnvQuery; use crate::{ imports::StaticApi, scenario::tx_to_step::TxToStep, scenario_model::TxResponse, ScenarioEnvExec, }; +use crate::{DebugApi, ScenarioEnvQuery}; use multiversx_chain_vm::tx_mock::TxFunctionName; +use multiversx_sc::contract_base::ContractBase; use multiversx_sc::{ tuple_util::NestedTupleFlatten, types::{ @@ -15,11 +16,10 @@ use multiversx_sc::{ pub trait ScenarioTxWhitebox { type Returns; - fn whitebox( - self, - contract_obj: ContractObj, - f: F, - ) -> Self::Returns; + fn whitebox(self, contract_obj: fn() -> ContractObj, f: F) -> Self::Returns + where + ContractObj: ContractBase + 'static, + F: FnOnce(ContractObj); } impl<'w, From, Payment, CodeValue, RH> ScenarioTxWhitebox @@ -41,11 +41,17 @@ where { type Returns = ::Unpacked; - fn whitebox( + fn whitebox( self, - contract_obj: ContractObj, + contract_obj_builder: fn() -> ContractObj, f: F, - ) -> Self::Returns { + ) -> Self::Returns + where + ContractObj: ContractBase + 'static, + F: FnOnce(ContractObj), + { + let contract_obj = contract_obj_builder(); + let mut step_wrapper = self.tx_to_step(); let (new_address, tx_result) = step_wrapper .env @@ -77,11 +83,17 @@ where { type Returns = ::Unpacked; - fn whitebox( + fn whitebox( self, - contract_obj: ContractObj, + contract_obj_builder: fn() -> ContractObj, f: F, - ) -> Self::Returns { + ) -> Self::Returns + where + ContractObj: ContractBase + 'static, + F: FnOnce(ContractObj), + { + let contract_obj = contract_obj_builder(); + let mut step_wrapper = self.tx_to_step(); // no endpoint is called per se, but if it is empty, the VM thinks it is a simple transfer of value @@ -117,11 +129,17 @@ where { type Returns = ::Unpacked; - fn whitebox( + fn whitebox( self, - contract_obj: ContractObj, + contract_obj_builder: fn() -> ContractObj, f: F, - ) -> Self::Returns { + ) -> Self::Returns + where + ContractObj: ContractBase + 'static, + F: FnOnce(ContractObj), + { + let contract_obj = contract_obj_builder(); + let mut step_wrapper = self.tx_to_query_step(); // no endpoint is called per se, but if it is empty, the VM thinks it is a simple transfer of value From b9dd460f5704fc1faeb4bc0d45bbb20e9a4810d4 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Sun, 18 Aug 2024 23:40:15 +0300 Subject: [PATCH 12/92] unified syntax - whitebox impl for empty data --- .../adder/tests/adder_whitebox_test.rs | 2 - .../facade/world_tx/scenario_tx_whitebox.rs | 51 +++++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/contracts/examples/adder/tests/adder_whitebox_test.rs b/contracts/examples/adder/tests/adder_whitebox_test.rs index ee93c7d94b..215f1647d2 100644 --- a/contracts/examples/adder/tests/adder_whitebox_test.rs +++ b/contracts/examples/adder/tests/adder_whitebox_test.rs @@ -74,7 +74,6 @@ fn adder_whitebox_unified() { .tx() .from(OWNER) .to(ADDER_ADDRESS) - .raw_call("") .whitebox(adder::contract_obj, |sc| { sc.add(BigUint::from(5u64)); }); @@ -82,7 +81,6 @@ fn adder_whitebox_unified() { let _raw_response = world .query() .to(ADDER_ADDRESS) - .raw_call("") .returns(ReturnsRawResult) .whitebox(adder::contract_obj, |sc| { let sum = sc.sum().get(); diff --git a/framework/scenario/src/facade/world_tx/scenario_tx_whitebox.rs b/framework/scenario/src/facade/world_tx/scenario_tx_whitebox.rs index 503cfa1d9c..62842a6e25 100644 --- a/framework/scenario/src/facade/world_tx/scenario_tx_whitebox.rs +++ b/framework/scenario/src/facade/world_tx/scenario_tx_whitebox.rs @@ -16,6 +16,8 @@ use multiversx_sc::{ pub trait ScenarioTxWhitebox { type Returns; + + /// Runs a lambda function in the name of a smart contract, with the configured transaction context. fn whitebox(self, contract_obj: fn() -> ContractObj, f: F) -> Self::Returns where ContractObj: ContractBase + 'static, @@ -72,6 +74,31 @@ where } } +impl<'w, From, To, Payment, RH> ScenarioTxWhitebox + for Tx, From, To, Payment, (), (), RH> +where + From: TxFromSpecified>, + To: TxToSpecified>, + Payment: TxPayment>, + RH: RHListExec>, + RH::ListReturns: NestedTupleFlatten, +{ + type Returns = ::Unpacked; + + fn whitebox( + self, + contract_obj_builder: fn() -> ContractObj, + f: F, + ) -> Self::Returns + where + ContractObj: ContractBase + 'static, + F: FnOnce(ContractObj), + { + self.raw_call(TxFunctionName::WHITEBOX_CALL.as_str()) + .whitebox(contract_obj_builder, f) + } +} + impl<'w, From, To, Payment, RH> ScenarioTxWhitebox for Tx, From, To, Payment, (), FunctionCall, RH> where @@ -119,6 +146,30 @@ where } } +impl<'w, To, Payment, RH> ScenarioTxWhitebox + for Tx, (), To, Payment, (), (), RH> +where + To: TxToSpecified>, + Payment: TxNoPayment>, + RH: RHListExec>, + RH::ListReturns: NestedTupleFlatten, +{ + type Returns = ::Unpacked; + + fn whitebox( + self, + contract_obj_builder: fn() -> ContractObj, + f: F, + ) -> Self::Returns + where + ContractObj: ContractBase + 'static, + F: FnOnce(ContractObj), + { + self.raw_call(TxFunctionName::WHITEBOX_CALL.as_str()) + .whitebox(contract_obj_builder, f) + } +} + impl<'w, To, Payment, RH> ScenarioTxWhitebox for Tx, (), To, Payment, (), FunctionCall, RH> where From bcc1b2016f98797584810e020a70d2500126c3b1 Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Mon, 19 Aug 2024 12:24:31 +0200 Subject: [PATCH 13/92] fetch transaction status from the process-status endpoint --- sdk/core/src/gateway/gateway_tx.rs | 19 +++++++++++++++++++ sdk/core/src/gateway/gateway_tx_retrieve.rs | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/sdk/core/src/gateway/gateway_tx.rs b/sdk/core/src/gateway/gateway_tx.rs index 47aa8b5a83..21312624ff 100644 --- a/sdk/core/src/gateway/gateway_tx.rs +++ b/sdk/core/src/gateway/gateway_tx.rs @@ -96,6 +96,25 @@ impl GatewayProxy { } } + // get_transaction_process_status retrieves a transaction's status from the network using process-status API + pub async fn get_transaction_process_status(&self, hash: &str) -> Result { + let endpoint = format!("transaction/{hash}/process-status"); + let endpoint = self.get_endpoint(endpoint.as_str()); + + let resp = self + .client + .get(endpoint) + .send() + .await? + .json::() + .await?; + + match resp.data { + None => Err(anyhow!("{}", resp.error)), + Some(b) => Ok(b.status), + } + } + // get_default_transaction_arguments will prepare the transaction creation argument by querying the account's info pub async fn get_default_transaction_arguments( &self, diff --git a/sdk/core/src/gateway/gateway_tx_retrieve.rs b/sdk/core/src/gateway/gateway_tx_retrieve.rs index 821713f972..4d781b6118 100644 --- a/sdk/core/src/gateway/gateway_tx_retrieve.rs +++ b/sdk/core/src/gateway/gateway_tx_retrieve.rs @@ -16,7 +16,7 @@ impl GatewayProxy { let start_time = Instant::now(); loop { - match self.get_transaction_status(&tx_hash).await { + match self.get_transaction_process_status(&tx_hash).await { Ok(status) => { // checks if transaction status is final match status.as_str() { From 43a99d8c92286b2e3cfd04fafecf8131b2297005 Mon Sep 17 00:00:00 2001 From: Andrei Vasilescu Date: Wed, 14 Aug 2024 20:19:29 +0300 Subject: [PATCH 14/92] keystore signing done --- Cargo.lock | 100 +++++++++++++++++++++++++++---- sdk/core/Cargo.toml | 3 + sdk/core/src/data/keystore.rs | 35 +++++++++++ sdk/core/src/data/mod.rs | 1 + sdk/core/src/wallet.rs | 110 ++++++++++++++++++++++++++++++++-- 5 files changed, 231 insertions(+), 18 deletions(-) create mode 100644 sdk/core/src/data/keystore.rs diff --git a/Cargo.lock b/Cargo.lock index 08f2acc6ae..f0558fc8b1 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -60,6 +60,17 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + [[package]] name = "ahash" version = "0.8.11" @@ -197,15 +208,15 @@ dependencies = [ [[package]] name = "base64" -version = "0.13.1" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] -name = "base64" -version = "0.22.1" +name = "base64ct" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "basic-features" @@ -435,6 +446,16 @@ dependencies = [ "multiversx-sc-meta-lib", ] +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + [[package]] name = "clap" version = "4.5.11" @@ -670,6 +691,15 @@ dependencies = [ "multiversx-sc-meta-lib", ] +[[package]] +name = "ctr" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +dependencies = [ + "cipher", +] + [[package]] name = "curve25519-dalek" version = "3.2.0" @@ -1527,6 +1557,15 @@ dependencies = [ "serde", ] +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", +] + [[package]] name = "interact" version = "0.0.0" @@ -1994,7 +2033,7 @@ dependencies = [ name = "multiversx-sc-meta" version = "0.52.3" dependencies = [ - "base64 0.13.1", + "bip39", "clap", "colored", "common-path", @@ -2003,7 +2042,6 @@ dependencies = [ "multiversx-sc", "multiversx-sc-meta-lib", "multiversx-sc-snippets", - "multiversx-sdk", "pathdiff", "reqwest", "ruplacer", @@ -2045,7 +2083,7 @@ dependencies = [ name = "multiversx-sc-scenario" version = "0.52.3" dependencies = [ - "base64 0.22.1", + "base64", "bech32", "colored", "hex", @@ -2069,7 +2107,7 @@ dependencies = [ name = "multiversx-sc-snippets" version = "0.52.3" dependencies = [ - "base64 0.22.1", + "base64", "env_logger", "futures", "hex", @@ -2092,10 +2130,12 @@ dependencies = [ name = "multiversx-sdk" version = "0.5.0" dependencies = [ + "aes", "anyhow", - "base64 0.22.1", + "base64", "bech32", "bip39", + "ctr", "hex", "hmac", "itertools", @@ -2104,6 +2144,7 @@ dependencies = [ "pem", "rand 0.8.5", "reqwest", + "scrypt", "serde", "serde_json", "serde_repr", @@ -2390,6 +2431,17 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "password-hash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" +dependencies = [ + "base64ct", + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "pathdiff" version = "0.2.1" @@ -2423,6 +2475,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" dependencies = [ "digest 0.10.7", + "hmac", ] [[package]] @@ -2431,7 +2484,7 @@ version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae" dependencies = [ - "base64 0.22.1", + "base64", "serde", ] @@ -2763,7 +2816,7 @@ version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" dependencies = [ - "base64 0.22.1", + "base64", "bytes", "encoding_rs", "futures-channel", @@ -2933,7 +2986,7 @@ version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" dependencies = [ - "base64 0.22.1", + "base64", "rustls-pki-types", ] @@ -2960,6 +3013,15 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +[[package]] +name = "salsa20" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" +dependencies = [ + "cipher", +] + [[package]] name = "same-file" version = "1.0.6" @@ -3000,6 +3062,18 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "scrypt" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1f" +dependencies = [ + "password-hash", + "pbkdf2", + "salsa20", + "sha2 0.10.8", +] + [[package]] name = "second-contract" version = "0.0.0" diff --git a/sdk/core/Cargo.toml b/sdk/core/Cargo.toml index 463b4ce130..32e170618f 100644 --- a/sdk/core/Cargo.toml +++ b/sdk/core/Cargo.toml @@ -35,3 +35,6 @@ bech32 = "0.9" itertools = "0.13.0" pem = "3.0.2" log = "0.4.17" +scrypt = "0.11" +aes = "0.8" +ctr = "0.9.2" \ No newline at end of file diff --git a/sdk/core/src/data/keystore.rs b/sdk/core/src/data/keystore.rs new file mode 100644 index 0000000000..fd3a618ce7 --- /dev/null +++ b/sdk/core/src/data/keystore.rs @@ -0,0 +1,35 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize)] +pub struct CryptoParams { + pub iv: String, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct KdfParams { + pub dklen: u32, + pub salt: String, + pub n: u32, + pub r: u32, + pub p: u32, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct Crypto { + pub ciphertext: String, + pub cipherparams: CryptoParams, + pub cipher: String, + pub kdf: String, + pub kdfparams: KdfParams, + pub mac: String, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct Keystore { + pub version: u32, + pub kind: String, + pub id: String, + pub address: String, + pub bech32: String, + pub crypto: Crypto, +} \ No newline at end of file diff --git a/sdk/core/src/data/mod.rs b/sdk/core/src/data/mod.rs index 797ec6e1ce..9a270211df 100644 --- a/sdk/core/src/data/mod.rs +++ b/sdk/core/src/data/mod.rs @@ -3,6 +3,7 @@ pub mod account_storage; pub mod address; pub mod esdt; pub mod hyperblock; +pub mod keystore; pub mod network_config; pub mod network_economics; pub mod network_status; diff --git a/sdk/core/src/wallet.rs b/sdk/core/src/wallet.rs index ab1b0a2f37..0519c0413d 100644 --- a/sdk/core/src/wallet.rs +++ b/sdk/core/src/wallet.rs @@ -1,11 +1,19 @@ extern crate rand; +use std::{ + fs::{self}, + io::{self, Read}, +}; + +use aes::{cipher::KeyIvInit, Aes128}; use anyhow::Result; use bip39::{Language, Mnemonic}; +use ctr::{cipher::StreamCipher, Ctr128BE}; use hmac::{Hmac, Mac}; use pbkdf2::pbkdf2; +use scrypt::{scrypt, Params}; use serde_json::json; -use sha2::{Digest, Sha512}; +use sha2::{Digest, Sha256, Sha512}; use sha3::Keccak256; use zeroize::Zeroize; @@ -14,19 +22,36 @@ use crate::{ private_key::{PrivateKey, PRIVATE_KEY_LENGTH}, public_key::PublicKey, }, - data::{address::Address, transaction::Transaction}, + data::{address::Address, keystore::Keystore, transaction::Transaction}, }; const EGLD_COIN_TYPE: u32 = 508; const HARDENED: u32 = 0x80000000; +const CIPHER_ALGORITHM_AES_128_CTR: &str = "aes-128-ctr"; +const KDF_SCRYPT: &str = "scrypt"; -type HmacSha521 = Hmac; +type HmacSha512 = Hmac; +type HmacSha256 = Hmac; #[derive(Copy, Clone, Debug)] pub struct Wallet { priv_key: PrivateKey, } +#[derive(Clone, Debug)] +pub struct DecryptionParams { + pub derived_key_first_half: Vec, + pub iv: Vec, + pub ciphertext: Vec, +} + +#[derive(Debug)] +pub enum WalletError { + InvalidPassword, + InvalidKdf, + InvalidCipher, +} + impl Wallet { // GenerateMnemonic will generate a new mnemonic value using the bip39 implementation pub fn generate_mnemonic() -> Mnemonic { @@ -63,7 +88,7 @@ impl Wallet { let hardened_child_padding: u8 = 0; let mut digest = - HmacSha521::new_from_slice(b"ed25519 seed").expect("HMAC can take key of any size"); + HmacSha512::new_from_slice(b"ed25519 seed").expect("HMAC can take key of any size"); digest.update(&seed); let intermediary: Vec = digest.finalize().into_bytes().into_iter().collect(); let mut key = intermediary[..serialized_key_len].to_vec(); @@ -83,7 +108,7 @@ impl Wallet { buff.push(child_idx as u8); digest = - HmacSha521::new_from_slice(&chain_code).expect("HMAC can take key of any size"); + HmacSha512::new_from_slice(&chain_code).expect("HMAC can take key of any size"); digest.update(&buff); let intermediary: Vec = digest.finalize().into_bytes().into_iter().collect(); key = intermediary[..serialized_key_len].to_vec(); @@ -111,6 +136,15 @@ impl Wallet { Ok(Self { priv_key: pri_key }) } + pub fn from_keystore_secret(file_path: &str) -> Result { + let decyption_params = Self::validate_keystore_password(file_path).unwrap_or_else(|e| { + panic!("Error: {:?}", e); + }); + let priv_key = + PrivateKey::from_hex_str(Self::decrypt_secret_key(decyption_params).as_str())?; + Ok(Self { priv_key }) + } + pub fn address(&self) -> Address { let public_key = PublicKey::from(&self.priv_key); Address::from(&public_key) @@ -131,4 +165,70 @@ impl Wallet { self.priv_key.sign(tx_bytes) } + + pub fn validate_keystore_password(path: &str) -> Result { + println!( + "Insert password. Press 'Ctrl-D' (Linux / MacOS) or 'Ctrl-Z' (Windows) when done." + ); + let mut password = String::new(); + io::stdin().read_to_string(&mut password).unwrap(); + password = password.trim().to_string(); + + let json_body = fs::read_to_string(path).unwrap(); + let keystore: Keystore = serde_json::from_str(&json_body).unwrap(); + let ciphertext = hex::decode(&keystore.crypto.ciphertext).unwrap(); + + let cipher = &keystore.crypto.cipher; + if cipher != CIPHER_ALGORITHM_AES_128_CTR { + return Err(WalletError::InvalidCipher); + } + + let iv = hex::decode(&keystore.crypto.cipherparams.iv).unwrap(); + let salt = hex::decode(&keystore.crypto.kdfparams.salt).unwrap(); + let json_mac = hex::decode(&keystore.crypto.mac).unwrap(); + + let kdf = &keystore.crypto.kdf; + if kdf != KDF_SCRYPT { + return Err(WalletError::InvalidKdf); + } + let n = keystore.crypto.kdfparams.n as f64; + let r = keystore.crypto.kdfparams.r as u64; + let p = keystore.crypto.kdfparams.p as u64; + let dklen = keystore.crypto.kdfparams.dklen as usize; + + let params = Params::new(n.log2() as u8, r as u32, p as u32, dklen).unwrap(); + + let mut derived_key = vec![0u8; 32]; + scrypt(password.as_bytes(), &salt, ¶ms, &mut derived_key).unwrap(); + + let derived_key_first_half = derived_key[0..16].to_vec(); + let derived_key_second_half = derived_key[16..32].to_vec(); + + let mut input_mac = HmacSha256::new_from_slice(&derived_key_second_half).unwrap(); + input_mac.update(&ciphertext); + let computed_mac = input_mac.finalize().into_bytes(); + + if computed_mac.as_slice() == json_mac.as_slice() { + println!("Password is correct"); + Ok(DecryptionParams { + derived_key_first_half, + iv, + ciphertext, + }) + } else { + println!("Password is incorrect"); + Err(WalletError::InvalidPassword) + } + } + + pub fn decrypt_secret_key(decryption_params: DecryptionParams) -> String { + let mut cipher = Ctr128BE::::new( + decryption_params.derived_key_first_half.as_slice().into(), + decryption_params.iv.as_slice().into(), + ); + let mut decrypted = decryption_params.ciphertext.to_vec(); + cipher.apply_keystream(&mut decrypted); + + hex::encode(decrypted).to_string() + } } From 695f622fc4b3aaab4f3d66964ec51ce5d942dd46 Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Mon, 19 Aug 2024 20:32:53 +0200 Subject: [PATCH 15/92] whitebox migration to unified for adder, scenario tester and staking module --- .../adder/tests/adder_whitebox_test.rs | 39 -- .../scenario-tester/tests/st_whitebox_test.rs | 64 +- .../tests/staking_module_whitebox_test.rs | 659 ++++++++---------- 3 files changed, 321 insertions(+), 441 deletions(-) diff --git a/contracts/examples/adder/tests/adder_whitebox_test.rs b/contracts/examples/adder/tests/adder_whitebox_test.rs index 215f1647d2..c609b08302 100644 --- a/contracts/examples/adder/tests/adder_whitebox_test.rs +++ b/contracts/examples/adder/tests/adder_whitebox_test.rs @@ -1,7 +1,6 @@ use adder::*; use multiversx_sc_scenario::imports::*; -const ADDER_PATH_EXPR: &str = "mxsc:output/adder.mxsc.json"; const OWNER: TestAddress = TestAddress::new("owner"); const ADDER_ADDRESS: TestSCAddress = TestSCAddress::new("adder"); const CODE_PATH: MxscPath = MxscPath::new("mxsc:output/adder.mxsc.json"); @@ -16,44 +15,6 @@ fn world() -> ScenarioWorld { #[test] fn adder_whitebox() { let mut world = world(); - let adder_whitebox = WhiteboxContract::new("sc:adder", adder::contract_obj); - let adder_code = world.code_expression(ADDER_PATH_EXPR); - - world - .set_state_step( - SetStateStep::new() - .put_account("address:owner", Account::new().nonce(1)) - .new_address("address:owner", 1, "sc:adder"), - ) - .whitebox_deploy( - &adder_whitebox, - ScDeployStep::new().from("address:owner").code(adder_code), - |sc| { - sc.init(5u32.into()); - }, - ) - .whitebox_query(&adder_whitebox, |sc| { - let sum_value = sc.sum(); - assert_eq!(sum_value.get(), 5u32); - }) - .whitebox_call( - &adder_whitebox, - ScCallStep::new().from("address:owner"), - |sc| sc.add(3u32.into()), - ) - .check_state_step( - CheckStateStep::new() - .put_account("address:owner", CheckAccount::new()) - .put_account( - "sc:adder", - CheckAccount::new().check_storage("str:sum", "8"), - ), - ); -} - -#[test] -fn adder_whitebox_unified() { - let mut world = world(); world.account(OWNER).nonce(1); diff --git a/contracts/feature-tests/scenario-tester/tests/st_whitebox_test.rs b/contracts/feature-tests/scenario-tester/tests/st_whitebox_test.rs index a6318b1f7f..61dd6cdc2d 100644 --- a/contracts/feature-tests/scenario-tester/tests/st_whitebox_test.rs +++ b/contracts/feature-tests/scenario-tester/tests/st_whitebox_test.rs @@ -1,7 +1,9 @@ use multiversx_sc_scenario::imports::*; use scenario_tester::*; -const ADDER_PATH_EXPR: &str = "mxsc:output/scenario-tester.mxsc.json"; +const ST_PATH_EXPR: MxscPath = MxscPath::new("mxsc:output/scenario-tester.mxsc.json"); +const OWNER: TestAddress = TestAddress::new("owner"); +const SCENARIO_TESTER: TestSCAddress = TestSCAddress::new("scenario-tester"); fn world() -> ScenarioWorld { let mut blockchain = ScenarioWorld::new(); @@ -16,37 +18,37 @@ fn world() -> ScenarioWorld { #[test] fn st_whitebox() { let mut world = world(); - let st_whitebox = WhiteboxContract::new("sc:adder", scenario_tester::contract_obj); - let st_code = world.code_expression(ADDER_PATH_EXPR); + + world.account(OWNER).nonce(1); + + let new_address = world + .tx() + .from(OWNER) + .raw_deploy() + .code(ST_PATH_EXPR) + .new_address(SCENARIO_TESTER) + .returns(ReturnsNewBech32Address) + .whitebox(scenario_tester::contract_obj, |sc| { + sc.init(BigUint::from(5u64)); + }); + + assert_eq!(new_address.to_address(), SCENARIO_TESTER.to_address()); world - .set_state_step( - SetStateStep::new() - .put_account("address:owner", Account::new().nonce(1)) - .new_address("address:owner", 1, "sc:adder"), - ) - .whitebox_deploy( - &st_whitebox, - ScDeployStep::new().from("address:owner").code(st_code), - |sc| { - sc.init(5u32.into()); - }, - ) - .whitebox_query(&st_whitebox, |sc| { + .query() + .to(SCENARIO_TESTER) + .whitebox(scenario_tester::contract_obj, |sc| { let sum_value = sc.sum(); - assert_eq!(sum_value.get(), 5u32); - }) - .whitebox_call( - &st_whitebox, - ScCallStep::new().from("address:owner"), - |sc| sc.add(3u32.into()), - ) - .check_state_step( - CheckStateStep::new() - .put_account("address:owner", CheckAccount::new()) - .put_account( - "sc:adder", - CheckAccount::new().check_storage("str:sum", "8"), - ), - ); + assert_eq!(sum_value.get(), BigUint::from(5u32)); + }); + + world + .tx() + .from(OWNER) + .to(SCENARIO_TESTER) + .whitebox(scenario_tester::contract_obj, |sc| sc.add(3u32.into())); + + world + .check_account(SCENARIO_TESTER) + .check_storage("str:sum", "8"); } 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 612fa725df..0f705ad131 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,23 +1,23 @@ use multiversx_sc_modules::staking::StakingModule; use multiversx_sc_scenario::imports::*; -const STAKING_TOKEN_ID_EXPR: &str = "str:STAKE-123456"; +const STAKING_TOKEN_ID_EXPR: TestTokenIdentifier = TestTokenIdentifier::new("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 = 3; -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 PAUL_ADDRESS_EXPR: &str = "address:paul"; -const SALLY_ADDRESS_EXPR: &str = "address:sally"; +const OWNER_ADDRESS: TestAddress = TestAddress::new("owner"); +const ALICE_ADDRESS: TestAddress = TestAddress::new("alice"); +const BOB_ADDRESS: TestAddress = TestAddress::new("bob"); +const CAROL_ADDRESS: TestAddress = TestAddress::new("carol"); +const EVE_ADDRESS: TestAddress = TestAddress::new("eve"); +const PAUL_ADDRESS: TestAddress = TestAddress::new("paul"); +const SALLY_ADDRESS: TestAddress = TestAddress::new("sally"); -const USE_MODULE_ADDRESS_EXPR: &str = "sc:use-module"; -const USE_MODULE_PATH_EXPR: &str = "mxsc:output/use-module.mxsc.json"; +const USE_MODULE_ADDRESS: TestSCAddress = TestSCAddress::new("use-module"); +const USE_MODULE_PATH_EXPR: MxscPath = MxscPath::new("mxsc:output/use-module.mxsc.json"); fn world() -> ScenarioWorld { let mut blockchain = ScenarioWorld::new(); @@ -30,447 +30,364 @@ fn world() -> ScenarioWorld { 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, INITIAL_BALANCE), - ) - .put_account( - BOB_ADDRESS_EXPR, - Account::new() - .nonce(1) - .esdt_balance(STAKING_TOKEN_ID_EXPR, INITIAL_BALANCE), - ) - .put_account( - CAROL_ADDRESS_EXPR, - Account::new() - .nonce(1) - .esdt_balance(STAKING_TOKEN_ID_EXPR, INITIAL_BALANCE), - ) - .put_account( - EVE_ADDRESS_EXPR, - Account::new() - .nonce(1) - .esdt_balance(STAKING_TOKEN_ID_EXPR, INITIAL_BALANCE), - ) - .put_account( - PAUL_ADDRESS_EXPR, - Account::new() - .nonce(1) - .esdt_balance(STAKING_TOKEN_ID_EXPR, INITIAL_BALANCE), - ) - .put_account( - SALLY_ADDRESS_EXPR, - Account::new() - .nonce(1) - .esdt_balance(STAKING_TOKEN_ID_EXPR, INITIAL_BALANCE), - ), - ); + world.account(OWNER_ADDRESS).nonce(1); + world + .account(ALICE_ADDRESS) + .nonce(1) + .esdt_balance(STAKING_TOKEN_ID_EXPR, INITIAL_BALANCE); + world + .account(BOB_ADDRESS) + .nonce(1) + .esdt_balance(STAKING_TOKEN_ID_EXPR, INITIAL_BALANCE); + world + .account(CAROL_ADDRESS) + .nonce(1) + .esdt_balance(STAKING_TOKEN_ID_EXPR, INITIAL_BALANCE); + world + .account(EVE_ADDRESS) + .nonce(1) + .esdt_balance(STAKING_TOKEN_ID_EXPR, INITIAL_BALANCE); + world + .account(PAUL_ADDRESS) + .nonce(1) + .esdt_balance(STAKING_TOKEN_ID_EXPR, INITIAL_BALANCE); + world + .account(SALLY_ADDRESS) + .nonce(1) + .esdt_balance(STAKING_TOKEN_ID_EXPR, 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 new_address = world + .tx() + .from(OWNER_ADDRESS) + .raw_deploy() + .code(USE_MODULE_PATH_EXPR) + .new_address(USE_MODULE_ADDRESS) + .returns(ReturnsNewBech32Address) + .whitebox(use_module::contract_obj, |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 - ))); - whitelist.push(managed_address!(&address_expr_to_address( - PAUL_ADDRESS_EXPR - ))); - whitelist.push(managed_address!(&address_expr_to_address( - SALLY_ADDRESS_EXPR - ))); + whitelist.push(ALICE_ADDRESS.to_managed_address()); + whitelist.push(BOB_ADDRESS.to_managed_address()); + whitelist.push(CAROL_ADDRESS.to_managed_address()); + whitelist.push(PAUL_ADDRESS.to_managed_address()); + whitelist.push(SALLY_ADDRESS.to_managed_address()); sc.init_staking_module( - &EgldOrEsdtTokenIdentifier::esdt(managed_token_id!(STAKING_TOKEN_ID)), - &managed_biguint!(REQUIRED_STAKE_AMOUNT), - &managed_biguint!(SLASH_AMOUNT), + &EgldOrEsdtTokenIdentifier::esdt(STAKING_TOKEN_ID), + &BigUint::from(REQUIRED_STAKE_AMOUNT), + &BigUint::from(SLASH_AMOUNT), QUORUM, &whitelist, ); - }, - ); + }); + + assert_eq!(new_address.to_address(), USE_MODULE_ADDRESS.to_address()); // 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, REQUIRED_STAKE_AMOUNT) - .no_expect(), - |sc| sc.stake(), - |r| { - r.assert_user_error("Only whitelisted members can stake"); - }, - ); + world + .tx() + .from(EVE_ADDRESS) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(STAKING_TOKEN_ID_EXPR), + 0, + &BigUint::from(REQUIRED_STAKE_AMOUNT), + ) + .returns(ExpectError(4u64, "Only whitelisted members can stake")) + .whitebox(use_module::contract_obj, |sc| { + sc.stake(); + }); // stake half and try unstake - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new().from(ALICE_ADDRESS_EXPR).esdt_transfer( - STAKING_TOKEN_ID, + world + .tx() + .from(ALICE_ADDRESS) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(STAKING_TOKEN_ID_EXPR), 0, - REQUIRED_STAKE_AMOUNT / 2, - ), - |sc| sc.stake(), - ); + &BigUint::from(REQUIRED_STAKE_AMOUNT / 2), + ) + .whitebox(use_module::contract_obj, |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"); - }, - ); + world + .tx() + .from(ALICE_ADDRESS) + .to(USE_MODULE_ADDRESS) + .returns(ExpectError(4u64, "Not enough stake")) + .whitebox(use_module::contract_obj, |sc| { + sc.unstake(BigUint::from(REQUIRED_STAKE_AMOUNT / 4)); + }); // bob and carol stake - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new().from(BOB_ADDRESS_EXPR).esdt_transfer( - STAKING_TOKEN_ID, + world + .tx() + .from(BOB_ADDRESS) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(STAKING_TOKEN_ID), 0, - REQUIRED_STAKE_AMOUNT, - ), - |sc| sc.stake(), - ); - - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new().from(CAROL_ADDRESS_EXPR).esdt_transfer( - STAKING_TOKEN_ID, + &BigUint::from(REQUIRED_STAKE_AMOUNT), + ) + .whitebox(use_module::contract_obj, |sc| { + sc.stake(); + }); + + world + .tx() + .from(CAROL_ADDRESS) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(STAKING_TOKEN_ID), 0, - REQUIRED_STAKE_AMOUNT, - ), - |sc| sc.stake(), - ); - - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new().from(PAUL_ADDRESS_EXPR).esdt_transfer( - STAKING_TOKEN_ID, + &BigUint::from(REQUIRED_STAKE_AMOUNT), + ) + .whitebox(use_module::contract_obj, |sc| { + sc.stake(); + }); + + world + .tx() + .from(PAUL_ADDRESS) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(STAKING_TOKEN_ID), 0, - REQUIRED_STAKE_AMOUNT, - ), - |sc| sc.stake(), - ); - - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new().from(SALLY_ADDRESS_EXPR).esdt_transfer( - STAKING_TOKEN_ID, + &BigUint::from(REQUIRED_STAKE_AMOUNT), + ) + .whitebox(use_module::contract_obj, |sc| { + sc.stake(); + }); + + world + .tx() + .from(SALLY_ADDRESS) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(STAKING_TOKEN_ID), 0, - REQUIRED_STAKE_AMOUNT, - ), - |sc| sc.stake(), - ); + &BigUint::from(REQUIRED_STAKE_AMOUNT), + ) + .whitebox(use_module::contract_obj, |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"); - }, - ); + world + .tx() + .from(ALICE_ADDRESS) + .to(USE_MODULE_ADDRESS) + .returns(ExpectError(4u64, "Not enough stake")) + .whitebox(use_module::contract_obj, |sc| { + sc.vote_slash_member(BOB_ADDRESS.to_managed_address()); + }); // 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"); - }, - ); + world + .tx() + .from(ALICE_ADDRESS) + .to(USE_MODULE_ADDRESS) + .returns(ExpectError(4u64, "Voted user is not a staked board member")) + .whitebox(use_module::contract_obj, |sc| { + sc.vote_slash_member(EVE_ADDRESS.to_managed_address()); + }); // 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, + world + .tx() + .from(ALICE_ADDRESS) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(STAKING_TOKEN_ID_EXPR), 0, - REQUIRED_STAKE_AMOUNT, - ), - |sc| { + &BigUint::from(REQUIRED_STAKE_AMOUNT), + ) + .whitebox(use_module::contract_obj, |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, "1_000_000"), - )); + let alice_staked_amount = sc.staked_amount(&ALICE_ADDRESS.to_managed_address()).get(); + assert_eq!(alice_staked_amount, BigUint::from(1_500_000u64)); + }); + + world + .tx() + .from(ALICE_ADDRESS) + .to(USE_MODULE_ADDRESS) + .whitebox(use_module::contract_obj, |sc| { + sc.unstake(BigUint::from(500_000u64)); + let alice_staked_amount = sc.staked_amount(&ALICE_ADDRESS.to_managed_address()).get(); + assert_eq!(alice_staked_amount, BigUint::from(1_000_000u64)); + }); + + world + .check_account(ALICE_ADDRESS) + .esdt_balance(STAKING_TOKEN_ID_EXPR, BigUint::from(1_000_000u64)); // 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))); + world + .tx() + .from(ALICE_ADDRESS) + .to(USE_MODULE_ADDRESS) + .whitebox(use_module::contract_obj, |sc| { + sc.vote_slash_member(BOB_ADDRESS.to_managed_address()); assert_eq!( - sc.slashing_proposal_voters(&managed_address!(&address_expr_to_address( - BOB_ADDRESS_EXPR - ))) - .len(), + sc.slashing_proposal_voters(&BOB_ADDRESS.to_managed_address()) + .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 - )))); - }, - ); + .slashing_proposal_voters(&BOB_ADDRESS.to_managed_address()) + .contains(&ALICE_ADDRESS.to_managed_address())); + }); // 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 - ))); - }, - ); + world + .tx() + .from(BOB_ADDRESS) + .to(USE_MODULE_ADDRESS) + .whitebox(use_module::contract_obj, |sc| { + sc.vote_slash_member(ALICE_ADDRESS.to_managed_address()); + }); // 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"); - }, - ); + world + .tx() + .from(BOB_ADDRESS) + .to(USE_MODULE_ADDRESS) + .returns(ExpectError(4u64, "Quorum not reached")) + .whitebox(use_module::contract_obj, |sc| { + sc.slash_member(ALICE_ADDRESS.to_managed_address()); + }); // paul vote to slash alice - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new().from(PAUL_ADDRESS_EXPR), - |sc| { - sc.vote_slash_member(managed_address!(&address_expr_to_address( - ALICE_ADDRESS_EXPR - ))); - }, - ); + world + .tx() + .from(PAUL_ADDRESS) + .to(USE_MODULE_ADDRESS) + .whitebox(use_module::contract_obj, |sc| { + sc.vote_slash_member(ALICE_ADDRESS.to_managed_address()); + }); // sally vote to slash alice - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new().from(SALLY_ADDRESS_EXPR), - |sc| { - sc.vote_slash_member(managed_address!(&address_expr_to_address( - ALICE_ADDRESS_EXPR - ))); - }, - ); + world + .tx() + .from(SALLY_ADDRESS) + .to(USE_MODULE_ADDRESS) + .whitebox(use_module::contract_obj, |sc| { + sc.vote_slash_member(ALICE_ADDRESS.to_managed_address()); + }); // sally cancels vote to slash alice - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new().from(SALLY_ADDRESS_EXPR), - |sc| { - sc.cancel_vote_slash_member(managed_address!(&address_expr_to_address( - ALICE_ADDRESS_EXPR - ))); - }, - ); + world + .tx() + .from(SALLY_ADDRESS) + .to(USE_MODULE_ADDRESS) + .whitebox(use_module::contract_obj, |sc| { + sc.cancel_vote_slash_member(ALICE_ADDRESS.to_managed_address()); + }); // 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 - ))); + world + .tx() + .from(CAROL_ADDRESS) + .to(USE_MODULE_ADDRESS) + .whitebox(use_module::contract_obj, |sc| { + sc.vote_slash_member(ALICE_ADDRESS.to_managed_address()); assert_eq!( - sc.slashing_proposal_voters(&managed_address!(&address_expr_to_address( - ALICE_ADDRESS_EXPR - ))) - .len(), + sc.slashing_proposal_voters(&ALICE_ADDRESS.to_managed_address()) + .len(), 3 ); assert!(sc - .slashing_proposal_voters(&managed_address!(&address_expr_to_address( - ALICE_ADDRESS_EXPR - ))) - .contains(&managed_address!(&address_expr_to_address( - BOB_ADDRESS_EXPR - )))); + .slashing_proposal_voters(&ALICE_ADDRESS.to_managed_address()) + .contains(&BOB_ADDRESS.to_managed_address())); assert!(sc - .slashing_proposal_voters(&managed_address!(&address_expr_to_address( - ALICE_ADDRESS_EXPR - ))) - .contains(&managed_address!(&address_expr_to_address( - CAROL_ADDRESS_EXPR - )))); + .slashing_proposal_voters(&ALICE_ADDRESS.to_managed_address()) + .contains(&CAROL_ADDRESS.to_managed_address())); assert!(sc - .slashing_proposal_voters(&managed_address!(&address_expr_to_address( - ALICE_ADDRESS_EXPR - ))) - .contains(&managed_address!(&address_expr_to_address( - PAUL_ADDRESS_EXPR - )))); + .slashing_proposal_voters(&ALICE_ADDRESS.to_managed_address()) + .contains(&PAUL_ADDRESS.to_managed_address())); assert!(!sc - .slashing_proposal_voters(&managed_address!(&address_expr_to_address( - ALICE_ADDRESS_EXPR - ))) - .contains(&managed_address!(&address_expr_to_address( - SALLY_ADDRESS_EXPR - )))); - }, - ); + .slashing_proposal_voters(&ALICE_ADDRESS.to_managed_address()) + .contains(&SALLY_ADDRESS.to_managed_address())); + }); // 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 - ))); + world + .tx() + .from(BOB_ADDRESS) + .to(USE_MODULE_ADDRESS) + .whitebox(use_module::contract_obj, |sc| { + sc.slash_member(ALICE_ADDRESS.to_managed_address()); 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) + sc.staked_amount(&ALICE_ADDRESS.to_managed_address()).get(), + BigUint::from(REQUIRED_STAKE_AMOUNT - SLASH_AMOUNT) ); + assert_eq!(sc.total_slashed_amount().get(), BigUint::from(SLASH_AMOUNT)); assert!(sc - .slashing_proposal_voters(&managed_address!(&address_expr_to_address( - ALICE_ADDRESS_EXPR - ))) + .slashing_proposal_voters(&ALICE_ADDRESS.to_managed_address()) .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"); - }, - ); + world + .tx() + .from(ALICE_ADDRESS) + .to(USE_MODULE_ADDRESS) + .returns(ExpectError(4u64, "Not enough stake")) + .whitebox(use_module::contract_obj, |sc| { + sc.vote_slash_member(BOB_ADDRESS.to_managed_address()); + }); // 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"); - }, - ); + world + .tx() + .from(ALICE_ADDRESS) + .to(USE_MODULE_ADDRESS) + .returns(ExpectError(4u64, "Not enough stake")) + .whitebox(use_module::contract_obj, |sc| { + sc.unstake(BigUint::from(400_000u64)); + }); // alice remove from board members - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new().from(OWNER_ADDRESS_EXPR), - |sc| { + world + .tx() + .from(OWNER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .whitebox(use_module::contract_obj, |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 - )))); + .slashing_proposal_voters(&BOB_ADDRESS.to_managed_address()) + .contains(&ALICE_ADDRESS.to_managed_address())); - sc.remove_board_member(&managed_address!(&address_expr_to_address( - ALICE_ADDRESS_EXPR - ))); + sc.remove_board_member(&ALICE_ADDRESS.to_managed_address()); assert_eq!(sc.user_whitelist().len(), 4); assert!(!sc .user_whitelist() - .contains(&managed_address!(&address_expr_to_address( - ALICE_ADDRESS_EXPR - )))); + .contains(&ALICE_ADDRESS.to_managed_address())); // alice's vote gets removed assert!(sc - .slashing_proposal_voters(&managed_address!(&address_expr_to_address( - BOB_ADDRESS_EXPR - ))) + .slashing_proposal_voters(&BOB_ADDRESS.to_managed_address()) .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 + .tx() + .from(ALICE_ADDRESS) + .to(USE_MODULE_ADDRESS) + .whitebox(use_module::contract_obj, |sc| { + sc.unstake(BigUint::from(400_000u64)); + }); + + world.check_account(ALICE_ADDRESS).esdt_balance( + TokenIdentifier::from(STAKING_TOKEN_ID_EXPR), + BigUint::from(INITIAL_BALANCE - SLASH_AMOUNT), ); - - world.check_state_step(CheckStateStep::new().put_account( - ALICE_ADDRESS_EXPR, - CheckAccount::new().esdt_balance(STAKING_TOKEN_ID_EXPR, INITIAL_BALANCE - SLASH_AMOUNT), - )); -} - -fn address_expr_to_address(address_expr: &str) -> Address { - AddressValue::from(address_expr).to_address() } From a8f137726086ac070135d01b1e81964deee12455 Mon Sep 17 00:00:00 2001 From: BiancaIalangi Date: Tue, 20 Aug 2024 09:09:06 +0300 Subject: [PATCH 16/92] upgrade blackbox rust_testing_framework_tester --- .../sc-config.toml | 5 ++ .../src/dummy_module.rs | 2 - .../rust-testing-framework-tester/src/lib.rs | 7 +- .../rust_testing_framework_tester_proxy.rs | 61 +++++++++++++ .../tests/tester_blackbox_test.rs | 85 +++++++------------ 5 files changed, 99 insertions(+), 61 deletions(-) create mode 100644 contracts/feature-tests/rust-testing-framework-tester/src/rust_testing_framework_tester_proxy.rs diff --git a/contracts/feature-tests/rust-testing-framework-tester/sc-config.toml b/contracts/feature-tests/rust-testing-framework-tester/sc-config.toml index 330cdda658..b8c5b739dc 100644 --- a/contracts/feature-tests/rust-testing-framework-tester/sc-config.toml +++ b/contracts/feature-tests/rust-testing-framework-tester/sc-config.toml @@ -4,3 +4,8 @@ main = "rust-testing-framework-tester" # the only purpose of this config is to specify the allocator [contracts.rust-testing-framework-tester] allocator = "static64k" + +[[proxy]] +path = "src/rust_testing_framework_tester_proxy.rs" +add-unlabelled = false +add-endpoints = ["init"] diff --git a/contracts/feature-tests/rust-testing-framework-tester/src/dummy_module.rs b/contracts/feature-tests/rust-testing-framework-tester/src/dummy_module.rs index 76721a8fc4..7db5c9379d 100644 --- a/contracts/feature-tests/rust-testing-framework-tester/src/dummy_module.rs +++ b/contracts/feature-tests/rust-testing-framework-tester/src/dummy_module.rs @@ -1,5 +1,3 @@ -multiversx_sc::imports!(); - #[multiversx_sc::module] pub trait DummyModule { fn some_function(&self) -> BigUint { diff --git a/contracts/feature-tests/rust-testing-framework-tester/src/lib.rs b/contracts/feature-tests/rust-testing-framework-tester/src/lib.rs index 4133f3f039..ad3766e123 100644 --- a/contracts/feature-tests/rust-testing-framework-tester/src/lib.rs +++ b/contracts/feature-tests/rust-testing-framework-tester/src/lib.rs @@ -1,11 +1,12 @@ #![no_std] -multiversx_sc::imports!(); -multiversx_sc::derive_imports!(); +use multiversx_sc::proxy_imports::*; pub mod dummy_module; +pub mod rust_testing_framework_tester_proxy; -#[derive(TopEncode, TopDecode, TypeAbi, Clone, Debug, PartialEq, Eq)] +#[type_abi] +#[derive(TopEncode, TopDecode, Clone, Debug, PartialEq, Eq)] pub struct NftDummyAttributes { pub creation_epoch: u64, pub cool_factor: u8, diff --git a/contracts/feature-tests/rust-testing-framework-tester/src/rust_testing_framework_tester_proxy.rs b/contracts/feature-tests/rust-testing-framework-tester/src/rust_testing_framework_tester_proxy.rs new file mode 100644 index 0000000000..6a42d7e5b3 --- /dev/null +++ b/contracts/feature-tests/rust-testing-framework-tester/src/rust_testing_framework_tester_proxy.rs @@ -0,0 +1,61 @@ +// Code generated by the multiversx-sc proxy generator. DO NOT EDIT. + +//////////////////////////////////////////////////// +////////////////// AUTO-GENERATED ////////////////// +//////////////////////////////////////////////////// + +#![allow(dead_code)] +#![allow(clippy::all)] + +use multiversx_sc::proxy_imports::*; + +pub struct RustTestingFrameworkTesterProxy; + +impl TxProxyTrait for RustTestingFrameworkTesterProxy +where + Env: TxEnv, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + type TxProxyMethods = RustTestingFrameworkTesterProxyMethods; + + fn proxy_methods(self, tx: Tx) -> Self::TxProxyMethods { + RustTestingFrameworkTesterProxyMethods { wrapped_tx: tx } + } +} + +pub struct RustTestingFrameworkTesterProxyMethods +where + Env: TxEnv, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + wrapped_tx: Tx, +} + +#[rustfmt::skip] +impl RustTestingFrameworkTesterProxyMethods +where + Env: TxEnv, + Env::Api: VMApi, + From: TxFrom, + Gas: TxGas, +{ + pub fn init( + self, + ) -> TxTypedDeploy> { + self.wrapped_tx + .payment(NotPayable) + .raw_deploy() + .original_result() + } +} + +#[type_abi] +#[derive(TopEncode, TopDecode, Clone, Debug, PartialEq, Eq)] +pub struct NftDummyAttributes { + pub creation_epoch: u64, + pub cool_factor: u8, +} diff --git a/contracts/feature-tests/rust-testing-framework-tester/tests/tester_blackbox_test.rs b/contracts/feature-tests/rust-testing-framework-tester/tests/tester_blackbox_test.rs index afdabb5199..fe4e7f5b77 100644 --- a/contracts/feature-tests/rust-testing-framework-tester/tests/tester_blackbox_test.rs +++ b/contracts/feature-tests/rust-testing-framework-tester/tests/tester_blackbox_test.rs @@ -1,77 +1,50 @@ use multiversx_sc_scenario::imports::*; use rust_testing_framework_tester::*; -const WASM_PATH_EXPR: &str = "mxsc:output/rust-testing-framework-tester.mxsc.json"; +const CODE_PATH: MxscPath = MxscPath::new("output/rust-testing-framework-tester.mxsc.json"); +const OWNER_ADDRESS: TestAddress = TestAddress::new("owner"); +const RUST_TESTING_FRAMEWORK_TESTER_ADDRESS: TestSCAddress = + TestSCAddress::new("rust-testing-framework-tester"); fn world() -> ScenarioWorld { let mut blockchain = ScenarioWorld::new(); - blockchain.register_contract( - WASM_PATH_EXPR, - rust_testing_framework_tester::ContractBuilder, - ); + blockchain.register_contract(CODE_PATH, rust_testing_framework_tester::ContractBuilder); + blockchain } #[test] -#[allow(deprecated)] fn tester_deploy_test() { let mut world = world(); - let code = world.code_expression(WASM_PATH_EXPR); - let owner_address = "address:owner"; - let mut adder_contract = - ContractInfo::>::new("sc:contract"); + world.start_trace(); + + world.account(OWNER_ADDRESS).new_address( + OWNER_ADDRESS, + 0, + RUST_TESTING_FRAMEWORK_TESTER_ADDRESS, + ); - world - .start_trace() - .set_state_step( - SetStateStep::new() - .put_account(owner_address, Account::new()) - .new_address(owner_address, 0, &adder_contract), - ) - .sc_deploy_use_result( - ScDeployStep::new() - .from(owner_address) - .code(code) - .call(adder_contract.init()), - |address, tr: TypedResponse| { - assert_eq!(address, adder_contract.to_address()); - assert_eq!(tr.result.unwrap(), "constructor-result"); - }, - ) - .write_scenario_trace("scenarios/trace-deploy.scen.json"); + let (returned_value, contract_address) = world + .tx() + .from(OWNER_ADDRESS) + .typed(rust_testing_framework_tester_proxy::RustTestingFrameworkTesterProxy) + .init() + .code(CODE_PATH) + .returns(ReturnsResult) + .new_address(RUST_TESTING_FRAMEWORK_TESTER_ADDRESS) + .returns(ReturnsNewAddress) + .run(); + + assert_eq!(returned_value.to_string(), "constructor-result"); + assert_eq!(contract_address, RUST_TESTING_FRAMEWORK_TESTER_ADDRESS); + + world.write_scenario_trace("scenarios/trace-deploy.scen.json"); } #[test] -#[allow(deprecated)] fn tester_deploy_test_spawned_thread() { - let handler = std::thread::spawn(|| { - let mut world = world(); - let code = world.code_expression(WASM_PATH_EXPR); - - let owner_address = "address:owner"; - let mut adder_contract = - ContractInfo::>::new("sc:contract"); - - world - .start_trace() - .set_state_step( - SetStateStep::new() - .put_account(owner_address, Account::new()) - .new_address(owner_address, 0, &adder_contract), - ) - .sc_deploy_use_result( - ScDeployStep::new() - .from(owner_address) - .code(code) - .call(adder_contract.init()), - |address, tr: TypedResponse| { - assert_eq!(address, adder_contract.to_address()); - assert_eq!(tr.result.unwrap(), "constructor-result"); - }, - ) - .write_scenario_trace("scenarios/trace-deploy.scen.json"); - }); + let handler = std::thread::spawn(|| tester_deploy_test()); handler.join().unwrap(); } From 2d508a9e0cba4535b550455bd4d555c040f6be57 Mon Sep 17 00:00:00 2001 From: BiancaIalangi Date: Tue, 20 Aug 2024 10:09:10 +0300 Subject: [PATCH 17/92] fix clippy --- .../rust-testing-framework-tester/tests/tester_blackbox_test.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/feature-tests/rust-testing-framework-tester/tests/tester_blackbox_test.rs b/contracts/feature-tests/rust-testing-framework-tester/tests/tester_blackbox_test.rs index fe4e7f5b77..a426721718 100644 --- a/contracts/feature-tests/rust-testing-framework-tester/tests/tester_blackbox_test.rs +++ b/contracts/feature-tests/rust-testing-framework-tester/tests/tester_blackbox_test.rs @@ -44,7 +44,7 @@ fn tester_deploy_test() { #[test] fn tester_deploy_test_spawned_thread() { - let handler = std::thread::spawn(|| tester_deploy_test()); + let handler = std::thread::spawn(tester_deploy_test); handler.join().unwrap(); } From 0490e8122b385d6b4e6ff8d5b3ed0c60cd711b0f Mon Sep 17 00:00:00 2001 From: Andrei Vasilescu Date: Tue, 20 Aug 2024 10:40:24 +0300 Subject: [PATCH 18/92] password prompt separated --- sdk/core/src/data/keystore.rs | 15 ++++++++++- sdk/core/src/wallet.rs | 47 +++++++++++++++++++++-------------- 2 files changed, 42 insertions(+), 20 deletions(-) diff --git a/sdk/core/src/data/keystore.rs b/sdk/core/src/data/keystore.rs index fd3a618ce7..2564d70a2e 100644 --- a/sdk/core/src/data/keystore.rs +++ b/sdk/core/src/data/keystore.rs @@ -1,5 +1,11 @@ use serde::{Deserialize, Serialize}; +#[derive(Debug)] +pub enum WalletError { + InvalidPassword, + InvalidKdf, + InvalidCipher, +} #[derive(Debug, Serialize, Deserialize)] pub struct CryptoParams { pub iv: String, @@ -32,4 +38,11 @@ pub struct Keystore { pub address: String, pub bech32: String, pub crypto: Crypto, -} \ No newline at end of file +} + +#[derive(Clone, Debug)] +pub struct DecryptionParams { + pub derived_key_first_half: Vec, + pub iv: Vec, + pub ciphertext: Vec, +} diff --git a/sdk/core/src/wallet.rs b/sdk/core/src/wallet.rs index 0519c0413d..b2856b74da 100644 --- a/sdk/core/src/wallet.rs +++ b/sdk/core/src/wallet.rs @@ -22,7 +22,11 @@ use crate::{ private_key::{PrivateKey, PRIVATE_KEY_LENGTH}, public_key::PublicKey, }, - data::{address::Address, keystore::Keystore, transaction::Transaction}, + data::{ + address::Address, + keystore::{DecryptionParams, Keystore, WalletError}, + transaction::Transaction, + }, }; const EGLD_COIN_TYPE: u32 = 508; @@ -38,20 +42,6 @@ pub struct Wallet { priv_key: PrivateKey, } -#[derive(Clone, Debug)] -pub struct DecryptionParams { - pub derived_key_first_half: Vec, - pub iv: Vec, - pub ciphertext: Vec, -} - -#[derive(Debug)] -pub enum WalletError { - InvalidPassword, - InvalidKdf, - InvalidCipher, -} - impl Wallet { // GenerateMnemonic will generate a new mnemonic value using the bip39 implementation pub fn generate_mnemonic() -> Mnemonic { @@ -137,14 +127,27 @@ impl Wallet { } pub fn from_keystore_secret(file_path: &str) -> Result { - let decyption_params = Self::validate_keystore_password(file_path).unwrap_or_else(|e| { - panic!("Error: {:?}", e); - }); + let decyption_params = + Self::validate_keystore_password(file_path, Self::get_keystore_password()) + .unwrap_or_else(|e| { + panic!("Error: {:?}", e); + }); let priv_key = PrivateKey::from_hex_str(Self::decrypt_secret_key(decyption_params).as_str())?; Ok(Self { priv_key }) } + pub fn get_private_key_from_keystore_secret(file_path: &str) -> Result { + let decyption_params = + Self::validate_keystore_password(file_path, Self::get_keystore_password()) + .unwrap_or_else(|e| { + panic!("Error: {:?}", e); + }); + let priv_key = + PrivateKey::from_hex_str(Self::decrypt_secret_key(decyption_params).as_str())?; + Ok(priv_key) + } + pub fn address(&self) -> Address { let public_key = PublicKey::from(&self.priv_key); Address::from(&public_key) @@ -166,14 +169,20 @@ impl Wallet { self.priv_key.sign(tx_bytes) } - pub fn validate_keystore_password(path: &str) -> Result { + fn get_keystore_password() -> String { println!( "Insert password. Press 'Ctrl-D' (Linux / MacOS) or 'Ctrl-Z' (Windows) when done." ); let mut password = String::new(); io::stdin().read_to_string(&mut password).unwrap(); password = password.trim().to_string(); + password + } + pub fn validate_keystore_password( + path: &str, + password: String, + ) -> Result { let json_body = fs::read_to_string(path).unwrap(); let keystore: Keystore = serde_json::from_str(&json_body).unwrap(); let ciphertext = hex::decode(&keystore.crypto.ciphertext).unwrap(); From c1b54c1d8c2b9e9683d84431623e0338d78cdbd8 Mon Sep 17 00:00:00 2001 From: JustEatAnApple Date: Wed, 21 Aug 2024 20:31:47 +0300 Subject: [PATCH 19/92] Keystore <-> Pem Sc-meta --- Cargo.lock | 10 ++ framework/meta/src/cmd/wallet.rs | 147 +++++++++++++++++----------- framework/meta/tests/wallet_test.rs | 91 +++++++++++++++++ sdk/core/Cargo.toml | 3 +- sdk/core/src/data/keystore.rs | 8 +- sdk/core/src/wallet.rs | 137 +++++++++++++++++++++----- 6 files changed, 316 insertions(+), 80 deletions(-) create mode 100644 framework/meta/tests/wallet_test.rs diff --git a/Cargo.lock b/Cargo.lock index f0558fc8b1..fecbf652fe 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -2151,6 +2151,7 @@ dependencies = [ "sha2 0.10.8", "sha3", "tokio", + "uuid", "zeroize", ] @@ -3724,6 +3725,15 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "uuid" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" +dependencies = [ + "getrandom 0.2.15", +] + [[package]] name = "vault" version = "0.0.0" diff --git a/framework/meta/src/cmd/wallet.rs b/framework/meta/src/cmd/wallet.rs index 7fcf28899a..ba8a9f6132 100644 --- a/framework/meta/src/cmd/wallet.rs +++ b/framework/meta/src/cmd/wallet.rs @@ -1,16 +1,16 @@ use core::str; -use multiversx_sc::types; -use std::{ - fs::{self, File}, - io::{self, Read, Write}, -}; use crate::cli::{WalletAction, WalletArgs, WalletBech32Args, WalletConvertArgs, WalletNewArgs}; -use bip39::Mnemonic; +use multiversx_sc::types::{self}; use multiversx_sc_snippets::sdk::{ crypto::public_key::PublicKey, data::address::Address, utils::base64_encode, wallet::Wallet, }; use multiversx_sc_snippets::{hex, imports::Bech32Address}; +use std::{ + fs::{self, File}, + io::{self, Read, Write}, +}; + pub fn wallet(args: &WalletArgs) { let command = &args.command; match command { @@ -27,45 +27,92 @@ fn convert(convert_args: &WalletConvertArgs) { let out_format = &convert_args.to; let mut mnemonic_str = String::new(); + let private_key_str: String; + let public_key_str: String; match (in_format.as_str(), out_format.as_str()) { ("mnemonic", "pem") => match infile { Some(file) => { mnemonic_str = fs::read_to_string(file).unwrap(); - mnemonic_str = mnemonic_str.replace('\n', ""); + (private_key_str, public_key_str) = Wallet::get_wallet_keys_mnemonic(mnemonic_str); + write_resulted_pem(&public_key_str, &private_key_str, outfile); }, None => { println!("Insert text below. Press 'Ctrl-D' (Linux / MacOS) or 'Ctrl-Z' (Windows) when done."); - _ = io::stdin().read_to_string(&mut mnemonic_str).unwrap() + _ = io::stdin().read_to_string(&mut mnemonic_str).unwrap(); + (private_key_str, public_key_str) = Wallet::get_wallet_keys_mnemonic(mnemonic_str); + write_resulted_pem(&public_key_str, &private_key_str, outfile); + }, + }, + ("keystore-secret", "pem") => match infile { + Some(file) => { + let private_key = Wallet::get_private_key_from_keystore_secret( + file, + &Wallet::get_keystore_password(), + ) + .unwrap(); + private_key_str = private_key.to_string(); + let public_key = PublicKey::from(&private_key); + public_key_str = public_key.to_string(); + write_resulted_pem(&public_key_str, &private_key_str, outfile); + }, + None => { + panic!("Input file is required for keystore-secret format"); + }, + }, + ("pem", "keystore-secret") => match infile { + Some(file) => { + let pem_decoded_keys = Wallet::get_pem_decoded_content(file); + (private_key_str, public_key_str) = Wallet::get_wallet_keys_pem(file); + + let address = get_wallet_address(&private_key_str); + let hex_decoded_keys = hex::decode(pem_decoded_keys).unwrap(); + + let json_result = Wallet::encrypt_keystore( + hex_decoded_keys.as_slice(), + &address, + &public_key_str, + &Wallet::get_keystore_password(), + ); + write_resulted_keystore(json_result, outfile); + }, + None => { + panic!("Input file is required for pem format"); }, }, _ => { println!("Unsupported conversion"); }, } +} - let mnemonic = Mnemonic::parse(mnemonic_str).unwrap(); - - let (private_key_str, public_key_str) = get_wallet_keys(mnemonic); - let address = get_wallet_address(private_key_str.as_str()); - +fn write_resulted_pem(public_key: &str, private_key: &str, outfile: Option<&String>) { + let address = get_wallet_address(private_key); match outfile { Some(outfile) => { - generate_pem( - &address, - private_key_str.as_str(), - public_key_str.as_str(), - outfile, - ); + let pem_content = generate_pem_content(&address, private_key, public_key); + let mut file = File::create(outfile).unwrap(); + file.write_all(pem_content.as_bytes()).unwrap(); }, None => { - let pem_content = - generate_pem_content(&address, private_key_str.as_str(), public_key_str.as_str()); + let pem_content = generate_pem_content(&address, private_key, public_key); print!("{}", pem_content); }, } } +fn write_resulted_keystore(json_result: String, outfile: Option<&String>) { + match outfile { + Some(outfile) => { + let mut file = File::create(outfile).unwrap(); + file.write_all(json_result.as_bytes()).unwrap(); + }, + None => { + println!("{}", json_result); + }, + } +} + fn bech32_conversion(bech32_args: &WalletBech32Args) { let encode_address = bech32_args.hex_address.as_ref(); let decode_address = bech32_args.bech32_address.as_ref(); @@ -90,57 +137,45 @@ fn bech32_conversion(bech32_args: &WalletBech32Args) { } } -fn get_wallet_keys(mnemonic: Mnemonic) -> (String, String) { - let private_key = Wallet::get_private_key_from_mnemonic(mnemonic, 0u32, 0u32); - let public_key = PublicKey::from(&private_key); - - let public_key_str: &str = &public_key.to_string(); - let private_key_str: &str = &private_key.to_string(); - - (private_key_str.to_string(), public_key_str.to_string()) -} - fn get_wallet_address(private_key: &str) -> Address { let wallet = Wallet::from_private_key(private_key).unwrap(); wallet.address() } fn new(new_args: &WalletNewArgs) { - let format = new_args.wallet_format.as_ref(); - let outfile = new_args.outfile.as_ref(); + let format = new_args.wallet_format.as_deref(); + let outfile = new_args.outfile.as_ref(); // Handle outfile as Option<&str> if it's an Option let mnemonic = Wallet::generate_mnemonic(); println!("Mnemonic: {}", mnemonic); - let (private_key_str, public_key_str) = get_wallet_keys(mnemonic); + let (private_key_str, public_key_str) = Wallet::get_wallet_keys_mnemonic(mnemonic.to_string()); let address = get_wallet_address(private_key_str.as_str()); println!("Wallet address: {}", address); - if let Some(f) = format { - match (f.as_str(), outfile) { - ("pem", Some(file)) => { - generate_pem( - &address, - private_key_str.as_str(), - public_key_str.as_str(), - file, - ); - }, - ("pem", None) => { - println!("Output file is required for PEM format"); - }, - _ => {}, - } + match format { + Some("pem") => { + write_resulted_pem(public_key_str.as_str(), private_key_str.as_str(), outfile); + }, + Some("keystore-secret") => { + let concatenated_keys = format!("{}{}", private_key_str, public_key_str); + let hex_decoded_keys = hex::decode(concatenated_keys).unwrap(); + let json_result = Wallet::encrypt_keystore( + hex_decoded_keys.as_slice(), + &address, + &public_key_str, + &Wallet::get_keystore_password(), + ); + write_resulted_keystore(json_result, outfile); + }, + Some(_) => { + println!("Unsupported format"); + }, + None => {}, } } -fn generate_pem(address: &Address, private_key: &str, public_key: &str, outfile: &String) { - let pem_content = generate_pem_content(address, private_key, public_key); - let mut file = File::create(outfile).unwrap(); - file.write_all(pem_content.as_bytes()).unwrap() -} - -fn generate_pem_content(address: &Address, private_key: &str, public_key: &str) -> String { +pub fn generate_pem_content(address: &Address, private_key: &str, public_key: &str) -> String { let concat_keys = format!("{}{}", private_key, public_key); let concat_keys_b64 = base64_encode(concat_keys); diff --git a/framework/meta/tests/wallet_test.rs b/framework/meta/tests/wallet_test.rs new file mode 100644 index 0000000000..ce1627ff64 --- /dev/null +++ b/framework/meta/tests/wallet_test.rs @@ -0,0 +1,91 @@ +use std::fs::{self, File}; +use std::io::Write; + +use multiversx_sc_meta::cmd::wallet::generate_pem_content; +use multiversx_sc_snippets::sdk::{crypto::public_key::PublicKey, data::address::Address}; +use multiversx_sc_snippets::{hex, imports::Wallet}; + +const ALICE_PEM_PATH: &str = "../snippets/src/test_wallets/alice.pem"; +const ALICE_KEYSTORE_PATH_TEST: &str = "alice.json"; +const ALICE_PEM_PATH_TEST: &str = "alice_test.pem"; +const KEYSTORE_PASSWORD: &str = "abcd"; + +fn create_keystore_from_pem(file: &str) { + let pem_decoded_keys = Wallet::get_pem_decoded_content(file); + let (private_key_str, public_key_str) = Wallet::get_wallet_keys_pem(file); + + let address = Wallet::from_private_key(&private_key_str) + .unwrap() + .address(); + let hex_decoded_keys = hex::decode(pem_decoded_keys).unwrap(); + + let json_result = Wallet::encrypt_keystore( + hex_decoded_keys.as_slice(), + &address, + &public_key_str, + KEYSTORE_PASSWORD, + ); + + write_to_file(&json_result, ALICE_KEYSTORE_PATH_TEST); +} + +fn write_to_file(content: &str, file: &str) { + let mut file = File::create(file).unwrap(); + file.write_all(content.as_bytes()).unwrap(); +} + +fn create_keystore_file_from_scratch() -> Address { + let mnemonic = Wallet::generate_mnemonic(); + let (private_key_str, public_key_str) = Wallet::get_wallet_keys_mnemonic(mnemonic.to_string()); + let wallet = Wallet::from_private_key(&private_key_str).unwrap(); + let address = wallet.address(); + + let concatenated_keys = format!("{}{}", private_key_str, public_key_str); + let hex_decoded_keys = hex::decode(concatenated_keys).unwrap(); + let json_result = Wallet::encrypt_keystore( + hex_decoded_keys.as_slice(), + &address, + &public_key_str, + KEYSTORE_PASSWORD, + ); + write_to_file(&json_result, ALICE_KEYSTORE_PATH_TEST); + address +} + +#[test] +fn test_wallet_convert_pem_to_keystore() { + create_keystore_from_pem(ALICE_PEM_PATH); + let (private_key_pem, _public_key_pem) = Wallet::get_wallet_keys_pem(ALICE_PEM_PATH); + assert_eq!( + Wallet::get_private_key_from_keystore_secret(ALICE_KEYSTORE_PATH_TEST, KEYSTORE_PASSWORD) + .unwrap() + .to_string(), + private_key_pem + ); + fs::remove_file(ALICE_KEYSTORE_PATH_TEST).unwrap(); +} + +#[test] +fn test_wallet_convert_keystore_to_pem() { + let address = create_keystore_file_from_scratch(); + + let private_key = + Wallet::get_private_key_from_keystore_secret(ALICE_KEYSTORE_PATH_TEST, KEYSTORE_PASSWORD) + .unwrap(); + let private_key_str = private_key.to_string(); + let public_key = PublicKey::from(&private_key); + let public_key_str = public_key.to_string(); + + let pem_content = generate_pem_content(&address, &private_key_str, &public_key_str); + write_to_file(&pem_content, ALICE_PEM_PATH_TEST); + + assert_eq!( + Wallet::get_private_key_from_keystore_secret(ALICE_KEYSTORE_PATH_TEST, KEYSTORE_PASSWORD) + .unwrap() + .to_string(), + Wallet::get_wallet_keys_pem(ALICE_PEM_PATH_TEST).0 + ); + + fs::remove_file(ALICE_PEM_PATH_TEST).unwrap(); + fs::remove_file(ALICE_KEYSTORE_PATH_TEST).unwrap(); +} diff --git a/sdk/core/Cargo.toml b/sdk/core/Cargo.toml index 32e170618f..e84f8cd4cb 100644 --- a/sdk/core/Cargo.toml +++ b/sdk/core/Cargo.toml @@ -37,4 +37,5 @@ pem = "3.0.2" log = "0.4.17" scrypt = "0.11" aes = "0.8" -ctr = "0.9.2" \ No newline at end of file +ctr = "0.9.2" +uuid = {version = "1.10.0", features = ["v4"]} \ No newline at end of file diff --git a/sdk/core/src/data/keystore.rs b/sdk/core/src/data/keystore.rs index 2564d70a2e..1b3c656ef1 100644 --- a/sdk/core/src/data/keystore.rs +++ b/sdk/core/src/data/keystore.rs @@ -1,5 +1,11 @@ use serde::{Deserialize, Serialize}; +pub const KDF_N: u32 = 4096; +pub const KDF_R: u32 = 8; +pub const KDF_P: u32 = 1; +pub const KDF_DKLEN: usize = 32; +pub const KEYSTORE_VERSION: u32 = 4; + #[derive(Debug)] pub enum WalletError { InvalidPassword, @@ -44,5 +50,5 @@ pub struct Keystore { pub struct DecryptionParams { pub derived_key_first_half: Vec, pub iv: Vec, - pub ciphertext: Vec, + pub data: Vec, } diff --git a/sdk/core/src/wallet.rs b/sdk/core/src/wallet.rs index b2856b74da..bbf2c41a2c 100644 --- a/sdk/core/src/wallet.rs +++ b/sdk/core/src/wallet.rs @@ -1,5 +1,6 @@ extern crate rand; +use core::str; use std::{ fs::{self}, io::{self, Read}, @@ -11,6 +12,7 @@ use bip39::{Language, Mnemonic}; use ctr::{cipher::StreamCipher, Ctr128BE}; use hmac::{Hmac, Mac}; use pbkdf2::pbkdf2; +use rand::RngCore; use scrypt::{scrypt, Params}; use serde_json::json; use sha2::{Digest, Sha256, Sha512}; @@ -22,13 +24,12 @@ use crate::{ private_key::{PrivateKey, PRIVATE_KEY_LENGTH}, public_key::PublicKey, }, - data::{ - address::Address, - keystore::{DecryptionParams, Keystore, WalletError}, - transaction::Transaction, - }, + data::{address::Address, keystore::*, transaction::Transaction}, + utils::base64_decode, }; +use uuid::Uuid; + const EGLD_COIN_TYPE: u32 = 508; const HARDENED: u32 = 0x80000000; const CIPHER_ALGORITHM_AES_128_CTR: &str = "aes-128-ctr"; @@ -79,6 +80,7 @@ impl Wallet { let mut digest = HmacSha512::new_from_slice(b"ed25519 seed").expect("HMAC can take key of any size"); + HmacSha512::new_from_slice(b"ed25519 seed").expect("HMAC can take key of any size"); digest.update(&seed); let intermediary: Vec = digest.finalize().into_bytes().into_iter().collect(); let mut key = intermediary[..serialized_key_len].to_vec(); @@ -99,6 +101,7 @@ impl Wallet { digest = HmacSha512::new_from_slice(&chain_code).expect("HMAC can take key of any size"); + HmacSha512::new_from_slice(&chain_code).expect("HMAC can take key of any size"); digest.update(&buff); let intermediary: Vec = digest.finalize().into_bytes().into_iter().collect(); key = intermediary[..serialized_key_len].to_vec(); @@ -108,9 +111,20 @@ impl Wallet { PrivateKey::from_bytes(key.as_slice()).unwrap() } + pub fn get_wallet_keys_mnemonic(mnemonic_str: String) -> (String, String) { + let mnemonic = Mnemonic::parse(mnemonic_str.replace('\n', "")).unwrap(); + let private_key = Self::get_private_key_from_mnemonic(mnemonic, 0u32, 0u32); + let public_key = PublicKey::from(&private_key); + + let public_key_str: &str = &public_key.to_string(); + let private_key_str: &str = &private_key.to_string(); + + (private_key_str.to_string(), public_key_str.to_string()) + } + pub fn from_private_key(priv_key: &str) -> Result { - let pri_key = PrivateKey::from_hex_str(priv_key)?; - Ok(Self { priv_key: pri_key }) + let priv_key = PrivateKey::from_hex_str(priv_key)?; + Ok(Self { priv_key }) } pub fn from_pem_file(file_path: &str) -> Result { @@ -126,25 +140,45 @@ impl Wallet { Ok(Self { priv_key: pri_key }) } + pub fn get_pem_decoded_content(file: &str) -> Vec { + let pem_content = fs::read_to_string(file).unwrap(); + let lines: Vec<&str> = pem_content.split('\n').collect(); + let pem_encoded_keys = format!("{}{}{}", lines[1], lines[2], lines[3]); + base64_decode(pem_encoded_keys) + } + + pub fn get_wallet_keys_pem(file: &str) -> (String, String) { + let pem_decoded_keys = Self::get_pem_decoded_content(file); + let (private_key, public_key) = pem_decoded_keys.split_at(pem_decoded_keys.len() / 2); + let private_key_str = String::from_utf8(private_key.to_vec()).unwrap(); + let public_key_str = String::from_utf8(public_key.to_vec()).unwrap(); + + (private_key_str, public_key_str) + } + pub fn from_keystore_secret(file_path: &str) -> Result { let decyption_params = Self::validate_keystore_password(file_path, Self::get_keystore_password()) .unwrap_or_else(|e| { panic!("Error: {:?}", e); }); - let priv_key = - PrivateKey::from_hex_str(Self::decrypt_secret_key(decyption_params).as_str())?; + let priv_key = PrivateKey::from_hex_str( + hex::encode(Self::decrypt_secret_key(decyption_params)).as_str(), + )?; Ok(Self { priv_key }) } - pub fn get_private_key_from_keystore_secret(file_path: &str) -> Result { - let decyption_params = - Self::validate_keystore_password(file_path, Self::get_keystore_password()) - .unwrap_or_else(|e| { - panic!("Error: {:?}", e); - }); - let priv_key = - PrivateKey::from_hex_str(Self::decrypt_secret_key(decyption_params).as_str())?; + pub fn get_private_key_from_keystore_secret( + file_path: &str, + password: &str, + ) -> Result { + let decyption_params = Self::validate_keystore_password(file_path, password.to_string()) + .unwrap_or_else(|e| { + panic!("Error: {:?}", e); + }); + let priv_key = PrivateKey::from_hex_str( + hex::encode(Self::decrypt_secret_key(decyption_params)).as_str(), + )?; Ok(priv_key) } @@ -169,7 +203,7 @@ impl Wallet { self.priv_key.sign(tx_bytes) } - fn get_keystore_password() -> String { + pub fn get_keystore_password() -> String { println!( "Insert password. Press 'Ctrl-D' (Linux / MacOS) or 'Ctrl-Z' (Windows) when done." ); @@ -222,7 +256,7 @@ impl Wallet { Ok(DecryptionParams { derived_key_first_half, iv, - ciphertext, + data: ciphertext, }) } else { println!("Password is incorrect"); @@ -230,14 +264,73 @@ impl Wallet { } } - pub fn decrypt_secret_key(decryption_params: DecryptionParams) -> String { + pub fn decrypt_secret_key(decryption_params: DecryptionParams) -> Vec { let mut cipher = Ctr128BE::::new( decryption_params.derived_key_first_half.as_slice().into(), decryption_params.iv.as_slice().into(), ); - let mut decrypted = decryption_params.ciphertext.to_vec(); + let mut decrypted = decryption_params.data.to_vec(); cipher.apply_keystream(&mut decrypted); - hex::encode(decrypted).to_string() + decrypted + } + + pub fn encrypt_keystore( + data: &[u8], + address: &Address, + public_key: &str, + password: &str, + ) -> String { + let params = Params::new((KDF_N as f64).log2() as u8, KDF_R, KDF_P, KDF_DKLEN).unwrap(); + let mut rand_salt: [u8; 32] = [0u8; 32]; + rand::thread_rng().fill_bytes(&mut rand_salt); + let salt_hex = hex::encode(rand_salt); + + let mut rand_iv: [u8; 16] = [0u8; 16]; + rand::thread_rng().fill_bytes(&mut rand_iv); + let iv_hex = hex::encode(rand_iv); + + let mut derived_key = vec![0u8; 32]; + scrypt(password.as_bytes(), &rand_salt, ¶ms, &mut derived_key).unwrap(); + + let derived_key_first_half = derived_key[0..16].to_vec(); + let derived_key_second_half = derived_key[16..32].to_vec(); + + let decryption_params = DecryptionParams { + derived_key_first_half, + iv: rand_iv.to_vec(), + data: data.to_vec(), + }; + + let ciphertext = Self::decrypt_secret_key(decryption_params); + + let mut h = HmacSha256::new_from_slice(&derived_key_second_half).unwrap(); + h.update(&ciphertext); + let mac = h.finalize().into_bytes(); + let keystore = Keystore { + crypto: Crypto { + cipher: CIPHER_ALGORITHM_AES_128_CTR.to_string(), + cipherparams: CryptoParams { iv: iv_hex }, + ciphertext: hex::encode(&ciphertext), + kdf: KDF_SCRYPT.to_string(), + kdfparams: KdfParams { + salt: salt_hex, + n: KDF_N, + r: KDF_R, + p: KDF_P, + dklen: KDF_DKLEN as u32, + }, + mac: hex::encode(mac), + }, + id: Uuid::new_v4().to_string(), + version: KEYSTORE_VERSION, + kind: "secretKey".to_string(), + address: public_key.to_string(), + bech32: address.to_string(), + }; + + let mut keystore_json: String = serde_json::to_string_pretty(&keystore).unwrap(); + keystore_json.push('\n'); + keystore_json } } From 59ef56038c4f7975091df2f363c9c91dad34cb9b Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Wed, 21 Aug 2024 22:49:00 +0200 Subject: [PATCH 20/92] whitebox migration for price aggregator, transfer role, gov module --- .../tests/price_aggregator_whitebox_test.rs | 562 +++++++------- .../tests/transfer_role_whitebox_test.rs | 230 +++--- .../tests/gov_module_whitebox_test.rs | 723 +++++++++--------- 3 files changed, 756 insertions(+), 759 deletions(-) diff --git a/contracts/core/price-aggregator/tests/price_aggregator_whitebox_test.rs b/contracts/core/price-aggregator/tests/price_aggregator_whitebox_test.rs index 180301b610..46ce6f52c3 100644 --- a/contracts/core/price-aggregator/tests/price_aggregator_whitebox_test.rs +++ b/contracts/core/price-aggregator/tests/price_aggregator_whitebox_test.rs @@ -4,7 +4,7 @@ use multiversx_price_aggregator_sc::{ }; use multiversx_sc_modules::{ pause::EndpointWrappers as PauseEndpointWrappers, - staking::EndpointWrappers as StakingEndpointWrappers, + staking::{EndpointWrappers as StakingEndpointWrappers, StakingModule}, }; use multiversx_sc_scenario::imports::*; @@ -17,9 +17,10 @@ pub const STAKE_AMOUNT: u64 = 20; pub const SUBMISSION_COUNT: usize = 3; pub const USD_TICKER: &[u8] = b"USDC"; -const OWNER_ADDRESS_EXPR: &str = "address:owner"; -const PRICE_AGGREGATOR_ADDRESS_EXPR: &str = "sc:price-aggregator"; -const PRICE_AGGREGATOR_PATH_EXPR: &str = "mxsc:output/multiversx-price-aggregator-sc.mxsc.json"; +const OWNER_ADDRESS: TestAddress = TestAddress::new("owner"); +const PRICE_AGGREGATOR_ADDRESS: TestSCAddress = TestSCAddress::new("price-aggregator"); +const PRICE_AGGREGATOR_PATH_EXPR: MxscPath = + MxscPath::new("mxsc:output/multiversx-price-aggregator-sc.mxsc.json"); fn world() -> ScenarioWorld { let mut blockchain = ScenarioWorld::new(); @@ -35,31 +36,27 @@ fn world() -> ScenarioWorld { #[test] fn test_price_aggregator_submit() { let (mut world, oracles) = setup(); - let price_aggregator_whitebox = WhiteboxContract::new( - PRICE_AGGREGATOR_ADDRESS_EXPR, - multiversx_price_aggregator_sc::contract_obj, - ); // configure the number of decimals - world.whitebox_call( - &price_aggregator_whitebox, - ScCallStep::new().from(OWNER_ADDRESS_EXPR), - |sc| { + world + .tx() + .from(OWNER_ADDRESS) + .to(PRICE_AGGREGATOR_ADDRESS) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { sc.set_pair_decimals( managed_buffer!(EGLD_TICKER), managed_buffer!(USD_TICKER), DECIMALS, ) - }, - ); + }); // try submit while paused - world.whitebox_call_check( - &price_aggregator_whitebox, - ScCallStep::new() - .from(&oracles[0]) - .expect(TxExpect::user_error("str:Contract is paused")), - |sc| { + world + .tx() + .from(&oracles[0]) + .to(PRICE_AGGREGATOR_ADDRESS) + .returns(ExpectError(4u64, "Contract is paused")) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { sc.submit( managed_buffer!(EGLD_TICKER), managed_buffer!(USD_TICKER), @@ -67,22 +64,24 @@ fn test_price_aggregator_submit() { managed_biguint!(100), DECIMALS, ) - }, - |r| r.assert_user_error("Contract is paused"), - ); + }); // unpause - world.whitebox_call( - &price_aggregator_whitebox, - ScCallStep::new().from(OWNER_ADDRESS_EXPR), - |sc| sc.call_unpause_endpoint(), - ); + world + .tx() + .from(OWNER_ADDRESS) + .to(PRICE_AGGREGATOR_ADDRESS) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { + sc.call_unpause_endpoint(); + }); // submit first timestamp too old - world.whitebox_call_check( - &price_aggregator_whitebox, - ScCallStep::new().from(&oracles[0]).no_expect(), - |sc| { + world + .tx() + .from(&oracles[0]) + .to(PRICE_AGGREGATOR_ADDRESS) + .returns(ExpectError(4u64, "First submission too old")) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { sc.submit( managed_buffer!(EGLD_TICKER), managed_buffer!(USD_TICKER), @@ -90,17 +89,14 @@ fn test_price_aggregator_submit() { managed_biguint!(100), DECIMALS, ) - }, - |r| { - r.assert_user_error("First submission too old"); - }, - ); + }); // submit ok - world.whitebox_call( - &price_aggregator_whitebox, - ScCallStep::new().from(&oracles[0]), - |sc| { + world + .tx() + .from(&oracles[0]) + .to(PRICE_AGGREGATOR_ADDRESS) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { sc.submit( managed_buffer!(EGLD_TICKER), managed_buffer!(USD_TICKER), @@ -108,49 +104,50 @@ fn test_price_aggregator_submit() { managed_biguint!(100), DECIMALS, ) - }, - ); + }); let current_timestamp = 100; - world.whitebox_query(&price_aggregator_whitebox, |sc| { - let token_pair = TokenPair { - from: managed_buffer!(EGLD_TICKER), - to: managed_buffer!(USD_TICKER), - }; - assert_eq!( - sc.first_submission_timestamp(&token_pair).get(), - current_timestamp - ); - assert_eq!( - sc.last_submission_timestamp(&token_pair).get(), - current_timestamp - ); - - let submissions = sc.submissions().get(&token_pair).unwrap(); - assert_eq!(submissions.len(), 1); - assert_eq!( - submissions - .get(&managed_address!(&oracles[0].to_address())) - .unwrap(), - managed_biguint!(100) - ); - - assert_eq!( - sc.oracle_status() - .get(&managed_address!(&oracles[0].to_address())) - .unwrap(), - OracleStatus { - total_submissions: 1, - accepted_submissions: 1 - } - ); - }); + world.query().to(PRICE_AGGREGATOR_ADDRESS).whitebox( + multiversx_price_aggregator_sc::contract_obj, + |sc| { + let token_pair = TokenPair { + from: managed_buffer!(EGLD_TICKER), + to: managed_buffer!(USD_TICKER), + }; + assert_eq!( + sc.first_submission_timestamp(&token_pair).get(), + current_timestamp + ); + assert_eq!( + sc.last_submission_timestamp(&token_pair).get(), + current_timestamp + ); + + let submissions = sc.submissions().get(&token_pair).unwrap(); + assert_eq!(submissions.len(), 1); + assert_eq!( + submissions.get(&ManagedAddress::from(&oracles[0])).unwrap(), + managed_biguint!(100) + ); + + assert_eq!( + sc.oracle_status() + .get(&ManagedAddress::from(&oracles[0])) + .unwrap(), + OracleStatus { + total_submissions: 1, + accepted_submissions: 1 + } + ); + }, + ); // first oracle submit again - submission not accepted - world.whitebox_call( - &price_aggregator_whitebox, - ScCallStep::new().from(&oracles[0]), - |sc| { + world + .tx() + .from(&oracles[0]) + .to(PRICE_AGGREGATOR_ADDRESS) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { sc.submit( managed_buffer!(EGLD_TICKER), managed_buffer!(USD_TICKER), @@ -158,55 +155,56 @@ fn test_price_aggregator_submit() { managed_biguint!(100), DECIMALS, ) + }); + + world.query().to(PRICE_AGGREGATOR_ADDRESS).whitebox( + multiversx_price_aggregator_sc::contract_obj, + |sc| { + assert_eq!( + sc.oracle_status() + .get(&ManagedAddress::from(&oracles[0])) + .unwrap(), + OracleStatus { + total_submissions: 2, + accepted_submissions: 1 + } + ); }, ); - - world.whitebox_query(&price_aggregator_whitebox, |sc| { - assert_eq!( - sc.oracle_status() - .get(&managed_address!(&oracles[0].to_address())) - .unwrap(), - OracleStatus { - total_submissions: 2, - accepted_submissions: 1 - } - ); - }); } #[test] fn test_price_aggregator_submit_round_ok() { let (mut world, oracles) = setup(); - let price_aggregator_whitebox = WhiteboxContract::new( - PRICE_AGGREGATOR_ADDRESS_EXPR, - multiversx_price_aggregator_sc::contract_obj, - ); // configure the number of decimals - world.whitebox_call( - &price_aggregator_whitebox, - ScCallStep::new().from(OWNER_ADDRESS_EXPR), - |sc| { + world + .tx() + .from(OWNER_ADDRESS) + .to(PRICE_AGGREGATOR_ADDRESS) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { sc.set_pair_decimals( managed_buffer!(EGLD_TICKER), managed_buffer!(USD_TICKER), DECIMALS, ) - }, - ); + }); // unpause - world.whitebox_call( - &price_aggregator_whitebox, - ScCallStep::new().from(OWNER_ADDRESS_EXPR), - |sc| sc.call_unpause_endpoint(), - ); + world + .tx() + .from(OWNER_ADDRESS) + .to(PRICE_AGGREGATOR_ADDRESS) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { + sc.call_unpause_endpoint(); + }); // submit first - world.whitebox_call( - &price_aggregator_whitebox, - ScCallStep::new().from(&oracles[0]), - |sc| { + world + .tx() + .from(&oracles[0]) + .to(PRICE_AGGREGATOR_ADDRESS) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { sc.submit( managed_buffer!(EGLD_TICKER), managed_buffer!(USD_TICKER), @@ -214,17 +212,17 @@ fn test_price_aggregator_submit_round_ok() { managed_biguint!(10_000), DECIMALS, ) - }, - ); + }); let current_timestamp = 110; - world.set_state_step(SetStateStep::new().block_timestamp(current_timestamp)); + world.current_block().block_timestamp(current_timestamp); // submit second - world.whitebox_call( - &price_aggregator_whitebox, - ScCallStep::new().from(&oracles[1]), - |sc| { + world + .tx() + .from(&oracles[1]) + .to(PRICE_AGGREGATOR_ADDRESS) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { sc.submit( managed_buffer!(EGLD_TICKER), managed_buffer!(USD_TICKER), @@ -232,14 +230,14 @@ fn test_price_aggregator_submit_round_ok() { managed_biguint!(11_000), DECIMALS, ) - }, - ); + }); // submit third - world.whitebox_call( - &price_aggregator_whitebox, - ScCallStep::new().from(&oracles[2]), - |sc| { + world + .tx() + .from(&oracles[2]) + .to(PRICE_AGGREGATOR_ADDRESS) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { sc.submit( managed_buffer!(EGLD_TICKER), managed_buffer!(USD_TICKER), @@ -247,72 +245,73 @@ fn test_price_aggregator_submit_round_ok() { managed_biguint!(12_000), DECIMALS, ) + }); + + world.query().to(PRICE_AGGREGATOR_ADDRESS).whitebox( + multiversx_price_aggregator_sc::contract_obj, + |sc| { + let result = + sc.latest_price_feed(managed_buffer!(EGLD_TICKER), managed_buffer!(USD_TICKER)); + + let (round_id, from, to, timestamp, price, decimals) = result.into_tuple(); + assert_eq!(round_id, 1); + assert_eq!(from, managed_buffer!(EGLD_TICKER)); + assert_eq!(to, managed_buffer!(USD_TICKER)); + assert_eq!(timestamp, current_timestamp); + assert_eq!(price, managed_biguint!(11_000)); + assert_eq!(decimals, DECIMALS); + + // submissions are deleted after round is created + let token_pair = TokenPair { from, to }; + let submissions = sc.submissions().get(&token_pair).unwrap(); + assert_eq!(submissions.len(), 0); + + let rounds = sc.rounds().get(&token_pair).unwrap(); + assert_eq!(rounds.len(), 1); + assert_eq!( + rounds.get(1), + TimestampedPrice { + timestamp, + price, + decimals + } + ); }, ); - - world.whitebox_query(&price_aggregator_whitebox, |sc| { - let result = - sc.latest_price_feed(managed_buffer!(EGLD_TICKER), managed_buffer!(USD_TICKER)); - - let (round_id, from, to, timestamp, price, decimals) = result.into_tuple(); - assert_eq!(round_id, 1); - assert_eq!(from, managed_buffer!(EGLD_TICKER)); - assert_eq!(to, managed_buffer!(USD_TICKER)); - assert_eq!(timestamp, current_timestamp); - assert_eq!(price, managed_biguint!(11_000)); - assert_eq!(decimals, DECIMALS); - - // submissions are deleted after round is created - let token_pair = TokenPair { from, to }; - let submissions = sc.submissions().get(&token_pair).unwrap(); - assert_eq!(submissions.len(), 0); - - let rounds = sc.rounds().get(&token_pair).unwrap(); - assert_eq!(rounds.len(), 1); - assert_eq!( - rounds.get(1), - TimestampedPrice { - timestamp, - price, - decimals - } - ); - }); } #[test] fn test_price_aggregator_discarded_round() { let (mut world, oracles) = setup(); - let price_aggregator_whitebox = WhiteboxContract::new( - PRICE_AGGREGATOR_ADDRESS_EXPR, - multiversx_price_aggregator_sc::contract_obj, - ); // configure the number of decimals - world.whitebox_call( - &price_aggregator_whitebox, - ScCallStep::new().from(OWNER_ADDRESS_EXPR), - |sc| { + world + .tx() + .from(OWNER_ADDRESS) + .to(PRICE_AGGREGATOR_ADDRESS) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { sc.set_pair_decimals( managed_buffer!(EGLD_TICKER), managed_buffer!(USD_TICKER), DECIMALS, ) - }, - ); + }); // unpause - world.whitebox_call( - &price_aggregator_whitebox, - ScCallStep::new().from(OWNER_ADDRESS_EXPR), - |sc| sc.call_unpause_endpoint(), - ); + world + .tx() + .from(OWNER_ADDRESS) + .to(PRICE_AGGREGATOR_ADDRESS) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { + sc.call_unpause_endpoint(); + }); // submit first - world.whitebox_call( - &price_aggregator_whitebox, - ScCallStep::new().from(&oracles[0]), - |sc| { + world + .tx() + .from(&oracles[0]) + .to(PRICE_AGGREGATOR_ADDRESS) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { sc.submit( managed_buffer!(EGLD_TICKER), managed_buffer!(USD_TICKER), @@ -320,17 +319,17 @@ fn test_price_aggregator_discarded_round() { managed_biguint!(10_000), DECIMALS, ) - }, - ); + }); let current_timestamp = 100 + MAX_ROUND_DURATION_SECONDS + 1; - world.set_state_step(SetStateStep::new().block_timestamp(current_timestamp)); + world.current_block().block_timestamp(current_timestamp); // submit second - this will discard the previous submission - world.whitebox_call( - &price_aggregator_whitebox, - ScCallStep::new().from(&oracles[1]), - |sc| { + world + .tx() + .from(&oracles[1]) + .to(PRICE_AGGREGATOR_ADDRESS) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { sc.submit( managed_buffer!(EGLD_TICKER), managed_buffer!(USD_TICKER), @@ -338,77 +337,100 @@ fn test_price_aggregator_discarded_round() { managed_biguint!(11_000), DECIMALS, ) + }); + + world.query().to(PRICE_AGGREGATOR_ADDRESS).whitebox( + multiversx_price_aggregator_sc::contract_obj, + |sc| { + let token_pair = TokenPair { + from: managed_buffer!(EGLD_TICKER), + to: managed_buffer!(USD_TICKER), + }; + let submissions = sc.submissions().get(&token_pair).unwrap(); + assert_eq!(submissions.len(), 1); + assert_eq!( + submissions.get(&managed_address!(&oracles[1])).unwrap(), + managed_biguint!(11_000) + ); }, ); - - world.whitebox_query(&price_aggregator_whitebox, |sc| { - let token_pair = TokenPair { - from: managed_buffer!(EGLD_TICKER), - to: managed_buffer!(USD_TICKER), - }; - let submissions = sc.submissions().get(&token_pair).unwrap(); - assert_eq!(submissions.len(), 1); - assert_eq!( - submissions - .get(&managed_address!(&oracles[1].to_address())) - .unwrap(), - managed_biguint!(11_000) - ); - }); } #[test] fn test_price_aggregator_slashing() { let (mut world, oracles) = setup(); - let price_aggregator_whitebox = WhiteboxContract::new( - PRICE_AGGREGATOR_ADDRESS_EXPR, - multiversx_price_aggregator_sc::contract_obj, - ); - // unpause - world.whitebox_call( - &price_aggregator_whitebox, - ScCallStep::new().from(OWNER_ADDRESS_EXPR), - |sc| sc.call_unpause_endpoint(), - ); - - world.whitebox_call( - &price_aggregator_whitebox, - ScCallStep::new() - .from(&oracles[0]) - .argument(BytesValue::from(oracles[1].to_address().as_bytes())), - |sc| sc.call_vote_slash_member(), - ); - - world.whitebox_call( - &price_aggregator_whitebox, - ScCallStep::new() - .from(&oracles[2]) - .argument(BytesValue::from(oracles[1].to_address().as_bytes())), - |sc| sc.call_vote_slash_member(), - ); + // configure the number of decimals + world + .tx() + .from(OWNER_ADDRESS) + .to(PRICE_AGGREGATOR_ADDRESS) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { + sc.set_pair_decimals( + managed_buffer!(EGLD_TICKER), + managed_buffer!(USD_TICKER), + DECIMALS, + ) + }); - world.whitebox_call( - &price_aggregator_whitebox, - ScCallStep::new() - .from(&oracles[3]) - .argument(BytesValue::from(oracles[1].to_address().as_bytes())), - |sc| sc.call_vote_slash_member(), + // unpause + world + .tx() + .from(OWNER_ADDRESS) + .to(PRICE_AGGREGATOR_ADDRESS) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { + sc.call_unpause_endpoint(); + }); + + world + .tx() + .from(&oracles[0]) + .to(PRICE_AGGREGATOR_ADDRESS) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { + sc.vote_slash_member(ManagedAddress::from(&oracles[1])); + }); + + world + .tx() + .from(&oracles[2]) + .to(PRICE_AGGREGATOR_ADDRESS) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { + sc.vote_slash_member(ManagedAddress::from(&oracles[1])) + }); + + world + .tx() + .from(&oracles[3]) + .to(PRICE_AGGREGATOR_ADDRESS) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { + sc.vote_slash_member(ManagedAddress::from(&oracles[1])); + }); + + world.query().to(PRICE_AGGREGATOR_ADDRESS).whitebox( + multiversx_price_aggregator_sc::contract_obj, + |sc| { + let list = sc.slashing_proposal_voters(&ManagedAddress::from(&oracles[1])); + assert!(list.contains(&ManagedAddress::from(&oracles[0]))); + assert!(list.contains(&ManagedAddress::from(&oracles[2]))); + assert!(list.contains(&ManagedAddress::from(&oracles[3]))); + }, ); - world.whitebox_call( - &price_aggregator_whitebox, - ScCallStep::new() - .from(&oracles[0]) - .argument(BytesValue::from(oracles[1].to_address().as_bytes())), - |sc| sc.call_slash_member(), - ); + world + .tx() + .from(&oracles[0]) + .to(PRICE_AGGREGATOR_ADDRESS) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { + sc.slash_member(ManagedAddress::from(&oracles[1])); + }); // oracle 1 try submit after slashing - world.whitebox_call_check( - &price_aggregator_whitebox, - ScCallStep::new().from(&oracles[1]).no_expect(), - |sc| { + world + .tx() + .from(&oracles[1]) + .to(PRICE_AGGREGATOR_ADDRESS) + .returns(ExpectError(4u64, "only oracles allowed")) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { sc.submit( managed_buffer!(EGLD_TICKER), managed_buffer!(USD_TICKER), @@ -416,49 +438,37 @@ fn test_price_aggregator_slashing() { managed_biguint!(10_000), DECIMALS, ) - }, - |r| { - r.assert_user_error("only oracles allowed"); - }, - ); + }); } -fn setup() -> (ScenarioWorld, Vec) { +fn setup() -> (ScenarioWorld, Vec
) { // setup let mut world = world(); - let price_aggregator_whitebox = WhiteboxContract::new( - PRICE_AGGREGATOR_ADDRESS_EXPR, - multiversx_price_aggregator_sc::contract_obj, - ); - let price_aggregator_code = world.code_expression(PRICE_AGGREGATOR_PATH_EXPR); - let mut set_state_step = SetStateStep::new() - .put_account(OWNER_ADDRESS_EXPR, Account::new().nonce(1)) - .new_address(OWNER_ADDRESS_EXPR, 1, PRICE_AGGREGATOR_ADDRESS_EXPR) - .block_timestamp(100); + world.account(OWNER_ADDRESS).nonce(1); + world.current_block().block_timestamp(100); let mut oracles = Vec::new(); for i in 1..=NR_ORACLES { - let oracle_address_expr = format!("address:oracle{i}"); - let oracle_address = AddressValue::from(oracle_address_expr.as_str()); - - set_state_step = set_state_step.put_account( - oracle_address_expr.as_str(), - Account::new().nonce(1).balance(STAKE_AMOUNT), - ); - oracles.push(oracle_address); + let oracle_address_expr = format!("oracle{i}"); + let oracle_address = TestAddress::new(&oracle_address_expr); + + world.account(oracle_address).nonce(1).balance(STAKE_AMOUNT); + + oracles.push(oracle_address.to_address()); } // init price aggregator - world.set_state_step(set_state_step).whitebox_deploy( - &price_aggregator_whitebox, - ScDeployStep::new() - .from(OWNER_ADDRESS_EXPR) - .code(price_aggregator_code), - |sc| { + world + .tx() + .from(OWNER_ADDRESS) + .raw_deploy() + .code(PRICE_AGGREGATOR_PATH_EXPR) + .new_address(PRICE_AGGREGATOR_ADDRESS) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { let mut oracle_args = MultiValueEncoded::new(); for oracle_address in &oracles { - oracle_args.push(managed_address!(&oracle_address.to_address())); + oracle_args.push(ManagedAddress::from(oracle_address)); } sc.init( @@ -469,17 +479,17 @@ fn setup() -> (ScenarioWorld, Vec) { SUBMISSION_COUNT, oracle_args, ) - }, - ); + }); for oracle_address in &oracles { - world.whitebox_call( - &price_aggregator_whitebox, - ScCallStep::new() - .from(oracle_address) - .egld_value(STAKE_AMOUNT), - |sc| sc.call_stake(), - ); + world + .tx() + .from(oracle_address) + .to(PRICE_AGGREGATOR_ADDRESS) + .egld(STAKE_AMOUNT) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { + sc.call_stake(); + }); } (world, oracles) 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 adf9582982..130c2b237c 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 @@ -1,15 +1,17 @@ use multiversx_sc_modules::transfer_role_proxy::TransferRoleProxyModule; use multiversx_sc_scenario::imports::*; use transfer_role_features::TransferRoleFeatures; +use vault::Vault; -const OWNER_ADDRESS_EXPR: &str = "address:owner"; -const USER_ADDRESS_EXPR: &str = "address:user"; +const OWNER_ADDRESS: TestAddress = TestAddress::new("owner"); +const USER_ADDRESS: TestAddress = TestAddress::new("user"); -const TRANSFER_ROLE_FEATURES_ADDRESS_EXPR: &str = "sc:transfer-role-features"; -const TRANSFER_ROLE_FEATURES_PATH_EXPR: &str = "mxsc:output/transfer-role-features.mxsc.json"; +const TRANSFER_ROLE_FEATURES_ADDRESS: TestSCAddress = TestSCAddress::new("transfer-role-features"); +const TRANSFER_ROLE_FEATURES_PATH_EXPR: MxscPath = + MxscPath::new("mxsc:output/transfer-role-features.mxsc.json"); -const TRANSFER_TOKEN_ID_EXPR: &str = "str:TRANSFER-123456"; -const TRANSFER_TOKEN_ID: &[u8] = b"TRANSFER-123456"; +const TRANSFER_TOKEN_ID: TestTokenIdentifier = TestTokenIdentifier::new("TRANSFER-123456"); +const TRANSFER_TOKEN_ID_EXPR: &[u8] = b"TRANSFER-123456"; const ACCEPT_FUNDS_FUNC_NAME: &[u8] = b"accept_funds"; const REJECT_FUNDS_FUNC_NAME: &[u8] = b"reject_funds"; @@ -27,175 +29,161 @@ fn world() -> ScenarioWorld { fn test_transfer_role() { 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, TRANSFER_ROLE_FEATURES_ADDRESS_EXPR) - .put_account( - USER_ADDRESS_EXPR, - Account::new() - .nonce(1) - .esdt_balance(TRANSFER_TOKEN_ID_EXPR, 1_000u64), - ), - ); + world.account(OWNER_ADDRESS).nonce(1); + world + .account(USER_ADDRESS) + .nonce(1) + .esdt_balance(TRANSFER_TOKEN_ID, BigUint::from(1_000u64)); // vault - let vault_code = world.code_expression(VAULT_PATH_EXPR); - - const VAULT_ADDRESS_EXPR: &str = "sc:vault"; - const VAULT_PATH_EXPR: &str = "mxsc:../vault/output/vault.mxsc.json"; + const VAULT_ADDRESS: TestSCAddress = TestSCAddress::new("vault"); + const VAULT_PATH_EXPR: MxscPath = MxscPath::new("mxsc:../vault/output/vault.mxsc.json"); world.register_contract(VAULT_PATH_EXPR, vault::ContractBuilder); - world.set_state_step( - SetStateStep::new() - .put_account(VAULT_ADDRESS_EXPR, Account::new().nonce(1).code(vault_code)), - ); - - let transfer_role_features_whitebox = WhiteboxContract::new( - TRANSFER_ROLE_FEATURES_ADDRESS_EXPR, - transfer_role_features::contract_obj, - ); - let transfer_role_features_code = world.code_expression(TRANSFER_ROLE_FEATURES_PATH_EXPR); + world + .tx() + .from(OWNER_ADDRESS) + .raw_deploy() + .new_address(VAULT_ADDRESS) + .code(VAULT_PATH_EXPR) + .whitebox(vault::contract_obj, |sc| { + let _ = sc.init(OptionalValue::None); + }); // init - world.whitebox_deploy( - &transfer_role_features_whitebox, - ScDeployStep::new() - .from(OWNER_ADDRESS_EXPR) - .code(transfer_role_features_code), - |sc| { + world + .tx() + .from(OWNER_ADDRESS) + .raw_deploy() + .new_address(TRANSFER_ROLE_FEATURES_ADDRESS) + .code(TRANSFER_ROLE_FEATURES_PATH_EXPR) + .whitebox(transfer_role_features::contract_obj, |sc| { let mut whitelist = MultiValueEncoded::new(); - whitelist.push(managed_address!(&address_expr_to_address( - OWNER_ADDRESS_EXPR - ))); - whitelist.push(managed_address!(&address_expr_to_address( - VAULT_ADDRESS_EXPR - ))); + whitelist.push(OWNER_ADDRESS.to_managed_address()); + whitelist.push(VAULT_ADDRESS.to_managed_address()); sc.init(whitelist); - }, - ); + }); // transfer to user - ok - world.whitebox_call( - &transfer_role_features_whitebox, - ScCallStep::new() - .from(USER_ADDRESS_EXPR) - .esdt_transfer(TRANSFER_TOKEN_ID, 0, "100"), - |sc| { + world + .tx() + .from(USER_ADDRESS) + .to(TRANSFER_ROLE_FEATURES_ADDRESS) + .single_esdt( + &TokenIdentifier::from(TRANSFER_TOKEN_ID), + 0, + &BigUint::from(100u64), + ) + .whitebox(transfer_role_features::contract_obj, |sc| { let payments = ManagedVec::from_single_item(EsdtTokenPayment::new( - managed_token_id!(TRANSFER_TOKEN_ID), + managed_token_id!(TRANSFER_TOKEN_ID_EXPR), 0, managed_biguint!(100), )); sc.transfer_to_user( - managed_address!(&address_expr_to_address(USER_ADDRESS_EXPR)), - managed_address!(&address_expr_to_address(OWNER_ADDRESS_EXPR)), + USER_ADDRESS.to_managed_address(), + OWNER_ADDRESS.to_managed_address(), &payments, managed_buffer!(b"enjoy"), ); - }, - ); + }); - world.check_state_step(CheckStateStep::new().put_account( - USER_ADDRESS_EXPR, - 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, "100"), - )); + world + .check_account(USER_ADDRESS) + .esdt_balance(TRANSFER_TOKEN_ID, BigUint::from(900u64)); + world + .check_account(OWNER_ADDRESS) + .esdt_balance(TRANSFER_TOKEN_ID, BigUint::from(100u64)); // transfer to user - err, not whitelisted - world.whitebox_call_check( - &transfer_role_features_whitebox, - ScCallStep::new() - .from(USER_ADDRESS_EXPR) - .esdt_transfer(TRANSFER_TOKEN_ID, 0, "100") - .no_expect(), - |sc| { + world + .tx() + .from(USER_ADDRESS) + .to(TRANSFER_ROLE_FEATURES_ADDRESS) + .single_esdt( + &TokenIdentifier::from(TRANSFER_TOKEN_ID), + 0, + &BigUint::from(100u64), + ) + .returns(ExpectError(4u64, "Destination address not whitelisted")) + .whitebox(transfer_role_features::contract_obj, |sc| { let payments = ManagedVec::from_single_item(EsdtTokenPayment::new( - managed_token_id!(TRANSFER_TOKEN_ID), + managed_token_id!(TRANSFER_TOKEN_ID_EXPR), 0, managed_biguint!(100), )); sc.transfer_to_user( - managed_address!(&address_expr_to_address(USER_ADDRESS_EXPR)), + USER_ADDRESS.to_managed_address(), managed_address!(&Address::zero()), &payments, managed_buffer!(b"enjoy"), ); - }, - |r| { - r.assert_user_error("Destination address not whitelisted"); - }, - ); + }); // transfer to sc - ok - world.whitebox_call( - &transfer_role_features_whitebox, - ScCallStep::new() - .from(USER_ADDRESS_EXPR) - .esdt_transfer(TRANSFER_TOKEN_ID, 0, "100"), - |sc| { + world + .tx() + .from(USER_ADDRESS) + .to(TRANSFER_ROLE_FEATURES_ADDRESS) + .single_esdt( + &TokenIdentifier::from(TRANSFER_TOKEN_ID), + 0, + &BigUint::from(100u64), + ) + .whitebox(transfer_role_features::contract_obj, |sc| { let payments = ManagedVec::from_single_item(EsdtTokenPayment::new( - managed_token_id!(TRANSFER_TOKEN_ID), + managed_token_id!(TRANSFER_TOKEN_ID_EXPR), 0, managed_biguint!(100), )); sc.transfer_to_contract_raw( - managed_address!(&address_expr_to_address(USER_ADDRESS_EXPR)), - managed_address!(&address_expr_to_address(VAULT_ADDRESS_EXPR)), + USER_ADDRESS.to_managed_address(), + VAULT_ADDRESS.to_managed_address(), &payments, managed_buffer!(ACCEPT_FUNDS_FUNC_NAME), ManagedArgBuffer::new(), None, ); - }, - ); + }); - world.check_state_step(CheckStateStep::new().put_account( - USER_ADDRESS_EXPR, - 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, "100"), - )); + world + .check_account(USER_ADDRESS) + .esdt_balance(TRANSFER_TOKEN_ID, BigUint::from(800u64)); + world + .check_account(VAULT_ADDRESS) + .esdt_balance(TRANSFER_TOKEN_ID, BigUint::from(100u64)); // transfer to sc - reject - world.whitebox_call( - &transfer_role_features_whitebox, - ScCallStep::new() - .from(USER_ADDRESS_EXPR) - .esdt_transfer(TRANSFER_TOKEN_ID, 0, "100"), - |sc| { + world + .tx() + .from(USER_ADDRESS) + .to(TRANSFER_ROLE_FEATURES_ADDRESS) + .single_esdt( + &TokenIdentifier::from(TRANSFER_TOKEN_ID), + 0, + &BigUint::from(100u64), + ) + .whitebox(transfer_role_features::contract_obj, |sc| { let payments = ManagedVec::from_single_item(EsdtTokenPayment::new( - managed_token_id!(TRANSFER_TOKEN_ID), + managed_token_id!(TRANSFER_TOKEN_ID_EXPR), 0, managed_biguint!(100), )); sc.transfer_to_contract_raw( - managed_address!(&address_expr_to_address(USER_ADDRESS_EXPR)), - managed_address!(&address_expr_to_address(VAULT_ADDRESS_EXPR)), + USER_ADDRESS.to_managed_address(), + VAULT_ADDRESS.to_managed_address(), &payments, managed_buffer!(REJECT_FUNDS_FUNC_NAME), ManagedArgBuffer::new(), None, ); - }, - ); - - world.check_state_step(CheckStateStep::new().put_account( - USER_ADDRESS_EXPR, - 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, "100"), - )); -} - -fn address_expr_to_address(address_expr: &str) -> Address { - AddressValue::from(address_expr).to_address() + }); + + world + .check_account(USER_ADDRESS) + .esdt_balance(TRANSFER_TOKEN_ID, BigUint::from(800u64)); + world + .check_account(VAULT_ADDRESS) + .esdt_balance(TRANSFER_TOKEN_ID, BigUint::from(100u64)); } 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 72b15aac66..288d3042f5 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::{ }; use multiversx_sc_scenario::imports::*; -const GOV_TOKEN_ID_EXPR: &str = "str:GOV-123456"; +const GOV_TOKEN_ID_EXPR: TestTokenIdentifier = TestTokenIdentifier::new("GOV-123456"); const GOV_TOKEN_ID: &[u8] = b"GOV-123456"; const QUORUM: u64 = 1_500; const MIN_BALANCE_PROPOSAL: u64 = 500; @@ -15,13 +15,13 @@ 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 = "mxsc:output/use-module.mxsc.json"; +const USE_MODULE_ADDRESS: TestSCAddress = TestSCAddress::new("use-module"); +const USE_MODULE_PATH_EXPR: MxscPath = MxscPath::new("mxsc:output/use-module.mxsc.json"); -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"; +const OWNER_ADDRESS: TestAddress = TestAddress::new("owner"); +const FIRST_USER_ADDRESS: TestAddress = TestAddress::new("first-user"); +const SECOND_USER_ADDRESS: TestAddress = TestAddress::new("second-user"); +const THIRD_USER_ADDRESS: TestAddress = TestAddress::new("third-user"); pub struct Payment { pub token: Vec, @@ -39,58 +39,45 @@ fn world() -> ScenarioWorld { fn setup() -> ScenarioWorld { 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, 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, INITIAL_GOV_TOKEN_BALANCE), - ) - .put_account( - SECOND_USER_ADDRESS_EXPR, - Account::new() - .nonce(1) - .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, INITIAL_GOV_TOKEN_BALANCE), - ), - ); + world + .account(OWNER_ADDRESS) + .nonce(1) + .esdt_balance(GOV_TOKEN_ID_EXPR, INITIAL_GOV_TOKEN_BALANCE); + world + .account(FIRST_USER_ADDRESS) + .nonce(1) + .esdt_balance(GOV_TOKEN_ID_EXPR, INITIAL_GOV_TOKEN_BALANCE); + world + .account(SECOND_USER_ADDRESS) + .nonce(1) + .esdt_balance(GOV_TOKEN_ID_EXPR, INITIAL_GOV_TOKEN_BALANCE); + world + .account(THIRD_USER_ADDRESS) + .nonce(1) + .esdt_balance(GOV_TOKEN_ID_EXPR, 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| { + let new_address = world + .tx() + .from(OWNER_ADDRESS) + .raw_deploy() + .code(USE_MODULE_PATH_EXPR) + .new_address(USE_MODULE_ADDRESS) + .returns(ReturnsNewBech32Address) + .whitebox(use_module::contract_obj, |sc| { sc.init_governance_module( - managed_token_id!(GOV_TOKEN_ID), - managed_biguint!(QUORUM), - managed_biguint!(MIN_BALANCE_PROPOSAL), + TokenIdentifier::from(GOV_TOKEN_ID_EXPR), + BigUint::from(QUORUM), + BigUint::from(MIN_BALANCE_PROPOSAL), VOTING_DELAY_BLOCKS, VOTING_PERIOD_BLOCKS, LOCKING_PERIOD_BLOCKS, ); - }, - ); + }); - world.set_state_step(SetStateStep::new().block_nonce(10)); + assert_eq!(new_address.to_address(), USE_MODULE_ADDRESS.to_address()); + + world.current_block().block_nonce(10); world } @@ -103,17 +90,18 @@ pub fn propose( 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, gov_token_amount), - |sc| { + world + .tx() + .from(proposer) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(GOV_TOKEN_ID_EXPR), + 0, + &BigUint::from(gov_token_amount), + ) + .whitebox(use_module::contract_obj, |sc| { let mut args_managed = ManagedVec::new(); for arg in args { args_managed.push(managed_buffer!(&arg)); @@ -131,8 +119,7 @@ pub fn propose( ); proposal_id = sc.propose(managed_buffer!(b"change quorum"), actions); - }, - ); + }); proposal_id } @@ -145,16 +132,14 @@ fn test_init() { #[test] fn test_change_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), + &FIRST_USER_ADDRESS.to_address(), 500, - &address_expr_to_address(USE_MODULE_ADDRESS_EXPR), + &USE_MODULE_ADDRESS.to_address(), b"changeQuorum", vec![1_000u64.to_be_bytes().to_vec()], ); @@ -162,209 +147,212 @@ fn test_change_gov_config() { assert_eq!(proposal_id, 1); // vote too early - world.whitebox_call_check( - &use_module_whitebox, - ScCallStep::new() - .from(SECOND_USER_ADDRESS_EXPR) - .esdt_transfer(GOV_TOKEN_ID, 0, "999") - .no_expect(), - |sc| { + world + .tx() + .from(SECOND_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(GOV_TOKEN_ID), + 0, + &BigUint::from(999u64), + ) + .returns(ExpectError(4u64, "Proposal is not active")) + .whitebox(use_module::contract_obj, |sc| { sc.vote(proposal_id, VoteType::UpVote); - }, - |r| { - 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, "999"), - |sc| { + world.current_block().block_nonce(current_block_nonce); + + world + .tx() + .from(SECOND_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(GOV_TOKEN_ID), + 0, + &BigUint::from(999u64), + ) + .whitebox(use_module::contract_obj, |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| { + world + .tx() + .from(FIRST_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .returns(ExpectError(4u64, "Can only execute queued proposals")) + .whitebox(use_module::contract_obj, |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| { + world + .tx() + .from(FIRST_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .returns(ExpectError(4u64, "Can only queue succeeded proposals")) + .whitebox(use_module::contract_obj, |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)); + world.current_block().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| { + world + .tx() + .from(FIRST_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .returns(ExpectError(4u64, "Can only queue succeeded proposals")) + .whitebox(use_module::contract_obj, |sc| { sc.queue(proposal_id); - }, - |r| { - r.assert_user_error("Can only queue succeeded proposals"); - }, - ); + }); // user 1 vote again current_block_nonce = 20; - 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, "200"), - |sc| { + world.current_block().block_nonce(current_block_nonce); + + world + .tx() + .from(FIRST_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(GOV_TOKEN_ID), + 0, + &BigUint::from(200u64), + ) + .whitebox(use_module::contract_obj, |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, "200"), - |sc| { + world + .tx() + .from(OWNER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(GOV_TOKEN_ID), + 0, + &BigUint::from(200u64), + ) + .whitebox(use_module::contract_obj, |sc| { sc.vote(proposal_id, VoteType::DownVote); - }, - ); + }); // try queue too many downvotes 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| { + world.current_block().block_nonce(current_block_nonce); + + world + .tx() + .from(FIRST_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .returns(ExpectError(4u64, "Can only queue succeeded proposals")) + .whitebox(use_module::contract_obj, |sc| { sc.queue(proposal_id); - }, - |r| { - r.assert_user_error("Can only queue succeeded proposals"); - }, - ); + }); // user 1 vote again current_block_nonce = 20; - 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) - .esdt_transfer(GOV_TOKEN_ID, 0, "200") - .no_expect(), - |sc| { + world.current_block().block_nonce(current_block_nonce); + + world + .tx() + .from(FIRST_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(GOV_TOKEN_ID), + 0, + &BigUint::from(200u64), + ) + .returns(ExpectError(4u64, "Already voted for this proposal")) + .whitebox(use_module::contract_obj, |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, "200"), - |sc| { + world + .tx() + .from(THIRD_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(GOV_TOKEN_ID), + 0, + &BigUint::from(200u64), + ) + .whitebox(use_module::contract_obj, |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| { + world.current_block().block_nonce(current_block_nonce); + + world + .tx() + .from(FIRST_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .whitebox(use_module::contract_obj, |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"); - }, - ); + world + .tx() + .from(FIRST_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .returns(ExpectError( + 4u64, + "Proposal is in timelock status. Try again later", + )) + .whitebox(use_module::contract_obj, |sc| sc.execute(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); - }, - ); + world.current_block().block_nonce(current_block_nonce); + + world + .tx() + .from(FIRST_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .whitebox(use_module::contract_obj, |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, "300"), - )); - world.check_state_step(CheckStateStep::new().put_account( - SECOND_USER_ADDRESS_EXPR, - 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, "800"), - )); - world.check_state_step(CheckStateStep::new().put_account( - OWNER_ADDRESS_EXPR, - CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, "800"), - )); + world + .query() + .to(USE_MODULE_ADDRESS) + .whitebox(use_module::contract_obj, |sc| { + assert_eq!(sc.quorum().get(), managed_biguint!(1_000)); + assert!(sc.proposals().item_is_empty(1)); + }); + + world + .check_account(FIRST_USER_ADDRESS) + .esdt_balance(GOV_TOKEN_ID_EXPR, BigUint::from(300u64)); + world + .check_account(SECOND_USER_ADDRESS) + .esdt_balance(GOV_TOKEN_ID_EXPR, BigUint::from(1u64)); + world + .check_account(THIRD_USER_ADDRESS) + .esdt_balance(GOV_TOKEN_ID_EXPR, BigUint::from(800u64)); + world + .check_account(OWNER_ADDRESS) + .esdt_balance(GOV_TOKEN_ID_EXPR, BigUint::from(800u64)); } #[test] 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), + &FIRST_USER_ADDRESS.to_address(), 500, - &address_expr_to_address(USE_MODULE_ADDRESS_EXPR), + &USE_MODULE_ADDRESS.to_address(), b"changeQuorum", vec![1_000u64.to_be_bytes().to_vec()], ); @@ -372,81 +360,87 @@ fn test_down_veto_gov_config() { 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, "300"), - |sc| { + world.current_block().block_nonce(current_block_nonce); + + world + .tx() + .from(FIRST_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(GOV_TOKEN_ID), + 0, + &BigUint::from(300u64), + ) + .whitebox(use_module::contract_obj, |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, "200"), - |sc| { + world.current_block().block_nonce(current_block_nonce); + + world + .tx() + .from(SECOND_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(GOV_TOKEN_ID), + 0, + &BigUint::from(200u64), + ) + .whitebox(use_module::contract_obj, |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, "200"), - |sc| { - sc.vote(proposal_id, VoteType::DownVetoVote); - }, - ); + world + .tx() + .from(THIRD_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(GOV_TOKEN_ID), + 0, + &BigUint::from(200u64), + ) + .whitebox(use_module::contract_obj, |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| { + world.current_block().block_epoch(current_block_nonce); + + world + .tx() + .from(FIRST_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .returns(ExpectError(4u64, "Can only queue succeeded proposals")) + .whitebox(use_module::contract_obj, |sc| { sc.queue(proposal_id); - }, - |r| { - r.assert_user_error("Can only queue succeeded proposals"); - }, - ); + }); + + world + .check_account(FIRST_USER_ADDRESS) + .esdt_balance(GOV_TOKEN_ID_EXPR, BigUint::from(200u64)); - world.check_state_step(CheckStateStep::new().put_account( - FIRST_USER_ADDRESS_EXPR, - 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, "800"), - )); - world.check_state_step(CheckStateStep::new().put_account( - THIRD_USER_ADDRESS_EXPR, - CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, "800"), - )); + world + .check_account(SECOND_USER_ADDRESS) + .esdt_balance(GOV_TOKEN_ID_EXPR, BigUint::from(800u64)); + + world + .check_account(THIRD_USER_ADDRESS) + .esdt_balance(GOV_TOKEN_ID_EXPR, BigUint::from(800u64)); } #[test] 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), + &FIRST_USER_ADDRESS.to_address(), 500, - &address_expr_to_address(USE_MODULE_ADDRESS_EXPR), + &USE_MODULE_ADDRESS.to_address(), b"changeQuorum", vec![1_000u64.to_be_bytes().to_vec()], ); @@ -454,95 +448,105 @@ fn test_abstain_vote_gov_config() { 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, "500"), - |sc| { + world.current_block().block_nonce(current_block_nonce); + + world + .tx() + .from(FIRST_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(GOV_TOKEN_ID), + 0, + &BigUint::from(500u64), + ) + .whitebox(use_module::contract_obj, |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, "400"), - |sc| { + world.current_block().block_nonce(current_block_nonce); + + world + .tx() + .from(SECOND_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(GOV_TOKEN_ID), + 0, + &BigUint::from(400u64), + ) + .whitebox(use_module::contract_obj, |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, "600"), - |sc| { + world + .tx() + .from(THIRD_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(GOV_TOKEN_ID), + 0, + &BigUint::from(600u64), + ) + .whitebox(use_module::contract_obj, |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| { + world.current_block().block_nonce(current_block_nonce); + + world + .tx() + .from(FIRST_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .whitebox(use_module::contract_obj, |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| { + world.current_block().block_nonce(current_block_nonce); + + world + .tx() + .from(FIRST_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .whitebox(use_module::contract_obj, |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, "0"), - )); - world.check_state_step(CheckStateStep::new().put_account( - SECOND_USER_ADDRESS_EXPR, - 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, "400"), - )); + world + .query() + .to(USE_MODULE_ADDRESS) + .whitebox(use_module::contract_obj, |sc| { + assert_eq!(sc.quorum().get(), managed_biguint!(1_000)); + assert!(sc.proposals().item_is_empty(1)); + }); + + world + .check_account(FIRST_USER_ADDRESS) + .esdt_balance(GOV_TOKEN_ID_EXPR, BigUint::zero()); + world + .check_account(SECOND_USER_ADDRESS) + .esdt_balance(GOV_TOKEN_ID_EXPR, BigUint::from(600u64)); + world + .check_account(THIRD_USER_ADDRESS) + .esdt_balance(GOV_TOKEN_ID_EXPR, BigUint::from(400u64)); } #[test] 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), + &FIRST_USER_ADDRESS.to_address(), 500, - &address_expr_to_address(USE_MODULE_ADDRESS_EXPR), + &USE_MODULE_ADDRESS.to_address(), b"changeQuorum", vec![1_000u64.to_be_bytes().to_vec()], ); @@ -550,42 +554,37 @@ fn test_gov_cancel_defeated_proposal() { 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, "999"), - |sc| { - sc.vote(proposal_id, VoteType::DownVote); - }, - ); + world.current_block().block_nonce(current_block_nonce); + + world + .tx() + .from(SECOND_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(GOV_TOKEN_ID), + 0, + &BigUint::from(999u64), + ) + .whitebox(use_module::contract_obj, |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| { + world + .tx() + .from(SECOND_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .returns(ExpectError(4u64, "Action may not be cancelled")) + .whitebox(use_module::contract_obj, |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); - }, - ); -} + world.current_block().block_nonce(current_block_nonce); -fn address_expr_to_address(address_expr: &str) -> Address { - AddressValue::from(address_expr).to_address() + world + .tx() + .from(SECOND_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .whitebox(use_module::contract_obj, |sc| sc.cancel(proposal_id)); } From c00a93f34d44201e5a3585c10adb6f0c578c1f04 Mon Sep 17 00:00:00 2001 From: Andrei Vasilescu Date: Thu, 22 Aug 2024 11:07:37 +0300 Subject: [PATCH 21/92] fixed unittests + small refactors --- framework/meta/src/cmd/wallet.rs | 28 +-------- framework/meta/tests/wallet_test.rs | 91 ----------------------------- sdk/core/src/wallet.rs | 24 +++++++- sdk/core/tests/wallet_test.rs | 68 +++++++++++++++++++++ 4 files changed, 94 insertions(+), 117 deletions(-) delete mode 100644 framework/meta/tests/wallet_test.rs diff --git a/framework/meta/src/cmd/wallet.rs b/framework/meta/src/cmd/wallet.rs index ba8a9f6132..b3833da517 100644 --- a/framework/meta/src/cmd/wallet.rs +++ b/framework/meta/src/cmd/wallet.rs @@ -3,7 +3,7 @@ use core::str; use crate::cli::{WalletAction, WalletArgs, WalletBech32Args, WalletConvertArgs, WalletNewArgs}; use multiversx_sc::types::{self}; use multiversx_sc_snippets::sdk::{ - crypto::public_key::PublicKey, data::address::Address, utils::base64_encode, wallet::Wallet, + crypto::public_key::PublicKey, data::address::Address, wallet::Wallet, }; use multiversx_sc_snippets::{hex, imports::Bech32Address}; use std::{ @@ -90,12 +90,12 @@ fn write_resulted_pem(public_key: &str, private_key: &str, outfile: Option<&Stri let address = get_wallet_address(private_key); match outfile { Some(outfile) => { - let pem_content = generate_pem_content(&address, private_key, public_key); + let pem_content = Wallet::generate_pem_content(&address, private_key, public_key); let mut file = File::create(outfile).unwrap(); file.write_all(pem_content.as_bytes()).unwrap(); }, None => { - let pem_content = generate_pem_content(&address, private_key, public_key); + let pem_content = Wallet::generate_pem_content(&address, private_key, public_key); print!("{}", pem_content); }, } @@ -174,25 +174,3 @@ fn new(new_args: &WalletNewArgs) { None => {}, } } - -pub fn generate_pem_content(address: &Address, private_key: &str, public_key: &str) -> String { - let concat_keys = format!("{}{}", private_key, public_key); - let concat_keys_b64 = base64_encode(concat_keys); - - // Split the base64 string into 64-character lines - let formatted_key = concat_keys_b64 - .as_bytes() - .chunks(64) - .map(|chunk| std::str::from_utf8(chunk).unwrap()) - .collect::>() - .join("\n"); - - let pem_content = format!( - "-----BEGIN PRIVATE KEY for {}-----\n{}\n-----END PRIVATE KEY for {}-----\n", - address.to_bech32_string().unwrap(), - formatted_key, - address.to_bech32_string().unwrap() - ); - - pem_content -} diff --git a/framework/meta/tests/wallet_test.rs b/framework/meta/tests/wallet_test.rs deleted file mode 100644 index ce1627ff64..0000000000 --- a/framework/meta/tests/wallet_test.rs +++ /dev/null @@ -1,91 +0,0 @@ -use std::fs::{self, File}; -use std::io::Write; - -use multiversx_sc_meta::cmd::wallet::generate_pem_content; -use multiversx_sc_snippets::sdk::{crypto::public_key::PublicKey, data::address::Address}; -use multiversx_sc_snippets::{hex, imports::Wallet}; - -const ALICE_PEM_PATH: &str = "../snippets/src/test_wallets/alice.pem"; -const ALICE_KEYSTORE_PATH_TEST: &str = "alice.json"; -const ALICE_PEM_PATH_TEST: &str = "alice_test.pem"; -const KEYSTORE_PASSWORD: &str = "abcd"; - -fn create_keystore_from_pem(file: &str) { - let pem_decoded_keys = Wallet::get_pem_decoded_content(file); - let (private_key_str, public_key_str) = Wallet::get_wallet_keys_pem(file); - - let address = Wallet::from_private_key(&private_key_str) - .unwrap() - .address(); - let hex_decoded_keys = hex::decode(pem_decoded_keys).unwrap(); - - let json_result = Wallet::encrypt_keystore( - hex_decoded_keys.as_slice(), - &address, - &public_key_str, - KEYSTORE_PASSWORD, - ); - - write_to_file(&json_result, ALICE_KEYSTORE_PATH_TEST); -} - -fn write_to_file(content: &str, file: &str) { - let mut file = File::create(file).unwrap(); - file.write_all(content.as_bytes()).unwrap(); -} - -fn create_keystore_file_from_scratch() -> Address { - let mnemonic = Wallet::generate_mnemonic(); - let (private_key_str, public_key_str) = Wallet::get_wallet_keys_mnemonic(mnemonic.to_string()); - let wallet = Wallet::from_private_key(&private_key_str).unwrap(); - let address = wallet.address(); - - let concatenated_keys = format!("{}{}", private_key_str, public_key_str); - let hex_decoded_keys = hex::decode(concatenated_keys).unwrap(); - let json_result = Wallet::encrypt_keystore( - hex_decoded_keys.as_slice(), - &address, - &public_key_str, - KEYSTORE_PASSWORD, - ); - write_to_file(&json_result, ALICE_KEYSTORE_PATH_TEST); - address -} - -#[test] -fn test_wallet_convert_pem_to_keystore() { - create_keystore_from_pem(ALICE_PEM_PATH); - let (private_key_pem, _public_key_pem) = Wallet::get_wallet_keys_pem(ALICE_PEM_PATH); - assert_eq!( - Wallet::get_private_key_from_keystore_secret(ALICE_KEYSTORE_PATH_TEST, KEYSTORE_PASSWORD) - .unwrap() - .to_string(), - private_key_pem - ); - fs::remove_file(ALICE_KEYSTORE_PATH_TEST).unwrap(); -} - -#[test] -fn test_wallet_convert_keystore_to_pem() { - let address = create_keystore_file_from_scratch(); - - let private_key = - Wallet::get_private_key_from_keystore_secret(ALICE_KEYSTORE_PATH_TEST, KEYSTORE_PASSWORD) - .unwrap(); - let private_key_str = private_key.to_string(); - let public_key = PublicKey::from(&private_key); - let public_key_str = public_key.to_string(); - - let pem_content = generate_pem_content(&address, &private_key_str, &public_key_str); - write_to_file(&pem_content, ALICE_PEM_PATH_TEST); - - assert_eq!( - Wallet::get_private_key_from_keystore_secret(ALICE_KEYSTORE_PATH_TEST, KEYSTORE_PASSWORD) - .unwrap() - .to_string(), - Wallet::get_wallet_keys_pem(ALICE_PEM_PATH_TEST).0 - ); - - fs::remove_file(ALICE_PEM_PATH_TEST).unwrap(); - fs::remove_file(ALICE_KEYSTORE_PATH_TEST).unwrap(); -} diff --git a/sdk/core/src/wallet.rs b/sdk/core/src/wallet.rs index bbf2c41a2c..bf1362a314 100644 --- a/sdk/core/src/wallet.rs +++ b/sdk/core/src/wallet.rs @@ -25,7 +25,7 @@ use crate::{ public_key::PublicKey, }, data::{address::Address, keystore::*, transaction::Transaction}, - utils::base64_decode, + utils::*, }; use uuid::Uuid; @@ -333,4 +333,26 @@ impl Wallet { keystore_json.push('\n'); keystore_json } + + pub fn generate_pem_content(address: &Address, private_key: &str, public_key: &str) -> String { + let concat_keys = format!("{}{}", private_key, public_key); + let concat_keys_b64 = base64_encode(concat_keys); + + // Split the base64 string into 64-character lines + let formatted_key = concat_keys_b64 + .as_bytes() + .chunks(64) + .map(|chunk| std::str::from_utf8(chunk).unwrap()) + .collect::>() + .join("\n"); + + let pem_content = format!( + "-----BEGIN PRIVATE KEY for {}-----\n{}\n-----END PRIVATE KEY for {}-----\n", + address.to_bech32_string().unwrap(), + formatted_key, + address.to_bech32_string().unwrap() + ); + + pem_content + } } diff --git a/sdk/core/tests/wallet_test.rs b/sdk/core/tests/wallet_test.rs index d076980084..4d523d57d5 100644 --- a/sdk/core/tests/wallet_test.rs +++ b/sdk/core/tests/wallet_test.rs @@ -1,6 +1,18 @@ use bip39::Mnemonic; use multiversx_sdk::{crypto::public_key::PublicKey, data::address::Address, wallet::Wallet}; +use std::fs::{self, File}; +use std::io::Write; + +// use multiversx_sc_meta::cmd::wallet::generate_pem_content; +// use multiversx_sc_snippets::{hex, imports::Wallet}; + +const ALICE_PEM_PATH: &str = "tests/alice.pem"; +const ALICE_KEYSTORE_PATH_TEST: &str = "tests/alice.json"; +const ALICE_PEM_PATH_TEST: &str = "tests/alice_test.pem"; +const KEYSTORE_PASSWORD: &str = "abcd"; +const ALICE_PUBLIC_KEY: &str = "0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1"; +const ALICE_PRIVATE_KEY: &str = "413f42575f7f26fad3317a778771212fdb80245850981e48b58a4f25e344e8f9"; #[test] fn test_private_key_from_mnemonic() { @@ -48,3 +60,59 @@ fn test_load_from_pem() { "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th" ); } + +fn write_to_file(content: &str, file: &str) { + let mut file = File::create(file).unwrap(); + file.write_all(content.as_bytes()).unwrap(); +} + +fn create_keystore_file_from_scratch() -> Address { + let wallet = Wallet::from_private_key(ALICE_PRIVATE_KEY).unwrap(); + let address = wallet.address(); + + let concatenated_keys = format!("{}{}", ALICE_PRIVATE_KEY, ALICE_PUBLIC_KEY); + let hex_decoded_keys = hex::decode(concatenated_keys).unwrap(); + let json_result = Wallet::encrypt_keystore( + hex_decoded_keys.as_slice(), + &address, + ALICE_PUBLIC_KEY, + KEYSTORE_PASSWORD, + ); + write_to_file(&json_result, ALICE_KEYSTORE_PATH_TEST); + address +} + +#[test] +fn test_wallet_convert_pem_to_keystore() { + let _ = create_keystore_file_from_scratch(); + let (private_key_pem, _public_key_pem) = Wallet::get_wallet_keys_pem(ALICE_PEM_PATH); + assert_eq!( + Wallet::get_private_key_from_keystore_secret(ALICE_KEYSTORE_PATH_TEST, KEYSTORE_PASSWORD) + .unwrap() + .to_string(), + private_key_pem + ); + fs::remove_file(ALICE_KEYSTORE_PATH_TEST).unwrap(); +} + +#[test] +fn test_wallet_convert_keystore_to_pem() { + let address = create_keystore_file_from_scratch(); + + let private_key = + Wallet::get_private_key_from_keystore_secret(ALICE_KEYSTORE_PATH_TEST, KEYSTORE_PASSWORD) + .unwrap(); + let private_key_str = private_key.to_string(); + let public_key = PublicKey::from(&private_key); + let public_key_str = public_key.to_string(); + + let pem_content = Wallet::generate_pem_content(&address, &private_key_str, &public_key_str); + write_to_file(&pem_content, ALICE_PEM_PATH_TEST); + assert_eq!( + private_key_str, + Wallet::get_wallet_keys_pem(ALICE_PEM_PATH_TEST).0 + ); + + fs::remove_file(ALICE_PEM_PATH_TEST).unwrap(); + fs::remove_file(ALICE_KEYSTORE_PATH_TEST).unwrap(); +} From dbca030977779beddf38332f0da6a2d256fd5f67 Mon Sep 17 00:00:00 2001 From: Andrei Vasilescu Date: Thu, 22 Aug 2024 11:30:31 +0300 Subject: [PATCH 22/92] tests fixed --- sdk/core/tests/wallet_test.rs | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/sdk/core/tests/wallet_test.rs b/sdk/core/tests/wallet_test.rs index 4d523d57d5..103166e430 100644 --- a/sdk/core/tests/wallet_test.rs +++ b/sdk/core/tests/wallet_test.rs @@ -4,11 +4,9 @@ use multiversx_sdk::{crypto::public_key::PublicKey, data::address::Address, wall use std::fs::{self, File}; use std::io::Write; -// use multiversx_sc_meta::cmd::wallet::generate_pem_content; -// use multiversx_sc_snippets::{hex, imports::Wallet}; - const ALICE_PEM_PATH: &str = "tests/alice.pem"; -const ALICE_KEYSTORE_PATH_TEST: &str = "tests/alice.json"; +const ALICE_KEYSTORE_PATH_TEST_1: &str = "tests/alice1.json"; +const ALICE_KEYSTORE_PATH_TEST_2: &str = "tests/alice2.json"; const ALICE_PEM_PATH_TEST: &str = "tests/alice_test.pem"; const KEYSTORE_PASSWORD: &str = "abcd"; const ALICE_PUBLIC_KEY: &str = "0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1"; @@ -66,7 +64,7 @@ fn write_to_file(content: &str, file: &str) { file.write_all(content.as_bytes()).unwrap(); } -fn create_keystore_file_from_scratch() -> Address { +fn create_keystore_file_from_scratch(file: &str) -> Address { let wallet = Wallet::from_private_key(ALICE_PRIVATE_KEY).unwrap(); let address = wallet.address(); @@ -78,29 +76,29 @@ fn create_keystore_file_from_scratch() -> Address { ALICE_PUBLIC_KEY, KEYSTORE_PASSWORD, ); - write_to_file(&json_result, ALICE_KEYSTORE_PATH_TEST); + write_to_file(&json_result, file); address } #[test] fn test_wallet_convert_pem_to_keystore() { - let _ = create_keystore_file_from_scratch(); + let _ = create_keystore_file_from_scratch(ALICE_KEYSTORE_PATH_TEST_1); let (private_key_pem, _public_key_pem) = Wallet::get_wallet_keys_pem(ALICE_PEM_PATH); assert_eq!( - Wallet::get_private_key_from_keystore_secret(ALICE_KEYSTORE_PATH_TEST, KEYSTORE_PASSWORD) + Wallet::get_private_key_from_keystore_secret(ALICE_KEYSTORE_PATH_TEST_1, KEYSTORE_PASSWORD) .unwrap() .to_string(), private_key_pem ); - fs::remove_file(ALICE_KEYSTORE_PATH_TEST).unwrap(); + fs::remove_file(ALICE_KEYSTORE_PATH_TEST_1).unwrap(); } #[test] fn test_wallet_convert_keystore_to_pem() { - let address = create_keystore_file_from_scratch(); + let address = create_keystore_file_from_scratch(ALICE_KEYSTORE_PATH_TEST_2); let private_key = - Wallet::get_private_key_from_keystore_secret(ALICE_KEYSTORE_PATH_TEST, KEYSTORE_PASSWORD) + Wallet::get_private_key_from_keystore_secret(ALICE_KEYSTORE_PATH_TEST_2, KEYSTORE_PASSWORD) .unwrap(); let private_key_str = private_key.to_string(); let public_key = PublicKey::from(&private_key); @@ -114,5 +112,5 @@ fn test_wallet_convert_keystore_to_pem() { ); fs::remove_file(ALICE_PEM_PATH_TEST).unwrap(); - fs::remove_file(ALICE_KEYSTORE_PATH_TEST).unwrap(); + fs::remove_file(ALICE_KEYSTORE_PATH_TEST_2).unwrap(); } From fe2ef22db0e59c5450b6ef7c9191ae124df634cc Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Thu, 22 Aug 2024 14:55:24 +0200 Subject: [PATCH 23/92] multisig whitebox migration --- .../multisig/tests/multisig_whitebox_test.rs | 929 ++++++++---------- 1 file changed, 426 insertions(+), 503 deletions(-) diff --git a/contracts/examples/multisig/tests/multisig_whitebox_test.rs b/contracts/examples/multisig/tests/multisig_whitebox_test.rs index 904a03c7e0..5e1347d82b 100644 --- a/contracts/examples/multisig/tests/multisig_whitebox_test.rs +++ b/contracts/examples/multisig/tests/multisig_whitebox_test.rs @@ -10,11 +10,11 @@ use multisig::{ user_role::UserRole, Multisig, }; -const OWNER_ADDRESS_EXPR: &str = "address:owner"; -const PROPOSER_ADDRESS_EXPR: &str = "address:proposer"; -const BOARD_MEMBER_ADDRESS_EXPR: &str = "address:board-member"; -const MULTISIG_ADDRESS_EXPR: &str = "sc:multisig"; -const MULTISIG_PATH_EXPR: &str = "mxsc:output/multisig.mxsc.json"; +const OWNER_ADDRESS: TestAddress = TestAddress::new("owner"); +const PROPOSER_ADDRESS: TestAddress = TestAddress::new("proposer"); +const BOARD_MEMBER_ADDRESS: TestAddress = TestAddress::new("board-member"); +const MULTISIG_ADDRESS: TestSCAddress = TestSCAddress::new("multisig"); +const MULTISIG_PATH_EXPR: MxscPath = MxscPath::new("mxsc:output/multisig.mxsc.json"); const QUORUM_SIZE: usize = 1; type RustBigUint = num_bigint::BigUint; @@ -59,40 +59,28 @@ fn world() -> ScenarioWorld { fn setup() -> ScenarioWorld { // setup let mut world = world(); - let multisig_whitebox = WhiteboxContract::new(MULTISIG_ADDRESS_EXPR, multisig::contract_obj); - let multisig_code = world.code_expression(MULTISIG_PATH_EXPR); - - world.set_state_step( - SetStateStep::new() - .put_account(OWNER_ADDRESS_EXPR, Account::new().nonce(1)) - .new_address(OWNER_ADDRESS_EXPR, 1, MULTISIG_ADDRESS_EXPR) - .put_account( - PROPOSER_ADDRESS_EXPR, - Account::new().nonce(1).balance(100_000_000u64), - ) - .put_account(BOARD_MEMBER_ADDRESS_EXPR, Account::new().nonce(1)), - ); + + world.account(OWNER_ADDRESS).nonce(1); + world + .account(PROPOSER_ADDRESS) + .nonce(1) + .balance(100_000_000u64); + world.account(BOARD_MEMBER_ADDRESS).nonce(1); // init multisig - world.whitebox_deploy( - &multisig_whitebox, - ScDeployStep::new() - .from(OWNER_ADDRESS_EXPR) - .code(multisig_code), - |sc| { + world + .tx() + .from(OWNER_ADDRESS) + .raw_deploy() + .code(MULTISIG_PATH_EXPR) + .new_address(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| { let mut board_members = ManagedVec::new(); - board_members.push(managed_address!(&address_expr_to_address( - BOARD_MEMBER_ADDRESS_EXPR - ))); + board_members.push(BOARD_MEMBER_ADDRESS.to_managed_address()); sc.init(QUORUM_SIZE, board_members.into()); - sc.change_user_role( - 0, - managed_address!(&address_expr_to_address(PROPOSER_ADDRESS_EXPR)), - UserRole::Proposer, - ); - }, - ); + sc.change_user_role(0, PROPOSER_ADDRESS.to_managed_address(), UserRole::Proposer); + }); world } @@ -119,70 +107,66 @@ fn call_propose( let mut action_id = 0; - let multisig_whitebox = WhiteboxContract::new(MULTISIG_ADDRESS_EXPR, multisig::contract_obj); - - world.whitebox_call_check( - &multisig_whitebox, - ScCallStep::new() - .from(PROPOSER_ADDRESS_EXPR) - .egld_value(amount_rust_biguint) - .no_expect(), - |sc| { - action_id = match action { - ActionRaw::_Nothing => panic!("Invalid action"), - ActionRaw::AddBoardMember(addr) => { - sc.propose_add_board_member(managed_address!(&addr)) + let mut transaction = world + .tx() + .from(PROPOSER_ADDRESS) + .to(MULTISIG_ADDRESS) + .egld(BigUint::from(egld_amount)); + + let mut transaction_with_err = match expected_message { + Some(message) => transaction.returns(ExpectError(4u64, message)), + None => transaction.returns(ExpectError(0u64, "")), + }; + + transaction_with_err.whitebox(multisig::contract_obj, |sc| { + action_id = match action { + ActionRaw::_Nothing => panic!("Invalid action"), + ActionRaw::AddBoardMember(addr) => sc.propose_add_board_member(managed_address!(&addr)), + ActionRaw::AddProposer(addr) => sc.propose_add_proposer(managed_address!(&addr)), + ActionRaw::RemoveUser(addr) => sc.propose_remove_user(managed_address!(&addr)), + ActionRaw::ChangeQuorum(new_size) => sc.propose_change_quorum(new_size), + ActionRaw::SendTransferExecute(call_data) => sc.propose_transfer_execute( + managed_address!(&call_data.to), + call_data.egld_amount.into(), + FunctionCall { + function_name: call_data.endpoint_name.into(), + arg_buffer: call_data.arguments.into(), }, - ActionRaw::AddProposer(addr) => sc.propose_add_proposer(managed_address!(&addr)), - ActionRaw::RemoveUser(addr) => sc.propose_remove_user(managed_address!(&addr)), - ActionRaw::ChangeQuorum(new_size) => sc.propose_change_quorum(new_size), - ActionRaw::SendTransferExecute(call_data) => sc.propose_transfer_execute( - managed_address!(&call_data.to), - BigUint::from_bytes_be(&call_data.egld_amount.to_bytes_be()), - FunctionCall { - function_name: call_data.endpoint_name.into(), - arg_buffer: call_data.arguments.into(), - }, - ), - ActionRaw::SendAsyncCall(call_data) => sc.propose_async_call( - managed_address!(&call_data.to), - BigUint::from_bytes_be(&call_data.egld_amount.to_bytes_be()), - FunctionCall { - function_name: call_data.endpoint_name.into(), - arg_buffer: call_data.arguments.into(), - }, - ), - ActionRaw::SCDeployFromSource { - amount, - source, - code_metadata, - arguments, - } => sc.propose_sc_deploy_from_source( - BigUint::from_bytes_be(&amount.to_bytes_be()), - managed_address!(&source), - code_metadata, - boxed_bytes_vec_to_managed(arguments).into(), - ), - ActionRaw::SCUpgradeFromSource { - sc_address, - amount, - source, - code_metadata, - arguments, - } => sc.propose_sc_upgrade_from_source( - managed_address!(&sc_address), - BigUint::from_bytes_be(&amount.to_bytes_be()), - managed_address!(&source), - code_metadata, - boxed_bytes_vec_to_managed(arguments).into(), - ), - } - }, - |r| match expected_message { - Some(msg) => r.assert_user_error(msg), - None => r.assert_ok(), - }, - ); + ), + ActionRaw::SendAsyncCall(call_data) => sc.propose_async_call( + managed_address!(&call_data.to), + call_data.egld_amount.into(), + FunctionCall { + function_name: call_data.endpoint_name.into(), + arg_buffer: call_data.arguments.into(), + }, + ), + ActionRaw::SCDeployFromSource { + amount, + source, + code_metadata, + arguments, + } => sc.propose_sc_deploy_from_source( + amount.into(), + managed_address!(&source), + code_metadata, + boxed_bytes_vec_to_managed(arguments).into(), + ), + ActionRaw::SCUpgradeFromSource { + sc_address, + amount, + source, + code_metadata, + arguments, + } => sc.propose_sc_upgrade_from_source( + managed_address!(&sc_address), + amount.into(), + managed_address!(&source), + code_metadata, + boxed_bytes_vec_to_managed(arguments).into(), + ), + } + }); action_id } @@ -190,341 +174,300 @@ fn call_propose( #[test] fn test_add_board_member() { let mut world = setup(); - let multisig_whitebox = WhiteboxContract::new(MULTISIG_ADDRESS_EXPR, multisig::contract_obj); - const NEW_BOARD_MEMBER_ADDRESS_EXPR: &str = "address:new-board-member"; - world.set_state_step( - SetStateStep::new().put_account(NEW_BOARD_MEMBER_ADDRESS_EXPR, Account::new().nonce(1)), - ); + const NEW_BOARD_MEMBER_ADDRESS: TestAddress = TestAddress::new("new-board-member"); + world.account(NEW_BOARD_MEMBER_ADDRESS).nonce(1); - world.whitebox_query(&multisig_whitebox, |sc| { - // check role before - let user_role = sc.user_role(managed_address!(&address_expr_to_address( - NEW_BOARD_MEMBER_ADDRESS_EXPR - ))); - assert_eq!(user_role, UserRole::None); - }); + world + .query() + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| { + // check role before + let user_role = sc.user_role(NEW_BOARD_MEMBER_ADDRESS.to_managed_address()); + assert_eq!(user_role, UserRole::None); + }); let action_id = call_propose( &mut world, - ActionRaw::AddBoardMember(address_expr_to_address(NEW_BOARD_MEMBER_ADDRESS_EXPR)), + ActionRaw::AddBoardMember(NEW_BOARD_MEMBER_ADDRESS.to_address()), None, ); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| sc.sign(action_id), - ); + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| sc.sign(action_id)); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| { + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| { let _ = sc.perform_action_endpoint(action_id); - }, - ); + }); - world.whitebox_query(&multisig_whitebox, |sc| { - // check role after - let user_role = sc.user_role(managed_address!(&address_expr_to_address( - NEW_BOARD_MEMBER_ADDRESS_EXPR - ))); - assert_eq!(user_role, UserRole::BoardMember); - - let board_members = sc.get_all_board_members().to_vec(); - assert_eq!( - (board_members.get(0).borrow() as &ManagedAddress).clone(), - managed_address!(&address_expr_to_address(BOARD_MEMBER_ADDRESS_EXPR)) - ); - assert_eq!( - (board_members.get(1).borrow() as &ManagedAddress).clone(), - managed_address!(&address_expr_to_address(NEW_BOARD_MEMBER_ADDRESS_EXPR)) - ); - }); + world + .query() + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| { + // check role after + let user_role = sc.user_role(NEW_BOARD_MEMBER_ADDRESS.to_managed_address()); + assert_eq!(user_role, UserRole::BoardMember); + + let board_members = sc.get_all_board_members().to_vec(); + assert_eq!(*board_members.get(0), BOARD_MEMBER_ADDRESS); + assert_eq!(*board_members.get(1), NEW_BOARD_MEMBER_ADDRESS); + }); } #[test] fn test_add_proposer() { let mut world = setup(); - let multisig_whitebox = WhiteboxContract::new(MULTISIG_ADDRESS_EXPR, multisig::contract_obj); - const NEW_PROPOSER_ADDRESS_EXPR: &str = "address:new-proposer"; - world.set_state_step( - SetStateStep::new().put_account(NEW_PROPOSER_ADDRESS_EXPR, Account::new().nonce(1)), - ); + const NEW_PROPOSER_ADDRESS: TestAddress = TestAddress::new("new-proposer"); + world.account(NEW_PROPOSER_ADDRESS).nonce(1); - world.whitebox_query(&multisig_whitebox, |sc| { - // check role before - let user_role = sc.user_role(managed_address!(&address_expr_to_address( - NEW_PROPOSER_ADDRESS_EXPR - ))); - assert_eq!(user_role, UserRole::None); - }); + world + .query() + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| { + // check role before + let user_role = sc.user_role(NEW_PROPOSER_ADDRESS.to_managed_address()); + assert_eq!(user_role, UserRole::None); + }); let action_id = call_propose( &mut world, - ActionRaw::AddProposer(address_expr_to_address(NEW_PROPOSER_ADDRESS_EXPR)), + ActionRaw::AddProposer(NEW_PROPOSER_ADDRESS.to_address()), None, ); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| sc.sign(action_id), - ); + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| sc.sign(action_id)); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| { + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| { let _ = sc.perform_action_endpoint(action_id); - }, - ); + }); - world.whitebox_query(&multisig_whitebox, |sc| { - // check role after - let user_role = sc.user_role(managed_address!(&address_expr_to_address( - NEW_PROPOSER_ADDRESS_EXPR - ))); - assert_eq!(user_role, UserRole::Proposer); - - let proposers = sc.get_all_proposers().to_vec(); - assert_eq!( - (proposers.get(0).borrow() as &ManagedAddress).clone(), - managed_address!(&address_expr_to_address(PROPOSER_ADDRESS_EXPR)) - ); - assert_eq!( - (proposers.get(1).borrow() as &ManagedAddress).clone(), - managed_address!(&address_expr_to_address(NEW_PROPOSER_ADDRESS_EXPR)) - ); - }); + world + .query() + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| { + // check role after + let user_role = sc.user_role(NEW_PROPOSER_ADDRESS.to_managed_address()); + assert_eq!(user_role, UserRole::Proposer); + + let proposers = sc.get_all_proposers().to_vec(); + assert_eq!(*proposers.get(0), PROPOSER_ADDRESS); + assert_eq!(*proposers.get(1), NEW_PROPOSER_ADDRESS); + }); } #[test] fn test_remove_proposer() { let mut world = setup(); - let multisig_whitebox = WhiteboxContract::new(MULTISIG_ADDRESS_EXPR, multisig::contract_obj); - - world.whitebox_query(&multisig_whitebox, |sc| { - // check role before - let user_role = sc.user_role(managed_address!(&address_expr_to_address( - PROPOSER_ADDRESS_EXPR - ))); - assert_eq!(user_role, UserRole::Proposer); - }); + + world + .query() + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| { + // check role before + let user_role = sc.user_role(PROPOSER_ADDRESS.to_managed_address()); + assert_eq!(user_role, UserRole::Proposer); + }); let action_id = call_propose( &mut world, - ActionRaw::RemoveUser(address_expr_to_address(PROPOSER_ADDRESS_EXPR)), + ActionRaw::RemoveUser(PROPOSER_ADDRESS.to_address()), None, ); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| sc.sign(action_id), - ); + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| sc.sign(action_id)); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| { + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| { let _ = sc.perform_action_endpoint(action_id); - }, - ); + }); - world.whitebox_query(&multisig_whitebox, |sc| { - // check role after - let user_role = sc.user_role(managed_address!(&address_expr_to_address( - PROPOSER_ADDRESS_EXPR - ))); - assert_eq!(user_role, UserRole::None); - - let proposers = sc.get_all_proposers().to_vec(); - assert!(proposers.is_empty()); - }); + world + .query() + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| { + // check role after + let user_role = sc.user_role(PROPOSER_ADDRESS.to_managed_address()); + assert_eq!(user_role, UserRole::None); + + let proposers = sc.get_all_proposers(); + assert!(proposers.is_empty()); + }); } #[test] fn test_try_remove_all_board_members() { let mut world = setup(); - let multisig_whitebox = WhiteboxContract::new(MULTISIG_ADDRESS_EXPR, multisig::contract_obj); let action_id = call_propose( &mut world, - ActionRaw::RemoveUser(address_expr_to_address(BOARD_MEMBER_ADDRESS_EXPR)), + ActionRaw::RemoveUser(BOARD_MEMBER_ADDRESS.to_address()), None, ); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| sc.sign(action_id), - ); + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| sc.sign(action_id)); - world.whitebox_call_check( - &multisig_whitebox, - ScCallStep::new() - .from(BOARD_MEMBER_ADDRESS_EXPR) - .no_expect(), - |sc| { + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .returns(ExpectError(4u64, "quorum cannot exceed board size")) + .whitebox(multisig::contract_obj, |sc| { let _ = sc.perform_action_endpoint(action_id); - }, - |r| { - r.assert_user_error("quorum cannot exceed board size"); - }, - ); + }); } #[test] fn test_change_quorum() { let mut world = setup(); - let multisig_whitebox = WhiteboxContract::new(MULTISIG_ADDRESS_EXPR, multisig::contract_obj); let new_quorum_size = 2; // try change quorum > board size let action_id = call_propose(&mut world, ActionRaw::ChangeQuorum(new_quorum_size), None); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| sc.sign(action_id), - ); + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| sc.sign(action_id)); - world.whitebox_call_check( - &multisig_whitebox, - ScCallStep::new() - .from(BOARD_MEMBER_ADDRESS_EXPR) - .no_expect(), - |sc| { + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .returns(ExpectError(4u64, "quorum cannot exceed board size")) + .whitebox(multisig::contract_obj, |sc| { let _ = sc.perform_action_endpoint(action_id); - }, - |r| { - r.assert_user_error("quorum cannot exceed board size"); - }, - ); + }); // try discard before unsigning - world.whitebox_call_check( - &multisig_whitebox, - ScCallStep::new() - .from(BOARD_MEMBER_ADDRESS_EXPR) - .no_expect(), - |sc| { - sc.discard_action(action_id); - }, - |r| { - r.assert_user_error("cannot discard action with valid signatures"); - }, - ); + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .returns(ExpectError( + 4u64, + "cannot discard action with valid signatures", + )) + .whitebox(multisig::contract_obj, |sc| sc.discard_action(action_id)); // unsign and discard action - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| sc.unsign(action_id), - ); + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| sc.unsign(action_id)); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| { - sc.discard_action(action_id); - }, - ); + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| sc.discard_action(action_id)); // try sign discarded action - world.whitebox_call_check( - &multisig_whitebox, - ScCallStep::new() - .from(BOARD_MEMBER_ADDRESS_EXPR) - .no_expect(), - |sc| { + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .returns(ExpectError(4u64, "action does not exist")) + .whitebox(multisig::contract_obj, |sc| { sc.sign(action_id); - }, - |r| { - r.assert_user_error("action does not exist"); - }, - ); + }); // add another board member - const NEW_BOARD_MEMBER_ADDRESS_EXPR: &str = "address:new-board-member"; - world.set_state_step( - SetStateStep::new().put_account(NEW_BOARD_MEMBER_ADDRESS_EXPR, Account::new().nonce(1)), - ); + const NEW_BOARD_MEMBER_ADDRESS: TestAddress = TestAddress::new("new-board-member"); + world.account(NEW_BOARD_MEMBER_ADDRESS).nonce(1); let action_id = call_propose( &mut world, - ActionRaw::AddBoardMember(address_expr_to_address(NEW_BOARD_MEMBER_ADDRESS_EXPR)), + ActionRaw::AddBoardMember(NEW_BOARD_MEMBER_ADDRESS.to_address()), None, ); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| sc.sign(action_id), - ); + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| sc.sign(action_id)); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| { + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| { let _ = sc.perform_action_endpoint(action_id); - }, - ); + }); // change quorum to 2 let action_id = call_propose(&mut world, ActionRaw::ChangeQuorum(new_quorum_size), None); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| sc.sign(action_id), - ); + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| sc.sign(action_id)); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| { + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| { let _ = sc.perform_action_endpoint(action_id); - }, - ); + }); } #[test] fn test_transfer_execute_to_user() { let mut world = setup(); - let multisig_whitebox = WhiteboxContract::new(MULTISIG_ADDRESS_EXPR, multisig::contract_obj); - const NEW_USER_ADDRESS_EXPR: &str = "address:new-user"; - world.set_state_step( - SetStateStep::new().put_account(NEW_USER_ADDRESS_EXPR, Account::new().nonce(1)), - ); + const NEW_USER_ADDRESS: TestAddress = TestAddress::new("new-user"); + world.account(NEW_USER_ADDRESS).nonce(1); const EGLD_AMOUNT: u64 = 100; - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new() - .from(PROPOSER_ADDRESS_EXPR) - .egld_value(EGLD_AMOUNT), - |sc| { + world + .tx() + .from(PROPOSER_ADDRESS) + .to(MULTISIG_ADDRESS) + .egld(EGLD_AMOUNT) + .whitebox(multisig::contract_obj, |sc| { sc.deposit(); - }, - ); + }); - world.check_state_step(CheckStateStep::new().put_account( - MULTISIG_ADDRESS_EXPR, - CheckAccount::new().balance(EGLD_AMOUNT.to_string().as_str()), - )); + world.check_account(MULTISIG_ADDRESS).balance(EGLD_AMOUNT); // failed attempt let action_id = call_propose( &mut world, ActionRaw::SendTransferExecute(CallActionDataRaw { - to: address_expr_to_address(NEW_USER_ADDRESS_EXPR), + to: NEW_USER_ADDRESS.to_address(), egld_amount: rust_biguint!(0), endpoint_name: BoxedBytes::empty(), arguments: Vec::new(), @@ -536,7 +479,7 @@ fn test_transfer_execute_to_user() { let action_id = call_propose( &mut world, ActionRaw::SendTransferExecute(CallActionDataRaw { - to: address_expr_to_address(NEW_USER_ADDRESS_EXPR), + to: NEW_USER_ADDRESS.to_address(), egld_amount: rust_biguint!(EGLD_AMOUNT), endpoint_name: BoxedBytes::empty(), arguments: Vec::new(), @@ -544,59 +487,48 @@ fn test_transfer_execute_to_user() { None, ); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| sc.sign(action_id), - ); + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| sc.sign(action_id)); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| { + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| { let _ = sc.perform_action_endpoint(action_id); - }, - ); + }); - world.check_state_step(CheckStateStep::new().put_account( - NEW_USER_ADDRESS_EXPR, - CheckAccount::new().balance(EGLD_AMOUNT.to_string().as_str()), - )); + world.check_account(NEW_USER_ADDRESS).balance(EGLD_AMOUNT); } #[test] fn test_transfer_execute_sc_all() { let mut world = setup(); - let multisig_whitebox = WhiteboxContract::new(MULTISIG_ADDRESS_EXPR, multisig::contract_obj); - - let adder_whitebox = WhiteboxContract::new(ADDER_ADDRESS_EXPR, adder::contract_obj); - let adder_code = world.code_expression(ADDER_PATH_EXPR); - const ADDER_OWNER_ADDRESS_EXPR: &str = "address:adder-owner"; - const ADDER_ADDRESS_EXPR: &str = "sc:adder"; - const ADDER_PATH_EXPR: &str = "mxsc:test-contracts/adder.mxsc.json"; + const ADDER_OWNER_ADDRESS: TestAddress = TestAddress::new("adder-owner"); + const ADDER_ADDRESS: TestSCAddress = TestSCAddress::new("adder"); + const ADDER_PATH_EXPR: MxscPath = MxscPath::new("mxsc:test-contracts/adder.mxsc.json"); world.register_contract(ADDER_PATH_EXPR, adder::ContractBuilder); - world.set_state_step( - SetStateStep::new() - .put_account(ADDER_OWNER_ADDRESS_EXPR, Account::new().nonce(1)) - .new_address(ADDER_OWNER_ADDRESS_EXPR, 1, ADDER_ADDRESS_EXPR), - ); + world.account(ADDER_OWNER_ADDRESS).nonce(1); - world.whitebox_deploy( - &adder_whitebox, - ScDeployStep::new() - .from(ADDER_OWNER_ADDRESS_EXPR) - .code(adder_code), - |sc| { - sc.init(managed_biguint!(5)); - }, - ); + world + .tx() + .raw_deploy() + .from(ADDER_OWNER_ADDRESS) + .code(ADDER_PATH_EXPR) + .new_address(ADDER_ADDRESS) + .whitebox(adder::contract_obj, |sc| { + sc.init(BigUint::from(5u64)); + }); let action_id = call_propose( &mut world, ActionRaw::SendTransferExecute(CallActionDataRaw { - to: address_expr_to_address(ADDER_ADDRESS_EXPR), + to: ADDER_ADDRESS.to_address(), egld_amount: 0u64.into(), endpoint_name: BoxedBytes::from(&b"add"[..]), arguments: vec![BoxedBytes::from(&[5u8][..])], @@ -604,60 +536,55 @@ fn test_transfer_execute_sc_all() { None, ); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| sc.sign(action_id), - ); + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| sc.sign(action_id)); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| { + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| { let _ = sc.perform_action_endpoint(action_id); - }, - ); + }); - world.whitebox_query(&adder_whitebox, |sc| { - let actual_sum = sc.sum().get(); - let expected_sum = managed_biguint!(10); - assert_eq!(actual_sum, expected_sum); - }); + world + .query() + .to(ADDER_ADDRESS) + .whitebox(adder::contract_obj, |sc| { + let actual_sum = sc.sum().get(); + let expected_sum = managed_biguint!(10); + assert_eq!(actual_sum, expected_sum); + }); } #[test] fn test_async_call_to_sc() { let mut world = setup(); - let multisig_whitebox = WhiteboxContract::new(MULTISIG_ADDRESS_EXPR, multisig::contract_obj); - - let adder_whitebox = WhiteboxContract::new(ADDER_ADDRESS_EXPR, adder::contract_obj); - let adder_code = world.code_expression(ADDER_PATH_EXPR); - const ADDER_OWNER_ADDRESS_EXPR: &str = "address:adder-owner"; - const ADDER_ADDRESS_EXPR: &str = "sc:adder"; - const ADDER_PATH_EXPR: &str = "mxsc:test-contracts/adder.mxsc.json"; + const ADDER_OWNER_ADDRESS: TestAddress = TestAddress::new("adder-owner"); + const ADDER_ADDRESS: TestSCAddress = TestSCAddress::new("adder"); + const ADDER_PATH_EXPR: MxscPath = MxscPath::new("mxsc:test-contracts/adder.mxsc.json"); world.register_contract(ADDER_PATH_EXPR, adder::ContractBuilder); - world.set_state_step( - SetStateStep::new() - .put_account(ADDER_OWNER_ADDRESS_EXPR, Account::new().nonce(1)) - .new_address(ADDER_OWNER_ADDRESS_EXPR, 1, ADDER_ADDRESS_EXPR), - ); + world.account(ADDER_OWNER_ADDRESS).nonce(1); - world.whitebox_deploy( - &adder_whitebox, - ScDeployStep::new() - .from(ADDER_OWNER_ADDRESS_EXPR) - .code(adder_code), - |sc| { - sc.init(managed_biguint!(5)); - }, - ); + world + .tx() + .raw_deploy() + .from(ADDER_OWNER_ADDRESS) + .code(ADDER_PATH_EXPR) + .new_address(ADDER_ADDRESS) + .whitebox(adder::contract_obj, |sc| { + sc.init(BigUint::from(5u64)); + }); let action_id = call_propose( &mut world, ActionRaw::SendAsyncCall(CallActionDataRaw { - to: address_expr_to_address(ADDER_ADDRESS_EXPR), + to: ADDER_ADDRESS.to_address(), egld_amount: 0u64.into(), endpoint_name: BoxedBytes::from(&b"add"[..]), arguments: vec![BoxedBytes::from(&[5u8][..])], @@ -665,93 +592,90 @@ fn test_async_call_to_sc() { None, ); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| sc.sign(action_id), - ); + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| sc.sign(action_id)); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| { + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| { let _ = sc.perform_action_endpoint(action_id); - }, - ); + }); - world.whitebox_query(&adder_whitebox, |sc| { - let actual_sum = sc.sum().get(); - let expected_sum = managed_biguint!(10); - assert_eq!(actual_sum, expected_sum); - }); + world + .query() + .to(ADDER_ADDRESS) + .whitebox(adder::contract_obj, |sc| { + let actual_sum = sc.sum().get(); + let expected_sum = managed_biguint!(10); + assert_eq!(actual_sum, expected_sum); + }); } #[test] fn test_deploy_and_upgrade_from_source() { let mut world = setup(); - let multisig_whitebox = WhiteboxContract::new(MULTISIG_ADDRESS_EXPR, multisig::contract_obj); + const NEW_ADDER_ADDRESS: TestSCAddress = TestSCAddress::new("new-adder"); - let adder_whitebox = WhiteboxContract::new(ADDER_ADDRESS_EXPR, adder::contract_obj); - let adder_code = world.code_expression(ADDER_PATH_EXPR); - - let new_adder_whitebox = WhiteboxContract::new(NEW_ADDER_ADDRESS_EXPR, adder::contract_obj); - - const ADDER_OWNER_ADDRESS_EXPR: &str = "address:adder-owner"; - const ADDER_ADDRESS_EXPR: &str = "sc:adder"; - const NEW_ADDER_ADDRESS_EXPR: &str = "sc:new-adder"; - const ADDER_PATH_EXPR: &str = "mxsc:test-contracts/adder.mxsc.json"; + const ADDER_OWNER_ADDRESS: TestAddress = TestAddress::new("adder-owner"); + const ADDER_ADDRESS: TestSCAddress = TestSCAddress::new("adder"); + const ADDER_PATH_EXPR: MxscPath = MxscPath::new("mxsc:test-contracts/adder.mxsc.json"); world.register_contract(ADDER_PATH_EXPR, adder::ContractBuilder); - world.set_state_step( - SetStateStep::new() - .put_account(ADDER_OWNER_ADDRESS_EXPR, Account::new().nonce(1)) - .new_address(ADDER_OWNER_ADDRESS_EXPR, 1, ADDER_ADDRESS_EXPR) - .new_address(MULTISIG_ADDRESS_EXPR, 0, NEW_ADDER_ADDRESS_EXPR), - ); + world.set_state_step(SetStateStep::new().new_address( + MULTISIG_ADDRESS.eval_to_expr().as_str(), + 0, + NEW_ADDER_ADDRESS.eval_to_expr().as_str(), + )); - world.whitebox_deploy( - &adder_whitebox, - ScDeployStep::new() - .from(ADDER_OWNER_ADDRESS_EXPR) - .code(adder_code), - |sc| { - sc.init(managed_biguint!(5)); - }, - ); + world.account(ADDER_OWNER_ADDRESS).nonce(1); + + world + .tx() + .raw_deploy() + .from(ADDER_OWNER_ADDRESS) + .code(ADDER_PATH_EXPR) + .new_address(ADDER_ADDRESS) + .whitebox(adder::contract_obj, |sc| { + sc.init(BigUint::from(5u64)); + }); let action_id = call_propose( &mut world, ActionRaw::SCDeployFromSource { amount: 0u64.into(), - source: address_expr_to_address(ADDER_ADDRESS_EXPR), + source: ADDER_ADDRESS.to_address(), code_metadata: CodeMetadata::all(), arguments: vec![BoxedBytes::from(&[5u8][..])], }, None, ); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| sc.sign(action_id), - ); + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| sc.sign(action_id)); - let mut addr = Address::zero(); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| { + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| { let opt_address = sc.perform_action_endpoint(action_id); - addr = opt_address.into_option().unwrap().to_address(); - }, - ); + let addr = opt_address.into_option().unwrap().to_address(); - assert_eq!(address_expr_to_address(NEW_ADDER_ADDRESS_EXPR), addr); + assert_eq!(NEW_ADDER_ADDRESS.to_address(), addr); + }); let action_id = call_propose( &mut world, ActionRaw::SendTransferExecute(CallActionDataRaw { - to: address_expr_to_address(NEW_ADDER_ADDRESS_EXPR), + to: NEW_ADDER_ADDRESS.to_address(), egld_amount: 0u64.into(), endpoint_name: BoxedBytes::from(&b"add"[..]), arguments: vec![BoxedBytes::from(&[5u8][..])], @@ -759,71 +683,70 @@ fn test_deploy_and_upgrade_from_source() { None, ); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| sc.sign(action_id), - ); + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| sc.sign(action_id)); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| { + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| { let _ = sc.perform_action_endpoint(action_id); - }, - ); + }); - world.whitebox_query(&new_adder_whitebox, |sc| { - let actual_sum = sc.sum().get(); - let expected_sum = managed_biguint!(10); - assert_eq!(actual_sum, expected_sum); - }); - - let factorial_code = world.code_expression(FACTORIAL_PATH_EXPR); + world + .query() + .to(NEW_ADDER_ADDRESS) + .whitebox(adder::contract_obj, |sc| { + let actual_sum = sc.sum().get(); + let expected_sum = managed_biguint!(10); + assert_eq!(actual_sum, expected_sum); + }); - const FACTORIAL_ADDRESS_EXPR: &str = "sc:factorial"; - const FACTORIAL_PATH_EXPR: &str = "mxsc:test-contracts/factorial.mxsc.json"; + const FACTORIAL_ADDRESS: TestSCAddress = TestSCAddress::new("factorial"); + const FACTORIAL_PATH_EXPR: MxscPath = MxscPath::new("mxsc:test-contracts/factorial.mxsc.json"); world.register_contract(FACTORIAL_PATH_EXPR, factorial::ContractBuilder); - world.set_state_step(SetStateStep::new().put_account( - FACTORIAL_ADDRESS_EXPR, - Account::new().nonce(1).code(factorial_code.clone()), - )); + world + .tx() + .raw_deploy() + .from(OWNER_ADDRESS) + .code(FACTORIAL_PATH_EXPR) + .new_address(FACTORIAL_ADDRESS) + .whitebox(factorial::contract_obj, |sc| { + sc.init(); + }); let action_id = call_propose( &mut world, ActionRaw::SCUpgradeFromSource { - source: address_expr_to_address(FACTORIAL_ADDRESS_EXPR), + source: FACTORIAL_ADDRESS.to_address(), amount: 0u64.into(), code_metadata: CodeMetadata::all(), arguments: Vec::new(), - sc_address: address_expr_to_address(ADDER_ADDRESS_EXPR), + sc_address: ADDER_ADDRESS.to_address(), }, None, ); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| sc.sign(action_id), - ); + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| sc.sign(action_id)); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| { + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| { let _ = sc.perform_action_endpoint(action_id); - }, - ); - - world.check_state_step( - CheckStateStep::new() - .put_account(ADDER_ADDRESS_EXPR, CheckAccount::new().code(factorial_code)), - ); -} + }); -fn address_expr_to_address(address_expr: &str) -> Address { - AddressValue::from(address_expr).to_address() + world.check_account(ADDER_ADDRESS).code(FACTORIAL_PATH_EXPR); } fn boxed_bytes_vec_to_managed( From 1de1b5b6f5981fbadf17b383689750f3a9838e9b Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Thu, 22 Aug 2024 15:23:04 +0200 Subject: [PATCH 24/92] impl new crypto opcodes --- framework/base/src/api/crypto_api.rs | 21 +++++++++++ .../api/uncallable/crypto_api_uncallable.rs | 27 ++++++++++++++ .../src/api/core_api_vh/crypto_api_vh.rs | 27 ++++++++++++++ .../wasm-adapter/src/api/crypto_api_node.rs | 37 +++++++++++++++++++ 4 files changed, 112 insertions(+) diff --git a/framework/base/src/api/crypto_api.rs b/framework/base/src/api/crypto_api.rs index 3c5c374a87..235e44919a 100644 --- a/framework/base/src/api/crypto_api.rs +++ b/framework/base/src/api/crypto_api.rs @@ -76,4 +76,25 @@ pub trait CryptoApiImpl: ManagedTypeApiImpl { s: Self::ManagedBufferHandle, dest: Self::ManagedBufferHandle, ); + + fn verify_secp256r1_managed( + &self, + key: Self::ManagedBufferHandle, + message: Self::ManagedBufferHandle, + signature: Self::ManagedBufferHandle, + ) -> bool; + + fn verify_bls_signature_share_managed( + &self, + key: Self::ManagedBufferHandle, + message: Self::ManagedBufferHandle, + signature: Self::ManagedBufferHandle, + ) -> bool; + + fn verify_bls_aggregated_signature_managed( + &self, + key: Self::ManagedBufferHandle, + message: Self::ManagedBufferHandle, + signature: Self::ManagedBufferHandle, + ) -> bool; } diff --git a/framework/base/src/api/uncallable/crypto_api_uncallable.rs b/framework/base/src/api/uncallable/crypto_api_uncallable.rs index 59195618c9..bb42aa04bb 100644 --- a/framework/base/src/api/uncallable/crypto_api_uncallable.rs +++ b/framework/base/src/api/uncallable/crypto_api_uncallable.rs @@ -82,4 +82,31 @@ impl CryptoApiImpl for UncallableApi { ) { unreachable!() } + + fn verify_secp256r1_managed( + &self, + _key: Self::ManagedBufferHandle, + _message: Self::ManagedBufferHandle, + _signature: Self::ManagedBufferHandle, + ) -> bool { + unreachable!() + } + + fn verify_bls_signature_share_managed( + &self, + _key: Self::ManagedBufferHandle, + _message: Self::ManagedBufferHandle, + _signature: Self::ManagedBufferHandle, + ) -> bool { + unreachable!() + } + + fn verify_bls_aggregated_signature_managed( + &self, + _key: Self::ManagedBufferHandle, + _message: Self::ManagedBufferHandle, + _signature: Self::ManagedBufferHandle, + ) -> bool { + unreachable!() + } } diff --git a/framework/scenario/src/api/core_api_vh/crypto_api_vh.rs b/framework/scenario/src/api/core_api_vh/crypto_api_vh.rs index f3789181e7..aa4c2dab94 100644 --- a/framework/scenario/src/api/core_api_vh/crypto_api_vh.rs +++ b/framework/scenario/src/api/core_api_vh/crypto_api_vh.rs @@ -99,4 +99,31 @@ impl CryptoApiImpl for VMHooksApi { ) { panic!("encode_secp256k1_signature not implemented yet!") } + + fn verify_secp256r1_managed( + &self, + _key: Self::ManagedBufferHandle, + _message: Self::ManagedBufferHandle, + _signature: Self::ManagedBufferHandle, + ) -> bool { + panic!("verify_secp256r1 not implemented yet!") + } + + fn verify_bls_signature_share_managed( + &self, + _key: Self::ManagedBufferHandle, + _message: Self::ManagedBufferHandle, + _signature: Self::ManagedBufferHandle, + ) -> bool { + panic!("verify_bls_signature_share not implemented yet!") + } + + fn verify_bls_aggregated_signature_managed( + &self, + _key: Self::ManagedBufferHandle, + _message: Self::ManagedBufferHandle, + _signature: Self::ManagedBufferHandle, + ) -> bool { + panic!("verify_bls_aggregated_signature not implemented yet!") + } } diff --git a/framework/wasm-adapter/src/api/crypto_api_node.rs b/framework/wasm-adapter/src/api/crypto_api_node.rs index eb16e25e6a..0cbe24fad5 100644 --- a/framework/wasm-adapter/src/api/crypto_api_node.rs +++ b/framework/wasm-adapter/src/api/crypto_api_node.rs @@ -25,6 +25,16 @@ extern "C" { ) -> i32; fn managedEncodeSecp256k1DerSignature(rHandle: i32, sHandle: i32, sigHandle: i32) -> i32; + + fn managedVerifySecp256r1(keyHandle: i32, messageHandle: i32, sigHandle: i32) -> i32; + + fn managedVerifyBLSSignatureShare(keyHandle: i32, messageHandle: i32, sigHandle: i32) -> i32; + + fn managedVerifyBLSAggregatedSignature( + keyHandle: i32, + messageHandle: i32, + sigHandle: i32, + ) -> i32; } impl CryptoApi for VmApiImpl { @@ -123,4 +133,31 @@ impl CryptoApiImpl for VmApiImpl { let _ = managedEncodeSecp256k1DerSignature(r, s, dest_sig_handle); } } + + fn verify_secp256r1_managed( + &self, + key: Self::ManagedBufferHandle, + message: Self::ManagedBufferHandle, + signature: Self::ManagedBufferHandle, + ) -> bool { + unsafe { managedVerifySecp256r1(key, message, signature) == 0 } + } + + fn verify_bls_signature_share_managed( + &self, + key: Self::ManagedBufferHandle, + message: Self::ManagedBufferHandle, + signature: Self::ManagedBufferHandle, + ) -> bool { + unsafe { managedVerifyBLSSignatureShare(key, message, signature) == 0 } + } + + fn verify_bls_aggregated_signature_managed( + &self, + key: Self::ManagedBufferHandle, + message: Self::ManagedBufferHandle, + signature: Self::ManagedBufferHandle, + ) -> bool { + unsafe { managedVerifyBLSAggregatedSignature(key, message, signature) == 0 } + } } From 9543e03aab14eeb01b2e72aec2b6454bae724a78 Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Thu, 22 Aug 2024 16:30:59 +0200 Subject: [PATCH 25/92] added in crypto wrapper and test contract --- .../basic-features/sc-config.toml | 3 ++ .../basic-features/src/crypto_features.rs | 30 ++++++++++++++ .../basic-features/wasm/src/lib.rs | 7 +++- .../contract_base/wrappers/crypto_wrapper.rs | 39 +++++++++++++++++++ 4 files changed, 77 insertions(+), 2 deletions(-) diff --git a/contracts/feature-tests/basic-features/sc-config.toml b/contracts/feature-tests/basic-features/sc-config.toml index 82698d1dab..6b24db99b9 100644 --- a/contracts/feature-tests/basic-features/sc-config.toml +++ b/contracts/feature-tests/basic-features/sc-config.toml @@ -1,6 +1,9 @@ [settings] main = "basic-features" +[contracts.basic-features] +ei = "1.4" + [contracts.basic-features.profile] overflow-checks = true # needed for overflow tests diff --git a/contracts/feature-tests/basic-features/src/crypto_features.rs b/contracts/feature-tests/basic-features/src/crypto_features.rs index 56c543163c..2c08b850e5 100644 --- a/contracts/feature-tests/basic-features/src/crypto_features.rs +++ b/contracts/feature-tests/basic-features/src/crypto_features.rs @@ -64,4 +64,34 @@ pub trait CryptoFeatures { fn compute_secp256k1_der_signature(&self, r: ManagedBuffer, s: ManagedBuffer) -> ManagedBuffer { self.crypto().encode_secp256k1_der_signature(&r, &s) } + + #[endpoint] + fn verify_secp256r1_signature( + &self, + key: ManagedBuffer, + message: ManagedBuffer, + signature: ManagedBuffer, + ) -> bool { + self.crypto().verify_secp256r1(&key, &message, &signature) + } + #[endpoint] + fn verify_bls_signature_share_managed( + &self, + key: ManagedBuffer, + message: ManagedBuffer, + signature: ManagedBuffer, + ) -> bool { + self.crypto() + .verify_bls_signature_share(&key, &message, &signature) + } + #[endpoint] + fn verify_bls_aggregated_signature_managed( + &self, + key: ManagedBuffer, + message: ManagedBuffer, + signature: ManagedBuffer, + ) -> bool { + self.crypto() + .verify_bls_aggregated_signature(&key, &message, &signature) + } } diff --git a/contracts/feature-tests/basic-features/wasm/src/lib.rs b/contracts/feature-tests/basic-features/wasm/src/lib.rs index 887b75bcd5..c602f6e198 100644 --- a/contracts/feature-tests/basic-features/wasm/src/lib.rs +++ b/contracts/feature-tests/basic-features/wasm/src/lib.rs @@ -5,9 +5,9 @@ //////////////////////////////////////////////////// // Init: 1 -// Endpoints: 403 +// Endpoints: 406 // Async Callback: 1 -// Total number of exported functions: 405 +// Total number of exported functions: 408 #![no_std] @@ -145,6 +145,9 @@ multiversx_sc_wasm_adapter::endpoints! { verify_secp256k1_signature => verify_secp256k1_signature verify_custom_secp256k1_signature => verify_custom_secp256k1_signature compute_secp256k1_der_signature => compute_secp256k1_der_signature + verify_secp256r1_signature => verify_secp256r1_signature + verify_bls_signature_share_managed => verify_bls_signature_share_managed + verify_bls_aggregated_signature_managed => verify_bls_aggregated_signature_managed echo_u64 => echo_u64 echo_i64 => echo_i64 echo_i32 => echo_i32 diff --git a/framework/base/src/contract_base/wrappers/crypto_wrapper.rs b/framework/base/src/contract_base/wrappers/crypto_wrapper.rs index c314899eaa..76b8fcd996 100644 --- a/framework/base/src/contract_base/wrappers/crypto_wrapper.rs +++ b/framework/base/src/contract_base/wrappers/crypto_wrapper.rs @@ -129,4 +129,43 @@ where ); ManagedBuffer::from_handle(new_handle) } + + pub fn verify_secp256r1( + &self, + key: &ManagedBuffer, + message: &ManagedBuffer, + signature: &ManagedBuffer, + ) -> bool { + A::crypto_api_impl().verify_secp256r1_managed( + key.get_handle(), + message.get_handle(), + signature.get_handle(), + ) + } + + pub fn verify_bls_signature_share( + &self, + key: &ManagedBuffer, + message: &ManagedBuffer, + signature: &ManagedBuffer, + ) -> bool { + A::crypto_api_impl().verify_bls_signature_share_managed( + key.get_handle(), + message.get_handle(), + signature.get_handle(), + ) + } + + pub fn verify_bls_aggregated_signature( + &self, + key: &ManagedBuffer, + message: &ManagedBuffer, + signature: &ManagedBuffer, + ) -> bool { + A::crypto_api_impl().verify_bls_aggregated_signature_managed( + key.get_handle(), + message.get_handle(), + signature.get_handle(), + ) + } } From 38422b0d8a288b7417429f58932c59fe11eec018 Mon Sep 17 00:00:00 2001 From: Andrei Vasilescu Date: Thu, 22 Aug 2024 18:22:12 +0300 Subject: [PATCH 26/92] register token from interactor --- .../sys-func-calls/interact/.gitignore | 9 ++ .../sys-func-calls/interact/Cargo.toml | 24 +++++ .../sys-func-calls/interact/config.toml | 1 + .../interact/src/basic_interact.rs | 87 +++++++++++++++++++ .../interact/src/basic_interact_cli.rs | 45 ++++++++++ .../interact/src/basic_interact_config.rs | 26 ++++++ .../interact/src/basic_interact_state.rs | 50 +++++++++++ 7 files changed, 242 insertions(+) create mode 100644 tools/interactor-system-func-calls/sys-func-calls/interact/.gitignore create mode 100644 tools/interactor-system-func-calls/sys-func-calls/interact/Cargo.toml create mode 100644 tools/interactor-system-func-calls/sys-func-calls/interact/config.toml create mode 100644 tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs create mode 100644 tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_cli.rs create mode 100644 tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_config.rs create mode 100644 tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_state.rs diff --git a/tools/interactor-system-func-calls/sys-func-calls/interact/.gitignore b/tools/interactor-system-func-calls/sys-func-calls/interact/.gitignore new file mode 100644 index 0000000000..b2630809de --- /dev/null +++ b/tools/interactor-system-func-calls/sys-func-calls/interact/.gitignore @@ -0,0 +1,9 @@ +# Pem files are used for interactions, but shouldn't be committed +*.pem +!adder-owner.pem + +# Temporary storage of deployed contract address, so we can preserve the context between executions. +state.toml + +# Trace file of interactor tooling +interactor_trace.scen.json diff --git a/tools/interactor-system-func-calls/sys-func-calls/interact/Cargo.toml b/tools/interactor-system-func-calls/sys-func-calls/interact/Cargo.toml new file mode 100644 index 0000000000..ce85dc57c1 --- /dev/null +++ b/tools/interactor-system-func-calls/sys-func-calls/interact/Cargo.toml @@ -0,0 +1,24 @@ +[[bin]] +name = "basic-interact-sys-calls" +path = "src/basic_interact.rs" + +[package] +name = "basic-interact-sys-calls" +version = "0.0.0" +publish = false +edition = "2021" +authors = ["you"] + +[dependencies] +toml = "0.8.6" + +[dependencies.clap] +version = "4.4.7" +features = ["derive"] + +[dependencies.serde] +version = "1.0" +features = ["derive"] + +[dependencies.multiversx-sc-snippets] +version = "0.52.3" diff --git a/tools/interactor-system-func-calls/sys-func-calls/interact/config.toml b/tools/interactor-system-func-calls/sys-func-calls/interact/config.toml new file mode 100644 index 0000000000..61ac8dbf87 --- /dev/null +++ b/tools/interactor-system-func-calls/sys-func-calls/interact/config.toml @@ -0,0 +1 @@ +gateway = 'https://devnet-gateway.multiversx.com' diff --git a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs new file mode 100644 index 0000000000..83f8d297fe --- /dev/null +++ b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs @@ -0,0 +1,87 @@ +mod basic_interact_cli; +mod basic_interact_config; +mod basic_interact_state; + +use basic_interact_config::Config; +use basic_interact_state::State; +use clap::Parser; + +use multiversx_sc_snippets::imports::*; + +#[tokio::main] +async fn main() { + env_logger::init(); + + let mut basic_interact = SysFuncCallsInteract::init().await; + + let cli = basic_interact_cli::InteractCli::parse(); + match &cli.command { + Some(basic_interact_cli::InteractCliCommand::Add(args)) => {}, + Some(basic_interact_cli::InteractCliCommand::IssueToken(args)) => { + basic_interact + .issue_token( + args.cost.clone(), + &args.display_name, + &args.ticker, + EsdtTokenType::from(args.token_type), + args.num_decimals, + ) + .await; + }, + + None => {}, + } +} + +#[allow(unused)] +struct SysFuncCallsInteract { + interactor: Interactor, + wallet_address: Bech32Address, + state: State, +} + +impl SysFuncCallsInteract { + async fn init() -> Self { + let config = Config::load_config(); + let mut interactor = Interactor::new(config.gateway()).await; + + let wallet_address = interactor.register_wallet(test_wallets::alice()); + + Self { + interactor, + wallet_address: wallet_address.into(), + state: State::load_state(), + } + } + + async fn set_state(&mut self) { + println!("wallet address: {}", self.wallet_address); + self.interactor.retrieve_account(&self.wallet_address).await; + } + + async fn issue_token( + &mut self, + issue_cost: RustBigUint, + token_display_name: &str, + token_ticker: &str, + token_type: EsdtTokenType, + num_decimals: usize, + ) { + self.interactor + .tx() + .from(&self.wallet_address) + .to(ESDTSystemSCAddress.to_managed_address()) + .gas(100_000_000u64) + .typed(ESDTSystemSCProxy) + .issue_and_set_all_roles( + issue_cost.into(), + token_display_name.into(), + token_ticker.into(), + token_type, + num_decimals, + ) + .prepare_async() + .run() + .await; + } +} diff --git a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_cli.rs b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_cli.rs new file mode 100644 index 0000000000..9c404c80e8 --- /dev/null +++ b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_cli.rs @@ -0,0 +1,45 @@ +use clap::{Args, Parser, Subcommand}; +use multiversx_sc_snippets::imports::{EsdtTokenType, RustBigUint}; + +/// SysFuncCalls Interact CLI +#[derive(Default, PartialEq, Eq, Debug, Parser)] +#[command(version, about)] +#[command(propagate_version = true)] +pub struct InteractCli { + #[command(subcommand)] + pub command: Option, +} + +/// SysFuncCalls Interact CLI Commands +#[derive(Clone, PartialEq, Eq, Debug, Subcommand)] +pub enum InteractCliCommand { + #[command(name = "add", about = "Add value")] + Add(AddArgs), + #[command(name = "issue-token", about = "Issue a token")] + IssueToken(IssueTokenArgs), +} + +#[derive(Default, Clone, PartialEq, Eq, Debug, Args)] +pub struct AddArgs { + /// The value to add + #[arg(short = 'v', long = "value")] + pub value: u32, + + /// Repeat this number of times + #[arg(short = 'c', long = "count", default_value = "1")] + pub count: usize, +} + +#[derive(Clone, Debug, PartialEq, Eq, Args)] +pub struct IssueTokenArgs { + #[arg(short = 'c', long = "cost", default_value = "50000000000000000")] + pub cost: RustBigUint, + #[arg(short = 'd', long = "display-name")] + pub display_name: String, + #[arg(long = "token-ticker")] + pub ticker: String, + #[arg(long = "token-type")] + pub token_type: u8, + #[arg(long = "num-decimals")] + pub num_decimals: usize, +} diff --git a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_config.rs b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_config.rs new file mode 100644 index 0000000000..f25b91a884 --- /dev/null +++ b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_config.rs @@ -0,0 +1,26 @@ +use serde::Deserialize; +use std::io::Read; + +/// Config file +const CONFIG_FILE: &str = "config.toml"; + +/// SysFuncCalls Interact configuration +#[derive(Debug, Deserialize)] +pub struct Config { + gateway: String, +} + +impl Config { + // Deserializes config from file + pub fn load_config() -> Self { + let mut file = std::fs::File::open(CONFIG_FILE).unwrap(); + let mut content = String::new(); + file.read_to_string(&mut content).unwrap(); + toml::from_str(&content).unwrap() + } + + // Returns the gateway + pub fn gateway(&self) -> &str { + &self.gateway + } +} diff --git a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_state.rs b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_state.rs new file mode 100644 index 0000000000..41453e36fd --- /dev/null +++ b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_state.rs @@ -0,0 +1,50 @@ +use multiversx_sc_snippets::imports::*; +use serde::{Deserialize, Serialize}; +use std::{ + io::{Read, Write}, + path::Path, +}; + +/// State file +const STATE_FILE: &str = "state.toml"; + +/// Multisig Interact state +#[derive(Debug, Default, Serialize, Deserialize)] +pub struct State { + adder_address: Option, +} + +impl State { + // Deserializes state from file + pub fn load_state() -> Self { + if Path::new(STATE_FILE).exists() { + let mut file = std::fs::File::open(STATE_FILE).unwrap(); + let mut content = String::new(); + file.read_to_string(&mut content).unwrap(); + toml::from_str(&content).unwrap() + } else { + Self::default() + } + } + + /// Sets the adder address + pub fn set_adder_address(&mut self, address: Bech32Address) { + self.adder_address = Some(address); + } + + /// Returns the adder contract + pub fn current_adder_address(&self) -> &Bech32Address { + self.adder_address + .as_ref() + .expect("no known adder contract, deploy first") + } +} + +impl Drop for State { + // Serializes state to file + fn drop(&mut self) { + let mut file = std::fs::File::create(STATE_FILE).unwrap(); + file.write_all(toml::to_string(self).unwrap().as_bytes()) + .unwrap(); + } +} From 3fc082a04f42d54f7c9bebb764c9485266708221 Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Thu, 22 Aug 2024 17:30:17 +0200 Subject: [PATCH 27/92] added tests --- .../scenarios/crypto_verify_bls.scen.json | 52 +++++++- .../crypto_verify_secp256r1.scen.json | 121 ++++++++++++++++++ .../basic-features/src/crypto_features.rs | 6 +- .../tests/basic_features_scenario_go_test.rs | 5 + .../tests/basic_features_scenario_rs_test.rs | 6 + .../basic-features/wasm/src/lib.rs | 4 +- 6 files changed, 189 insertions(+), 5 deletions(-) create mode 100644 contracts/feature-tests/basic-features/scenarios/crypto_verify_secp256r1.scen.json diff --git a/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls.scen.json b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls.scen.json index ead18354dc..7b07232695 100644 --- a/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls.scen.json @@ -41,6 +41,56 @@ "gas": "*", "refund": "*" } + }, + { + "step": "scCall", + "id": "4", + "tx": { + "from": "address:an_account", + "to": "sc:basic-features", + "function": "verify_bls_signature_share", + "arguments": [ + "0xb5823f6e564251cc03ce7bad3da83e72576e92795d3500bba1acb30ec9a94dce87bb8aa794d67b2d61d15c33f28f6c0c23ba1dfcbf21e8f8b46286ff871afabac925303ddcaddce6254fcff6d3155797db40b3d3b5865e8fc0bd770b3d79b381", + "0x6d65737361676520746f206265207369676e6564", + "0xaf32a2ddf341c08d1eb7232f05dc34e4454155e676b58c40fddf9a036562ac2c01533d2d557cb49d73aa9d7a89744696" + ], + "gasLimit": "50,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [ + "0x01" + ], + "status": "", + "logs": "*", + "gas": "*", + "refund": "*" + } + }, + { + "step": "scCall", + "id": "5", + "tx": { + "from": "address:an_account", + "to": "sc:basic-features", + "function": "verify_bls_aggregated_signature", + "arguments": [ + "0xb5823f6e564251cc03ce7bad3da83e72576e92795d3500bba1acb30ec9a94dce87bb8aa794d67b2d61d15c33f28f6c0c23ba1dfcbf21e8f8b46286ff871afabac925303ddcaddce6254fcff6d3155797db40b3d3b5865e8fc0bd770b3d79b381", + "0x6d65737361676520746f206265207369676e6564", + "0xaf32a2ddf341c08d1eb7232f05dc34e4454155e676b58c40fddf9a036562ac2c01533d2d557cb49d73aa9d7a89744696" + ], + "gasLimit": "50,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [ + "0x01" + ], + "status": "", + "logs": "*", + "gas": "*", + "refund": "*" + } } ] -} +} \ No newline at end of file diff --git a/contracts/feature-tests/basic-features/scenarios/crypto_verify_secp256r1.scen.json b/contracts/feature-tests/basic-features/scenarios/crypto_verify_secp256r1.scen.json new file mode 100644 index 0000000000..e87822db95 --- /dev/null +++ b/contracts/feature-tests/basic-features/scenarios/crypto_verify_secp256r1.scen.json @@ -0,0 +1,121 @@ +{ + "name": "crypto", + "comment": "", + "gasSchedule": "v3", + "steps": [ + { + "step": "setState", + "accounts": { + "sc:basic-features": { + "nonce": "0", + "balance": "0", + "code": "mxsc:../output/basic-features.mxsc.json" + }, + "address:an_account": { + "nonce": "0", + "balance": "0" + } + } + }, + { + "step": "scCall", + "id": "5 - compressed key", + "tx": { + "from": "address:an_account", + "to": "sc:basic-features", + "function": "verify_secp256r1_signature", + "arguments": [ + "0x02a673638cb9587cb68ea08dbef685c6f2d2a751a8b3c6f2a7e9a4999e6e4bfaf5", + "0x6d65737361676520746f207369676e", + "0x3045022100fab29dbcb623e7e96f44665f312b89ffdb9e4d2e2f53353236fbbcf57b2f49bf02203d6f9c63df8be43121042970a549a2d3baeca093fd37b726ddcc0924638409f5" + ], + "gasLimit": "50,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [ + "0x01" + ], + "status": "", + "logs": "*", + "gas": "*", + "refund": "*" + } + }, + { + "step": "scCall", + "id": "6 - uncompressed key", + "tx": { + "from": "address:an_account", + "to": "sc:basic-features", + "function": "verify_secp256r1_signature", + "arguments": [ + "0x04a673638cb9587cb68ea08dbef685c6f2d2a751a8b3c6f2a7e9a4999e6e4bfaf5ca1d22fe57c6103dbaac10cf15d15c0791cab8bb9a04f800e4d215276cb3e008", + "0x6d65737361676520746f207369676e", + "0x3045022100fab29dbcb623e7e96f44665f312b89ffdb9e4d2e2f53353236fbbcf57b2f49bf02203d6f9c63df8be43121042970a549a2d3baeca093fd37b726ddcc0924638409f5" + ], + "gasLimit": "50,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [ + "0x01" + ], + "status": "", + "logs": "*", + "gas": "*", + "refund": "*" + } + }, + { + "step": "scCall", + "id": "7 - encode key from r and s", + "tx": { + "from": "address:an_account", + "to": "sc:basic-features", + "function": "compute_secp256k1_der_signature", + "arguments": [ + "0x90f27b8b488db00b00606796d2987f6a5f59ae62ea05effe84fef5b8b0e54998", + "0x4a691139ad57a3f0b906637673aa2f63d1f55cb1a69199d4009eea23ceaddc93" + ], + "gasLimit": "50,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [ + "0x304502210090f27b8b488db00b00606796d2987f6a5f59ae62ea05effe84fef5b8b0e5499802204a691139ad57a3f0b906637673aa2f63d1f55cb1a69199d4009eea23ceaddc93" + ], + "status": "", + "logs": "*", + "gas": "*", + "refund": "*" + } + }, + { + "step": "scCall", + "id": "8 - verify custom secp256k1", + "tx": { + "from": "address:an_account", + "to": "sc:basic-features", + "function": "verify_custom_secp256k1_signature", + "arguments": [ + "0x04e32df42865e97135acfb65f3bae71bdc86f4d49150ad6a440b6f15878109880a0a2b2667f7e725ceea70c673093bf67663e0312623c8e091b13cf2c0f11ef652", + "0xce0677bb30baa8cf067c88db9811f4333d131bf8bcf12fe7065d211dce971008", + "0x304502210090f27b8b488db00b00606796d2987f6a5f59ae62ea05effe84fef5b8b0e5499802204a691139ad57a3f0b906637673aa2f63d1f55cb1a69199d4009eea23ceaddc93", + "0" + ], + "gasLimit": "50,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [ + "0x01" + ], + "status": "", + "logs": "*", + "gas": "*", + "refund": "*" + } + } + ] +} diff --git a/contracts/feature-tests/basic-features/src/crypto_features.rs b/contracts/feature-tests/basic-features/src/crypto_features.rs index 2c08b850e5..f66479026c 100644 --- a/contracts/feature-tests/basic-features/src/crypto_features.rs +++ b/contracts/feature-tests/basic-features/src/crypto_features.rs @@ -74,8 +74,9 @@ pub trait CryptoFeatures { ) -> bool { self.crypto().verify_secp256r1(&key, &message, &signature) } + #[endpoint] - fn verify_bls_signature_share_managed( + fn verify_bls_signature_share( &self, key: ManagedBuffer, message: ManagedBuffer, @@ -84,8 +85,9 @@ pub trait CryptoFeatures { self.crypto() .verify_bls_signature_share(&key, &message, &signature) } + #[endpoint] - fn verify_bls_aggregated_signature_managed( + fn verify_bls_aggregated_signature( &self, key: ManagedBuffer, message: ManagedBuffer, diff --git a/contracts/feature-tests/basic-features/tests/basic_features_scenario_go_test.rs b/contracts/feature-tests/basic-features/tests/basic_features_scenario_go_test.rs index 9c39d06ae5..f5a9a10726 100644 --- a/contracts/feature-tests/basic-features/tests/basic_features_scenario_go_test.rs +++ b/contracts/feature-tests/basic-features/tests/basic_features_scenario_go_test.rs @@ -94,6 +94,11 @@ fn crypto_verify_secp_256_k_1_go() { world().run("scenarios/crypto_verify_secp256k1.scen.json"); } +#[test] +fn crypto_verify_secp_256_r_1_go() { + world().run("scenarios/crypto_verify_secp256r1.scen.json"); +} + #[test] fn echo_array_u_8_go() { world().run("scenarios/echo_array_u8.scen.json"); diff --git a/contracts/feature-tests/basic-features/tests/basic_features_scenario_rs_test.rs b/contracts/feature-tests/basic-features/tests/basic_features_scenario_rs_test.rs index f35c4779e6..95a617e20c 100644 --- a/contracts/feature-tests/basic-features/tests/basic_features_scenario_rs_test.rs +++ b/contracts/feature-tests/basic-features/tests/basic_features_scenario_rs_test.rs @@ -109,6 +109,12 @@ fn crypto_verify_secp_256_k_1_rs() { world().run("scenarios/crypto_verify_secp256k1.scen.json"); } +#[test] +#[ignore] +fn crypto_verify_secp_256_r_1_rs() { + world().run("scenarios/crypto_verify_secp256r1.scen.json"); +} + #[test] fn echo_array_u_8_rs() { world().run("scenarios/echo_array_u8.scen.json"); diff --git a/contracts/feature-tests/basic-features/wasm/src/lib.rs b/contracts/feature-tests/basic-features/wasm/src/lib.rs index c602f6e198..90986ec90b 100644 --- a/contracts/feature-tests/basic-features/wasm/src/lib.rs +++ b/contracts/feature-tests/basic-features/wasm/src/lib.rs @@ -146,8 +146,8 @@ multiversx_sc_wasm_adapter::endpoints! { verify_custom_secp256k1_signature => verify_custom_secp256k1_signature compute_secp256k1_der_signature => compute_secp256k1_der_signature verify_secp256r1_signature => verify_secp256r1_signature - verify_bls_signature_share_managed => verify_bls_signature_share_managed - verify_bls_aggregated_signature_managed => verify_bls_aggregated_signature_managed + verify_bls_signature_share => verify_bls_signature_share + verify_bls_aggregated_signature => verify_bls_aggregated_signature echo_u64 => echo_u64 echo_i64 => echo_i64 echo_i32 => echo_i32 From 6e59c53c981f86059622da9d4eba376f03e294f1 Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Fri, 23 Aug 2024 15:33:53 +0200 Subject: [PATCH 28/92] created contract variant from new crypto endpoints --- .../basic-features/sc-config.toml | 11 ++++++ .../wasm-basic-features-crypto/Cargo.toml | 35 +++++++++++++++++++ .../wasm-basic-features-crypto/src/lib.rs | 27 ++++++++++++++ 3 files changed, 73 insertions(+) create mode 100644 contracts/feature-tests/basic-features/wasm-basic-features-crypto/Cargo.toml create mode 100644 contracts/feature-tests/basic-features/wasm-basic-features-crypto/src/lib.rs diff --git a/contracts/feature-tests/basic-features/sc-config.toml b/contracts/feature-tests/basic-features/sc-config.toml index 6b24db99b9..b21719850f 100644 --- a/contracts/feature-tests/basic-features/sc-config.toml +++ b/contracts/feature-tests/basic-features/sc-config.toml @@ -12,6 +12,17 @@ add-unlabelled = false add-endpoints = ["init", "load_bytes", "store_bytes"] kill_legacy_callback = true +[contracts.basic-features-crypto] +ei = "1.4" +add-unlabelled = false +add-endpoints = [ + "init", + "verify_secp256r1_signature", + "verify_bls_signature_share", + "verify_bls_aggregated_signature", +] +kill_legacy_callback = true + [[proxy]] path = "src/basic_features_proxy.rs" add-unlabelled = false diff --git a/contracts/feature-tests/basic-features/wasm-basic-features-crypto/Cargo.toml b/contracts/feature-tests/basic-features/wasm-basic-features-crypto/Cargo.toml new file mode 100644 index 0000000000..46f40289e3 --- /dev/null +++ b/contracts/feature-tests/basic-features/wasm-basic-features-crypto/Cargo.toml @@ -0,0 +1,35 @@ +# Code generated by the multiversx-sc build system. DO NOT EDIT. + +# ########################################## +# ############## AUTO-GENERATED ############# +# ########################################## + +[package] +name = "basic-features-crypto-wasm" +version = "0.0.0" +edition = "2021" +publish = false + +[lib] +crate-type = ["cdylib"] + +[profile.release] +codegen-units = 1 +opt-level = "z" +lto = true +debug = false +panic = "abort" +overflow-checks = false + +[profile.dev] +panic = "abort" + +[dependencies.basic-features] +path = ".." + +[dependencies.multiversx-sc-wasm-adapter] +version = "0.52.3" +path = "../../../../framework/wasm-adapter" + +[workspace] +members = ["."] diff --git a/contracts/feature-tests/basic-features/wasm-basic-features-crypto/src/lib.rs b/contracts/feature-tests/basic-features/wasm-basic-features-crypto/src/lib.rs new file mode 100644 index 0000000000..134138a65f --- /dev/null +++ b/contracts/feature-tests/basic-features/wasm-basic-features-crypto/src/lib.rs @@ -0,0 +1,27 @@ +// Code generated by the multiversx-sc build system. DO NOT EDIT. + +//////////////////////////////////////////////////// +////////////////// AUTO-GENERATED ////////////////// +//////////////////////////////////////////////////// + +// Init: 1 +// Endpoints: 3 +// Async Callback (empty): 1 +// Total number of exported functions: 5 + +#![no_std] + +multiversx_sc_wasm_adapter::allocator!(); +multiversx_sc_wasm_adapter::panic_handler!(); + +multiversx_sc_wasm_adapter::endpoints! { + basic_features + ( + init => init + verify_secp256r1_signature => verify_secp256r1_signature + verify_bls_signature_share => verify_bls_signature_share + verify_bls_aggregated_signature => verify_bls_aggregated_signature + ) +} + +multiversx_sc_wasm_adapter::async_callback_empty! {} From 97c63ab5f81283313f99412902236d8320862a6a Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Fri, 23 Aug 2024 17:12:25 +0300 Subject: [PATCH 29/92] basic features sc-config fix --- .../basic-features/sc-config.toml | 9 +- .../basic-features/src/crypto_features.rs | 3 + .../wasm-basic-features-crypto/Cargo.lock | 186 ++++++++++++++++++ .../basic-features/wasm/src/lib.rs | 7 +- 4 files changed, 193 insertions(+), 12 deletions(-) create mode 100644 contracts/feature-tests/basic-features/wasm-basic-features-crypto/Cargo.lock diff --git a/contracts/feature-tests/basic-features/sc-config.toml b/contracts/feature-tests/basic-features/sc-config.toml index b21719850f..42c4880f67 100644 --- a/contracts/feature-tests/basic-features/sc-config.toml +++ b/contracts/feature-tests/basic-features/sc-config.toml @@ -2,7 +2,6 @@ main = "basic-features" [contracts.basic-features] -ei = "1.4" [contracts.basic-features.profile] overflow-checks = true # needed for overflow tests @@ -15,12 +14,8 @@ kill_legacy_callback = true [contracts.basic-features-crypto] ei = "1.4" add-unlabelled = false -add-endpoints = [ - "init", - "verify_secp256r1_signature", - "verify_bls_signature_share", - "verify_bls_aggregated_signature", -] +add-endpoints = ["init"] +add-labels = ["crypto-ei-1.4"] kill_legacy_callback = true [[proxy]] diff --git a/contracts/feature-tests/basic-features/src/crypto_features.rs b/contracts/feature-tests/basic-features/src/crypto_features.rs index f66479026c..4a9c7dbb6f 100644 --- a/contracts/feature-tests/basic-features/src/crypto_features.rs +++ b/contracts/feature-tests/basic-features/src/crypto_features.rs @@ -66,6 +66,7 @@ pub trait CryptoFeatures { } #[endpoint] + #[label("crypto-ei-1.4")] fn verify_secp256r1_signature( &self, key: ManagedBuffer, @@ -76,6 +77,7 @@ pub trait CryptoFeatures { } #[endpoint] + #[label("crypto-ei-1.4")] fn verify_bls_signature_share( &self, key: ManagedBuffer, @@ -87,6 +89,7 @@ pub trait CryptoFeatures { } #[endpoint] + #[label("crypto-ei-1.4")] fn verify_bls_aggregated_signature( &self, key: ManagedBuffer, diff --git a/contracts/feature-tests/basic-features/wasm-basic-features-crypto/Cargo.lock b/contracts/feature-tests/basic-features/wasm-basic-features-crypto/Cargo.lock new file mode 100644 index 0000000000..1666820785 --- /dev/null +++ b/contracts/feature-tests/basic-features/wasm-basic-features-crypto/Cargo.lock @@ -0,0 +1,186 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "basic-features" +version = "0.0.0" +dependencies = [ + "multiversx-sc", + "multiversx-sc-modules", +] + +[[package]] +name = "basic-features-crypto-wasm" +version = "0.0.0" +dependencies = [ + "basic-features", + "multiversx-sc-wasm-adapter", +] + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "endian-type" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hex-literal" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" + +[[package]] +name = "multiversx-sc" +version = "0.52.3" +dependencies = [ + "bitflags", + "hex-literal", + "multiversx-sc-codec", + "multiversx-sc-derive", + "num-traits", + "unwrap-infallible", +] + +[[package]] +name = "multiversx-sc-codec" +version = "0.20.1" +dependencies = [ + "arrayvec", + "multiversx-sc-codec-derive", + "unwrap-infallible", +] + +[[package]] +name = "multiversx-sc-codec-derive" +version = "0.20.1" +dependencies = [ + "hex", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "multiversx-sc-derive" +version = "0.52.3" +dependencies = [ + "hex", + "proc-macro2", + "quote", + "radix_trie", + "syn", +] + +[[package]] +name = "multiversx-sc-modules" +version = "0.52.3" +dependencies = [ + "multiversx-sc", +] + +[[package]] +name = "multiversx-sc-wasm-adapter" +version = "0.52.3" +dependencies = [ + "multiversx-sc", +] + +[[package]] +name = "nibble_vec" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" +dependencies = [ + "smallvec", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radix_trie" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd" +dependencies = [ + "endian-type", + "nibble_vec", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "syn" +version = "2.0.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unwrap-infallible" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "151ac09978d3c2862c4e39b557f4eceee2cc72150bc4cb4f16abf061b6e381fb" diff --git a/contracts/feature-tests/basic-features/wasm/src/lib.rs b/contracts/feature-tests/basic-features/wasm/src/lib.rs index 90986ec90b..887b75bcd5 100644 --- a/contracts/feature-tests/basic-features/wasm/src/lib.rs +++ b/contracts/feature-tests/basic-features/wasm/src/lib.rs @@ -5,9 +5,9 @@ //////////////////////////////////////////////////// // Init: 1 -// Endpoints: 406 +// Endpoints: 403 // Async Callback: 1 -// Total number of exported functions: 408 +// Total number of exported functions: 405 #![no_std] @@ -145,9 +145,6 @@ multiversx_sc_wasm_adapter::endpoints! { verify_secp256k1_signature => verify_secp256k1_signature verify_custom_secp256k1_signature => verify_custom_secp256k1_signature compute_secp256k1_der_signature => compute_secp256k1_der_signature - verify_secp256r1_signature => verify_secp256r1_signature - verify_bls_signature_share => verify_bls_signature_share - verify_bls_aggregated_signature => verify_bls_aggregated_signature echo_u64 => echo_u64 echo_i64 => echo_i64 echo_i32 => echo_i32 From e437447b3bd6806ad3989c2186052f5b6918393c Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Fri, 23 Aug 2024 18:52:52 +0200 Subject: [PATCH 30/92] test reorg --- .../scenarios/crypto_verify_bls.scen.json | 50 ---------- ..._verify_bls_aggregated_signature.scen.json | 71 ++++++++++++++ .../crypto_verify_bls_share.scen.json | 96 +++++++++++++++++++ .../crypto_verify_secp256r1.scen.json | 74 +++----------- .../tests/basic_features_scenario_go_test.rs | 10 ++ .../tests/basic_features_scenario_rs_test.rs | 16 ++++ 6 files changed, 205 insertions(+), 112 deletions(-) create mode 100644 contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_aggregated_signature.scen.json create mode 100644 contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_share.scen.json diff --git a/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls.scen.json b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls.scen.json index 7b07232695..f5c6ef194c 100644 --- a/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls.scen.json @@ -41,56 +41,6 @@ "gas": "*", "refund": "*" } - }, - { - "step": "scCall", - "id": "4", - "tx": { - "from": "address:an_account", - "to": "sc:basic-features", - "function": "verify_bls_signature_share", - "arguments": [ - "0xb5823f6e564251cc03ce7bad3da83e72576e92795d3500bba1acb30ec9a94dce87bb8aa794d67b2d61d15c33f28f6c0c23ba1dfcbf21e8f8b46286ff871afabac925303ddcaddce6254fcff6d3155797db40b3d3b5865e8fc0bd770b3d79b381", - "0x6d65737361676520746f206265207369676e6564", - "0xaf32a2ddf341c08d1eb7232f05dc34e4454155e676b58c40fddf9a036562ac2c01533d2d557cb49d73aa9d7a89744696" - ], - "gasLimit": "50,000,000", - "gasPrice": "0" - }, - "expect": { - "out": [ - "0x01" - ], - "status": "", - "logs": "*", - "gas": "*", - "refund": "*" - } - }, - { - "step": "scCall", - "id": "5", - "tx": { - "from": "address:an_account", - "to": "sc:basic-features", - "function": "verify_bls_aggregated_signature", - "arguments": [ - "0xb5823f6e564251cc03ce7bad3da83e72576e92795d3500bba1acb30ec9a94dce87bb8aa794d67b2d61d15c33f28f6c0c23ba1dfcbf21e8f8b46286ff871afabac925303ddcaddce6254fcff6d3155797db40b3d3b5865e8fc0bd770b3d79b381", - "0x6d65737361676520746f206265207369676e6564", - "0xaf32a2ddf341c08d1eb7232f05dc34e4454155e676b58c40fddf9a036562ac2c01533d2d557cb49d73aa9d7a89744696" - ], - "gasLimit": "50,000,000", - "gasPrice": "0" - }, - "expect": { - "out": [ - "0x01" - ], - "status": "", - "logs": "*", - "gas": "*", - "refund": "*" - } } ] } \ No newline at end of file diff --git a/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_aggregated_signature.scen.json b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_aggregated_signature.scen.json new file mode 100644 index 0000000000..46617194c5 --- /dev/null +++ b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_aggregated_signature.scen.json @@ -0,0 +1,71 @@ +{ + "name": "crypto", + "comment": "does not currently work with scenarios-rs, because verify_bls function is not yet mocked", + "gasSchedule": "v3", + "steps": [ + { + "step": "setState", + "accounts": { + "sc:basic-features-crypto": { + "nonce": "0", + "balance": "0", + "code": "mxsc:../output/basic-features-crypto.mxsc.json" + }, + "address:an_account": { + "nonce": "0", + "balance": "0" + } + } + }, + { + "step": "scCall", + "id": "1", + "tx": { + "from": "address:an_account", + "to": "sc:basic-features-crypto", + "function": "verify_bls_aggregated_signature", + "arguments": [ + "0x9cfb3532e21737e8f9eec99b04f000b27ec277d2477d881273ea07d3af96dc3e153878ed002bcd10e8320242caab49024b8c934b437b17e743b9706757f0e7b2e9fb28295d7f82af8875e0776ae8918c25206519b3f73dcbbd53cafeb5cec716", + "0x6d65737361676530", + "0x84737000b07fbce9b649449f9de6aae76347f5bb5eefcd017f53e874601ccf5f96c9b4ca5f85ea5f6ef6243c38c9ab99" + ], + "gasLimit": "50,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [ + "0x01" + ], + "status": "", + "logs": "*", + "gas": "*", + "refund": "*" + } + }, + { + "step": "scCall", + "id": "2", + "tx": { + "from": "address:an_account", + "to": "sc:basic-features-crypto", + "function": "verify_bls_aggregated_signature", + "arguments": [ + "0x9cfb3532e21737e8f9eec99b04f000b27ec277d2477d881273ea07d3af96dc3e153878ed002bcd10e8320242caab49024b8c934b437b17e743b9706757f0e7b2e9fb28295d7f82af8875e0776ae8918c25206519b3f73dcbbd53cafeb5cec716", + "0x6d657373616765323133", + "0x84737000b07fbce9b649449f9de6aae76347f5bb5eefcd017f53e874601ccf5f96c9b4ca5f85ea5f6ef6243c38c9ab99" + ], + "gasLimit": "50,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [ + "0x00" + ], + "status": "", + "logs": "*", + "gas": "*", + "refund": "*" + } + } + ] +} \ No newline at end of file diff --git a/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_share.scen.json b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_share.scen.json new file mode 100644 index 0000000000..046b015d86 --- /dev/null +++ b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_share.scen.json @@ -0,0 +1,96 @@ +{ + "name": "crypto", + "comment": "does not currently work with scenarios-rs, because verify_bls function is not yet mocked", + "gasSchedule": "v3", + "steps": [ + { + "step": "setState", + "accounts": { + "sc:basic-features-crypto": { + "nonce": "0", + "balance": "0", + "code": "mxsc:../output/basic-features-crypto.mxsc.json" + }, + "address:an_account": { + "nonce": "0", + "balance": "0" + } + } + }, + { + "step": "scCall", + "id": "1", + "tx": { + "from": "address:an_account", + "to": "sc:basic-features-crypto", + "function": "verify_bls_signature_share", + "arguments": [ + "0x3e886a4c6e109a151f4105aee65a5192d150ef1fa68d3cd76964a0b086006dbe4324c989deb0e4416c6d6706db1b1910eb2732f08842fb4886067b9ed191109ac2188d76002d2e11da80a3f0ea89fee6b59c834cc478a6bd49cb8a193b1abb16", + "0xe96bd0f36b70c5ccc0c4396343bd7d8255b8a526c55fa1e218511fafe6539b8e", + "0x04725db195e37aa237cdbbda76270d4a229b6e7a3651104dc58c4349c0388e8546976fe54a04240530b99064e434c90f" + ], + "gasLimit": "50,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [ + "0x01" + ], + "status": "", + "logs": "*", + "gas": "*", + "refund": "*" + } + }, + { + "step": "scCall", + "id": "2", + "tx": { + "from": "address:an_account", + "to": "sc:basic-features-crypto", + "function": "verify_bls_signature_share", + "arguments": [ + "0x2c9a358953f61d34401d7ee4175eec105c476b18baacab371e2f47270035b539d84ad79ba587552b7e38802be00ff7148fc2a9c7a7034ff1e63ee24602ee952235ad14ca7d36e2be617fb2c99ed22a7a2729d86ae9fbb4df06f957ba07fec50e", + "0x1e46d9cbb995e30b82485525c29f80ac78aca295a6e88a11c3df8f9a445494bb", + "0xbe8c460db180d6254c712ead3aa81935bc9be15b919dd45cb152b3dece04762569778c5e70e7af03fa1c66409d4f4711" + ], + "gasLimit": "50,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [ + "0x00" + ], + "status": "", + "logs": "*", + "gas": "*", + "refund": "*" + } + }, + { + "step": "scCall", + "id": "2", + "tx": { + "from": "address:an_account", + "to": "sc:basic-features", + "function": "verify_bls_aggregated_signature", + "arguments": [ + "0xb5823f6e564251cc03ce7bad3da83e72576e92795d3500bba1acb30ec9a94dce87bb8aa794d67b2d61d15c33f28f6c0c23ba1dfcbf21e8f8b46286ff871afabac925303ddcaddce6254fcff6d3155797db40b3d3b5865e8fc0bd770b3d79b381", + "0x6d65737361676520746f206265207369676e6564", + "0xaf32a2ddf341c08d1eb7232f05dc34e4454155e676b58c40fddf9a036562ac2c01533d2d557cb49d73aa9d7a89744696" + ], + "gasLimit": "50,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [ + "0x01" + ], + "status": "", + "logs": "*", + "gas": "*", + "refund": "*" + } + } + ] +} \ No newline at end of file diff --git a/contracts/feature-tests/basic-features/scenarios/crypto_verify_secp256r1.scen.json b/contracts/feature-tests/basic-features/scenarios/crypto_verify_secp256r1.scen.json index e87822db95..0de6016ef6 100644 --- a/contracts/feature-tests/basic-features/scenarios/crypto_verify_secp256r1.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/crypto_verify_secp256r1.scen.json @@ -6,10 +6,10 @@ { "step": "setState", "accounts": { - "sc:basic-features": { + "sc:basic-features-crypto": { "nonce": "0", "balance": "0", - "code": "mxsc:../output/basic-features.mxsc.json" + "code": "mxsc:../output/basic-features-crypto.mxsc.json" }, "address:an_account": { "nonce": "0", @@ -19,15 +19,15 @@ }, { "step": "scCall", - "id": "5 - compressed key", + "id": "1", "tx": { "from": "address:an_account", - "to": "sc:basic-features", + "to": "sc:basic-features-crypto", "function": "verify_secp256r1_signature", "arguments": [ - "0x02a673638cb9587cb68ea08dbef685c6f2d2a751a8b3c6f2a7e9a4999e6e4bfaf5", - "0x6d65737361676520746f207369676e", - "0x3045022100fab29dbcb623e7e96f44665f312b89ffdb9e4d2e2f53353236fbbcf57b2f49bf02203d6f9c63df8be43121042970a549a2d3baeca093fd37b726ddcc0924638409f5" + "0x03e4d20902182b89cd5ed7984ebcf063f2fd2508d9f034e4109be487be9e2cf54d", + "0xa607fab72e13d6b625942bd5c56cc32792c2c7c7f16053b2fb6d62dd9cf36fdacf9d5a8af3537eaf5eb93335b36cf8f1d6e5bb2dfffce9055a2608d5e1a5b839eacf36dd5dec6d2fa156133acf064cc26487d543873f3b3837a3c09b5f4cb509bbc6585d", + "0xd5065c32582bf0bc8f96b34177cbf47f61d4705d64daaebff884693b6dd94afd50d3ac647aeb14d325c28bb00ab68b23280c1c480cac0e72b5a58176ac8cd1b9" ], "gasLimit": "50,000,000", "gasPrice": "0" @@ -44,14 +44,14 @@ }, { "step": "scCall", - "id": "6 - uncompressed key", + "id": "2", "tx": { "from": "address:an_account", - "to": "sc:basic-features", + "to": "sc:basic-features-crypto", "function": "verify_secp256r1_signature", "arguments": [ "0x04a673638cb9587cb68ea08dbef685c6f2d2a751a8b3c6f2a7e9a4999e6e4bfaf5ca1d22fe57c6103dbaac10cf15d15c0791cab8bb9a04f800e4d215276cb3e008", - "0x6d65737361676520746f207369676e", + "0x00", "0x3045022100fab29dbcb623e7e96f44665f312b89ffdb9e4d2e2f53353236fbbcf57b2f49bf02203d6f9c63df8be43121042970a549a2d3baeca093fd37b726ddcc0924638409f5" ], "gasLimit": "50,000,000", @@ -59,57 +59,7 @@ }, "expect": { "out": [ - "0x01" - ], - "status": "", - "logs": "*", - "gas": "*", - "refund": "*" - } - }, - { - "step": "scCall", - "id": "7 - encode key from r and s", - "tx": { - "from": "address:an_account", - "to": "sc:basic-features", - "function": "compute_secp256k1_der_signature", - "arguments": [ - "0x90f27b8b488db00b00606796d2987f6a5f59ae62ea05effe84fef5b8b0e54998", - "0x4a691139ad57a3f0b906637673aa2f63d1f55cb1a69199d4009eea23ceaddc93" - ], - "gasLimit": "50,000,000", - "gasPrice": "0" - }, - "expect": { - "out": [ - "0x304502210090f27b8b488db00b00606796d2987f6a5f59ae62ea05effe84fef5b8b0e5499802204a691139ad57a3f0b906637673aa2f63d1f55cb1a69199d4009eea23ceaddc93" - ], - "status": "", - "logs": "*", - "gas": "*", - "refund": "*" - } - }, - { - "step": "scCall", - "id": "8 - verify custom secp256k1", - "tx": { - "from": "address:an_account", - "to": "sc:basic-features", - "function": "verify_custom_secp256k1_signature", - "arguments": [ - "0x04e32df42865e97135acfb65f3bae71bdc86f4d49150ad6a440b6f15878109880a0a2b2667f7e725ceea70c673093bf67663e0312623c8e091b13cf2c0f11ef652", - "0xce0677bb30baa8cf067c88db9811f4333d131bf8bcf12fe7065d211dce971008", - "0x304502210090f27b8b488db00b00606796d2987f6a5f59ae62ea05effe84fef5b8b0e5499802204a691139ad57a3f0b906637673aa2f63d1f55cb1a69199d4009eea23ceaddc93", - "0" - ], - "gasLimit": "50,000,000", - "gasPrice": "0" - }, - "expect": { - "out": [ - "0x01" + "0x00" ], "status": "", "logs": "*", @@ -118,4 +68,4 @@ } } ] -} +} \ No newline at end of file diff --git a/contracts/feature-tests/basic-features/tests/basic_features_scenario_go_test.rs b/contracts/feature-tests/basic-features/tests/basic_features_scenario_go_test.rs index f5a9a10726..3a7a5dc515 100644 --- a/contracts/feature-tests/basic-features/tests/basic_features_scenario_go_test.rs +++ b/contracts/feature-tests/basic-features/tests/basic_features_scenario_go_test.rs @@ -84,6 +84,16 @@ fn crypto_verify_bls_go() { world().run("scenarios/crypto_verify_bls.scen.json"); } +#[test] +fn crypto_verify_bls_share_go() { + world().run("scenarios/crypto_verify_bls_share.scen.json"); +} + +#[test] +fn crypto_verify_bls_aggregated_go() { + world().run("scenarios/crypto_verify_bls_aggregated_signature.scen.json"); +} + #[test] fn crypto_verify_ed_25519_go() { world().run("scenarios/crypto_verify_ed25519.scen.json"); diff --git a/contracts/feature-tests/basic-features/tests/basic_features_scenario_rs_test.rs b/contracts/feature-tests/basic-features/tests/basic_features_scenario_rs_test.rs index 95a617e20c..2689d7f3ec 100644 --- a/contracts/feature-tests/basic-features/tests/basic_features_scenario_rs_test.rs +++ b/contracts/feature-tests/basic-features/tests/basic_features_scenario_rs_test.rs @@ -11,6 +11,10 @@ fn world() -> ScenarioWorld { "mxsc:../esdt-system-sc-mock/output/esdt-system-sc-mock.mxsc.json", esdt_system_sc_mock::ContractBuilder, ); + blockchain.register_contract( + "mxsc:output/basic-features-crypto.mxsc.json", + basic_features::ContractBuilder, + ); blockchain } @@ -98,6 +102,18 @@ fn crypto_verify_bls_rs() { world().run("scenarios/crypto_verify_bls.scen.json"); } +#[test] +#[ignore] +fn crypto_verify_bls_share_rs() { + world().run("scenarios/crypto_verify_bls_share.scen.json"); +} + +#[test] +#[ignore] +fn crypto_verify_bls_aggregated_rs() { + world().run("scenarios/crypto_verify_bls_aggregated_signature.scen.json"); +} + #[test] fn crypto_verify_ed_25519_rs() { world().run("scenarios/crypto_verify_ed25519.scen.json"); From 93ebae93e5d6710b4fe0919eed9ef5f16c392ce5 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Sat, 24 Aug 2024 06:31:13 +0300 Subject: [PATCH 31/92] deprecated the older whitebox methods --- .../tests/st_whitebox_deprecated_test.rs | 54 +++++++++++++++++++ .../src/facade/scenario_world_whitebox.rs | 26 +++++++++ 2 files changed, 80 insertions(+) create mode 100644 contracts/feature-tests/scenario-tester/tests/st_whitebox_deprecated_test.rs diff --git a/contracts/feature-tests/scenario-tester/tests/st_whitebox_deprecated_test.rs b/contracts/feature-tests/scenario-tester/tests/st_whitebox_deprecated_test.rs new file mode 100644 index 0000000000..e67fd8cacf --- /dev/null +++ b/contracts/feature-tests/scenario-tester/tests/st_whitebox_deprecated_test.rs @@ -0,0 +1,54 @@ +#![allow(deprecated)] + +use multiversx_sc_scenario::imports::*; +use scenario_tester::*; + +const ADDER_PATH_EXPR: &str = "mxsc:output/scenario-tester.mxsc.json"; + +fn world() -> ScenarioWorld { + let mut blockchain = ScenarioWorld::new(); + + blockchain.register_contract( + "mxsc:output/scenario-tester.mxsc.json", + scenario_tester::ContractBuilder, + ); + blockchain +} + +#[test] +fn st_whitebox() { + let mut world = world(); + let st_whitebox = WhiteboxContract::new("sc:adder", scenario_tester::contract_obj); + let st_code = world.code_expression(ADDER_PATH_EXPR); + + world + .set_state_step( + SetStateStep::new() + .put_account("address:owner", Account::new().nonce(1)) + .new_address("address:owner", 1, "sc:adder"), + ) + .whitebox_deploy( + &st_whitebox, + ScDeployStep::new().from("address:owner").code(st_code), + |sc| { + sc.init(5u32.into()); + }, + ) + .whitebox_query(&st_whitebox, |sc| { + let sum_value = sc.sum(); + assert_eq!(sum_value.get(), 5u32); + }) + .whitebox_call( + &st_whitebox, + ScCallStep::new().from("address:owner"), + |sc| sc.add(3u32.into()), + ) + .check_state_step( + CheckStateStep::new() + .put_account("address:owner", CheckAccount::new()) + .put_account( + "sc:adder", + CheckAccount::new().check_storage("str:sum", "8"), + ), + ); +} diff --git a/framework/scenario/src/facade/scenario_world_whitebox.rs b/framework/scenario/src/facade/scenario_world_whitebox.rs index 32a148ad0a..542e0fe0b2 100644 --- a/framework/scenario/src/facade/scenario_world_whitebox.rs +++ b/framework/scenario/src/facade/scenario_world_whitebox.rs @@ -1,3 +1,5 @@ +#![allow(deprecated)] + use multiversx_chain_vm::tx_mock::{TxFunctionName, TxResult}; use multiversx_sc::contract_base::{CallableContract, ContractBase}; @@ -10,6 +12,10 @@ use crate::{ use super::whitebox_contract::WhiteboxContract; impl ScenarioWorld { + #[deprecated( + since = "0.53.0", + note = "Please use method `whitebox`, as part of the unified transaction syntax." + )] pub fn whitebox_query( &mut self, whitebox_contract: &WhiteboxContract, @@ -24,6 +30,10 @@ impl ScenarioWorld { }) } + #[deprecated( + since = "0.53.0", + note = "Please use method `whitebox`, as part of the unified transaction syntax." + )] pub fn whitebox_query_check( &mut self, whitebox_contract: &WhiteboxContract, @@ -50,6 +60,10 @@ impl ScenarioWorld { self } + #[deprecated( + since = "0.53.0", + note = "Please use method `whitebox`, as part of the unified transaction syntax." + )] pub fn whitebox_call( &mut self, whitebox_contract: &WhiteboxContract, @@ -65,6 +79,10 @@ impl ScenarioWorld { }) } + #[deprecated( + since = "0.53.0", + note = "Please use method `whitebox`, as part of the unified transaction syntax." + )] pub fn whitebox_call_check( &mut self, whitebox_contract: &WhiteboxContract, @@ -99,6 +117,10 @@ impl ScenarioWorld { self } + #[deprecated( + since = "0.53.0", + note = "Please use method `whitebox`, as part of the unified transaction syntax." + )] pub fn whitebox_deploy( &mut self, whitebox_contract: &WhiteboxContract, @@ -114,6 +136,10 @@ impl ScenarioWorld { }) } + #[deprecated( + since = "0.53.0", + note = "Please use method `whitebox`, as part of the unified transaction syntax." + )] pub fn whitebox_deploy_check( &mut self, whitebox_contract: &WhiteboxContract, From e9397b00cd56c1ebd677ef6a055063090a84b62f Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Sat, 24 Aug 2024 06:42:55 +0300 Subject: [PATCH 32/92] price aggregator whitebox migration --- .../tests/price_aggregator_blackbox_test.rs | 51 +++++++++---------- .../tests/price_aggregator_stress_blackbox.rs | 23 +++------ 2 files changed, 30 insertions(+), 44 deletions(-) diff --git a/contracts/core/price-aggregator/tests/price_aggregator_blackbox_test.rs b/contracts/core/price-aggregator/tests/price_aggregator_blackbox_test.rs index b0e1f54455..a312b0ca1f 100644 --- a/contracts/core/price-aggregator/tests/price_aggregator_blackbox_test.rs +++ b/contracts/core/price-aggregator/tests/price_aggregator_blackbox_test.rs @@ -1,6 +1,6 @@ use multiversx_price_aggregator_sc::{ price_aggregator_data::{OracleStatus, TimestampedPrice, TokenPair}, - ContractObj, PriceAggregator, MAX_ROUND_DURATION_SECONDS, + PriceAggregator, MAX_ROUND_DURATION_SECONDS, }; use multiversx_sc_scenario::imports::*; @@ -35,7 +35,6 @@ fn world() -> ScenarioWorld { struct PriceAggregatorTestState { world: ScenarioWorld, oracles: Vec, - price_aggregator_whitebox: WhiteboxContract>, } impl PriceAggregatorTestState { @@ -57,16 +56,7 @@ impl PriceAggregatorTestState { oracles.push(address_value); } - let price_aggregator_whitebox = WhiteboxContract::new( - PRICE_AGGREGATOR_ADDRESS, - multiversx_price_aggregator_sc::contract_obj, - ); - - Self { - world, - oracles, - price_aggregator_whitebox, - } + Self { world, oracles } } fn deploy(&mut self) -> &mut Self { @@ -203,9 +193,10 @@ fn test_price_aggregator_submit() { state.submit(&state.oracles[0].clone(), 95, 100); let current_timestamp = 100; - state - .world - .whitebox_query(&state.price_aggregator_whitebox, |sc| { + + state.world.query().to(PRICE_AGGREGATOR_ADDRESS).whitebox( + multiversx_price_aggregator_sc::contract_obj, + |sc| { let token_pair = TokenPair { from: managed_buffer!(EGLD_TICKER), to: managed_buffer!(USD_TICKER), @@ -237,14 +228,15 @@ fn test_price_aggregator_submit() { accepted_submissions: 1 } ); - }); + }, + ); // first oracle submit again - submission not accepted state.submit(&state.oracles[0].clone(), 95, 100); - state - .world - .whitebox_query(&state.price_aggregator_whitebox, |sc| { + state.world.query().to(PRICE_AGGREGATOR_ADDRESS).whitebox( + multiversx_price_aggregator_sc::contract_obj, + |sc| { assert_eq!( sc.oracle_status() .get(&managed_address!(&state.oracles[0].to_address())) @@ -254,7 +246,8 @@ fn test_price_aggregator_submit() { accepted_submissions: 1 } ); - }); + }, + ); } #[test] @@ -283,9 +276,9 @@ fn test_price_aggregator_submit_round_ok() { // submit third state.submit(&state.oracles[2].clone(), 105, 12_000); - state - .world - .whitebox_query(&state.price_aggregator_whitebox, |sc| { + state.world.query().to(PRICE_AGGREGATOR_ADDRESS).whitebox( + multiversx_price_aggregator_sc::contract_obj, + |sc| { let result = sc.latest_price_feed(managed_buffer!(EGLD_TICKER), managed_buffer!(USD_TICKER)); @@ -312,7 +305,8 @@ fn test_price_aggregator_submit_round_ok() { decimals } ); - }); + }, + ); } #[test] @@ -338,9 +332,9 @@ fn test_price_aggregator_discarded_round() { // submit second - this will discard the previous submission state.submit(&state.oracles[1].clone(), current_timestamp - 1, 11_000); - state - .world - .whitebox_query(&state.price_aggregator_whitebox, |sc| { + state.world.query().to(PRICE_AGGREGATOR_ADDRESS).whitebox( + multiversx_price_aggregator_sc::contract_obj, + |sc| { let token_pair = TokenPair { from: managed_buffer!(EGLD_TICKER), to: managed_buffer!(USD_TICKER), @@ -353,7 +347,8 @@ fn test_price_aggregator_discarded_round() { .unwrap(), managed_biguint!(11_000) ); - }); + }, + ); } #[test] diff --git a/contracts/core/price-aggregator/tests/price_aggregator_stress_blackbox.rs b/contracts/core/price-aggregator/tests/price_aggregator_stress_blackbox.rs index 660bbf1dda..be457448b5 100644 --- a/contracts/core/price-aggregator/tests/price_aggregator_stress_blackbox.rs +++ b/contracts/core/price-aggregator/tests/price_aggregator_stress_blackbox.rs @@ -1,6 +1,6 @@ use multiversx_price_aggregator_sc::{ price_aggregator_data::{OracleStatus, TokenPair}, - ContractObj, PriceAggregator, + PriceAggregator, }; use multiversx_sc_scenario::imports::*; @@ -34,7 +34,6 @@ fn world() -> ScenarioWorld { struct PriceAggregatorTestState { world: ScenarioWorld, oracles: Vec, - price_aggregator_whitebox: WhiteboxContract>, } impl PriceAggregatorTestState { @@ -60,16 +59,7 @@ impl PriceAggregatorTestState { oracles.push(address_value); } - let price_aggregator_whitebox = WhiteboxContract::new( - PRICE_AGGREGATOR_ADDRESS, - multiversx_price_aggregator_sc::contract_obj, - ); - - Self { - world, - oracles, - price_aggregator_whitebox, - } + Self { world, oracles } } fn deploy(&mut self) -> &mut Self { @@ -170,9 +160,9 @@ fn test_price_aggregator_submit() { } let current_timestamp = 100; - state - .world - .whitebox_query(&state.price_aggregator_whitebox, |sc| { + state.world.query().to(PRICE_AGGREGATOR_ADDRESS).whitebox( + multiversx_price_aggregator_sc::contract_obj, + |sc| { let blockchain_timestamp = sc.blockchain().get_block_timestamp(); let token_pair = TokenPair { @@ -207,7 +197,8 @@ fn test_price_aggregator_submit() { } ); } - }); + }, + ); // submit last that resets the round state.submit( From c841e2a6eab8f390675abf4b21ec2b01461ddcba Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Sat, 24 Aug 2024 07:16:43 +0300 Subject: [PATCH 33/92] forwarder whitebox migration --- .../tests/forwarder_whitebox_legacy_test.rs | 124 ++++++------------ .../tests/forwarder_whitebox_test.rs | 115 ++++++---------- .../interaction/expr/test_token_identifier.rs | 4 + 3 files changed, 89 insertions(+), 154 deletions(-) diff --git a/contracts/feature-tests/composability/tests/forwarder_whitebox_legacy_test.rs b/contracts/feature-tests/composability/tests/forwarder_whitebox_legacy_test.rs index 8766bfa174..f6cfb158f6 100644 --- a/contracts/feature-tests/composability/tests/forwarder_whitebox_legacy_test.rs +++ b/contracts/feature-tests/composability/tests/forwarder_whitebox_legacy_test.rs @@ -1,24 +1,16 @@ use forwarder_legacy::fwd_nft_legacy::{Color, ForwarderNftModule}; -use multiversx_sc::{contract_base::ContractBase, types::Address}; -use multiversx_sc_scenario::{ - managed_address, managed_biguint, managed_token_id, - scenario_model::{ - Account, AddressValue, CheckAccount, CheckStateStep, ScCallStep, SetStateStep, - }, - ScenarioWorld, WhiteboxContract, -}; -const USER_ADDRESS_EXPR: &str = "address:user"; -const FORWARDER_ADDRESS_EXPR: &str = "sc:forwarder_legacy"; -const FORWARDER_PATH_EXPR: &str = "mxsc:output/forwarder_legacy.mxsc.json"; +use multiversx_sc_scenario::imports::*; -const NFT_TOKEN_ID_EXPR: &str = "str:COOL-123456"; -const NFT_TOKEN_ID: &[u8] = b"COOL-123456"; +const USER_ADDRESS: TestAddress = TestAddress::new("user"); +const FORWARDER_ADDRESS: TestSCAddress = TestSCAddress::new("forwarder_legacy"); +const FORWARDER_PATH: MxscPath = MxscPath::new("output/forwarder_legacy.mxsc.json"); +const NFT_TOKEN_ID: TestTokenIdentifier = TestTokenIdentifier::new("COOL-123456"); fn world() -> ScenarioWorld { let mut blockchain = ScenarioWorld::new(); - blockchain.register_contract(FORWARDER_PATH_EXPR, forwarder_legacy::ContractBuilder); + blockchain.register_contract(FORWARDER_PATH, forwarder_legacy::ContractBuilder); blockchain } @@ -26,57 +18,40 @@ fn world() -> ScenarioWorld { fn test_nft_update_attributes_and_send() { let mut world = world(); - let forwarder_legacy_code = world.code_expression(FORWARDER_PATH_EXPR); let roles = vec![ "ESDTRoleNFTCreate".to_string(), "ESDTRoleNFTUpdateAttributes".to_string(), ]; - world.set_state_step( - SetStateStep::new() - .put_account(USER_ADDRESS_EXPR, Account::new().nonce(1)) - .put_account( - FORWARDER_ADDRESS_EXPR, - Account::new() - .nonce(1) - .code(forwarder_legacy_code) - .esdt_roles(NFT_TOKEN_ID_EXPR, roles), - ), - ); - - let forwarder_legacy_whitebox = - WhiteboxContract::new(FORWARDER_ADDRESS_EXPR, forwarder_legacy::contract_obj); + world.account(USER_ADDRESS).nonce(1); + world + .account(FORWARDER_ADDRESS) + .nonce(1) + .code(FORWARDER_PATH) + .esdt_roles(NFT_TOKEN_ID, roles); let original_attributes = Color { r: 0, g: 0, b: 0 }; - world.whitebox_call( - &forwarder_legacy_whitebox, - ScCallStep::new().from(USER_ADDRESS_EXPR), - |sc| { + world + .tx() + .from(USER_ADDRESS) + .to(FORWARDER_ADDRESS) + .whitebox(forwarder_legacy::contract_obj, |sc| { sc.nft_create_compact( - managed_token_id!(NFT_TOKEN_ID), + NFT_TOKEN_ID.to_token_identifier(), managed_biguint!(1), original_attributes, ); - sc.send().direct_esdt( - &managed_address!(&address_expr_to_address(USER_ADDRESS_EXPR)), - &managed_token_id!(NFT_TOKEN_ID), - 1, - &managed_biguint!(1), - ); - }, - ); + sc.tx() + .to(USER_ADDRESS) + .esdt((NFT_TOKEN_ID.to_token_identifier(), 1, 1u32.into())) + .transfer(); + }); - world.check_state_step(CheckStateStep::new().put_account( - USER_ADDRESS_EXPR, - CheckAccount::new().esdt_nft_balance_and_attributes( - NFT_TOKEN_ID_EXPR, - 1, - "1", - Some(original_attributes), - ), - )); + world + .check_account(USER_ADDRESS) + .esdt_nft_balance_and_attributes(NFT_TOKEN_ID, 1, 1, original_attributes); let new_attributes = Color { r: 255, @@ -84,34 +59,21 @@ fn test_nft_update_attributes_and_send() { b: 255, }; - world.whitebox_call( - &forwarder_legacy_whitebox, - ScCallStep::new() - .from(USER_ADDRESS_EXPR) - .esdt_transfer(NFT_TOKEN_ID, 1, "1"), - |sc| { - sc.nft_update_attributes(managed_token_id!(NFT_TOKEN_ID), 1, new_attributes); - - sc.send().direct_esdt( - &managed_address!(&address_expr_to_address(USER_ADDRESS_EXPR)), - &managed_token_id!(NFT_TOKEN_ID), - 1, - &managed_biguint!(1), - ); - }, - ); - - world.check_state_step(CheckStateStep::new().put_account( - USER_ADDRESS_EXPR, - CheckAccount::new().esdt_nft_balance_and_attributes( - NFT_TOKEN_ID_EXPR, - 1, - "1", - Some(new_attributes), - ), - )); -} - -fn address_expr_to_address(address_expr: &str) -> Address { - AddressValue::from(address_expr).to_address() + world + .tx() + .from(USER_ADDRESS) + .to(FORWARDER_ADDRESS) + .single_esdt(&TokenIdentifier::from(NFT_TOKEN_ID), 1, &1u32.into()) + .whitebox(forwarder_legacy::contract_obj, |sc| { + sc.nft_update_attributes(NFT_TOKEN_ID.to_token_identifier(), 1, new_attributes); + + sc.tx() + .to(USER_ADDRESS) + .esdt((NFT_TOKEN_ID.to_token_identifier(), 1, 1u32.into())) + .transfer(); + }); + + world + .check_account(USER_ADDRESS) + .esdt_nft_balance_and_attributes(NFT_TOKEN_ID, 1, 1, new_attributes); } diff --git a/contracts/feature-tests/composability/tests/forwarder_whitebox_test.rs b/contracts/feature-tests/composability/tests/forwarder_whitebox_test.rs index 1dbf3952f2..c861c561ef 100644 --- a/contracts/feature-tests/composability/tests/forwarder_whitebox_test.rs +++ b/contracts/feature-tests/composability/tests/forwarder_whitebox_test.rs @@ -1,17 +1,15 @@ use forwarder::fwd_nft::{Color, ForwarderNftModule}; use multiversx_sc_scenario::imports::*; -const USER_ADDRESS_EXPR: &str = "address:user"; -const FORWARDER_ADDRESS_EXPR: &str = "sc:forwarder"; -const FORWARDER_PATH_EXPR: &str = "mxsc:output/forwarder.mxsc.json"; - -const NFT_TOKEN_ID_EXPR: &str = "str:COOL-123456"; -const NFT_TOKEN_ID: &[u8] = b"COOL-123456"; +const USER_ADDRESS: TestAddress = TestAddress::new("user"); +const FORWARDER_ADDRESS: TestSCAddress = TestSCAddress::new("forwarder"); +const FORWARDER_PATH: MxscPath = MxscPath::new("output/forwarder.mxsc.json"); +const NFT_TOKEN_ID: TestTokenIdentifier = TestTokenIdentifier::new("COOL-123456"); fn world() -> ScenarioWorld { let mut blockchain = ScenarioWorld::new(); - blockchain.register_contract(FORWARDER_PATH_EXPR, forwarder::ContractBuilder); + blockchain.register_contract(FORWARDER_PATH, forwarder::ContractBuilder); blockchain } @@ -19,56 +17,40 @@ fn world() -> ScenarioWorld { fn test_nft_update_attributes_and_send() { let mut world = world(); - let forwarder_code = world.code_expression(FORWARDER_PATH_EXPR); let roles = vec![ "ESDTRoleNFTCreate".to_string(), "ESDTRoleNFTUpdateAttributes".to_string(), ]; - world.set_state_step( - SetStateStep::new() - .put_account(USER_ADDRESS_EXPR, Account::new().nonce(1)) - .put_account( - FORWARDER_ADDRESS_EXPR, - Account::new() - .nonce(1) - .code(forwarder_code) - .esdt_roles(NFT_TOKEN_ID_EXPR, roles), - ), - ); - - let forwarder_whitebox = WhiteboxContract::new(FORWARDER_ADDRESS_EXPR, forwarder::contract_obj); + world.account(USER_ADDRESS).nonce(1); + world + .account(FORWARDER_ADDRESS) + .nonce(1) + .code(FORWARDER_PATH) + .esdt_roles(NFT_TOKEN_ID, roles); let original_attributes = Color { r: 0, g: 0, b: 0 }; - world.whitebox_call( - &forwarder_whitebox, - ScCallStep::new().from(USER_ADDRESS_EXPR), - |sc| { + world + .tx() + .from(USER_ADDRESS) + .to(FORWARDER_ADDRESS) + .whitebox(forwarder::contract_obj, |sc| { sc.nft_create_compact( - managed_token_id!(NFT_TOKEN_ID), + NFT_TOKEN_ID.to_token_identifier(), managed_biguint!(1), original_attributes, ); - sc.send().direct_esdt( - &managed_address!(&address_expr_to_address(USER_ADDRESS_EXPR)), - &managed_token_id!(NFT_TOKEN_ID), - 1, - &managed_biguint!(1), - ); - }, - ); + sc.tx() + .to(USER_ADDRESS) + .esdt((NFT_TOKEN_ID.to_token_identifier(), 1, 1u32.into())) + .transfer(); + }); - world.check_state_step(CheckStateStep::new().put_account( - USER_ADDRESS_EXPR, - CheckAccount::new().esdt_nft_balance_and_attributes( - NFT_TOKEN_ID_EXPR, - 1, - "1", - Some(original_attributes), - ), - )); + world + .check_account(USER_ADDRESS) + .esdt_nft_balance_and_attributes(NFT_TOKEN_ID, 1, 1, original_attributes); let new_attributes = Color { r: 255, @@ -76,34 +58,21 @@ fn test_nft_update_attributes_and_send() { b: 255, }; - world.whitebox_call( - &forwarder_whitebox, - ScCallStep::new() - .from(USER_ADDRESS_EXPR) - .esdt_transfer(NFT_TOKEN_ID, 1, "1"), - |sc| { - sc.nft_update_attributes(managed_token_id!(NFT_TOKEN_ID), 1, new_attributes); - - sc.send().direct_esdt( - &managed_address!(&address_expr_to_address(USER_ADDRESS_EXPR)), - &managed_token_id!(NFT_TOKEN_ID), - 1, - &managed_biguint!(1), - ); - }, - ); - - world.check_state_step(CheckStateStep::new().put_account( - USER_ADDRESS_EXPR, - CheckAccount::new().esdt_nft_balance_and_attributes( - NFT_TOKEN_ID_EXPR, - 1, - "1", - Some(new_attributes), - ), - )); -} - -fn address_expr_to_address(address_expr: &str) -> Address { - AddressValue::from(address_expr).to_address() + world + .tx() + .from(USER_ADDRESS) + .to(FORWARDER_ADDRESS) + .single_esdt(&TokenIdentifier::from(NFT_TOKEN_ID), 1, &1u32.into()) + .whitebox(forwarder::contract_obj, |sc| { + sc.nft_update_attributes(NFT_TOKEN_ID.to_token_identifier(), 1, new_attributes); + + sc.tx() + .to(USER_ADDRESS) + .esdt((NFT_TOKEN_ID.to_token_identifier(), 1, 1u32.into())) + .transfer(); + }); + + world + .check_account(USER_ADDRESS) + .esdt_nft_balance_and_attributes(NFT_TOKEN_ID, 1, 1, new_attributes); } diff --git a/framework/base/src/types/interaction/expr/test_token_identifier.rs b/framework/base/src/types/interaction/expr/test_token_identifier.rs index 47568b37ba..56d9a8bcd9 100644 --- a/framework/base/src/types/interaction/expr/test_token_identifier.rs +++ b/framework/base/src/types/interaction/expr/test_token_identifier.rs @@ -26,6 +26,10 @@ impl<'a> TestTokenIdentifier<'a> { pub fn eval_to_expr(&self) -> alloc::string::String { alloc::format!("{STR_PREFIX}{}", self.name) } + + pub fn to_token_identifier(&self) -> TokenIdentifier { + self.name.into() + } } impl<'a, Env> AnnotatedValue> for TestTokenIdentifier<'a> From ed3af84375d436f5d320a05793257eca4daadb8e Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Sat, 24 Aug 2024 07:24:17 +0300 Subject: [PATCH 34/92] rewards distribution test migration --- .../rewards_distribution_integration_test.rs | 26 +++++++------------ 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/contracts/examples/rewards-distribution/tests/rewards_distribution_integration_test.rs b/contracts/examples/rewards-distribution/tests/rewards_distribution_integration_test.rs index be3a4cb788..f9b64545bd 100644 --- a/contracts/examples/rewards-distribution/tests/rewards_distribution_integration_test.rs +++ b/contracts/examples/rewards-distribution/tests/rewards_distribution_integration_test.rs @@ -6,7 +6,7 @@ use multiversx_sc_scenario::imports::*; use std::iter::zip; use rewards_distribution::{ - rewards_distribution_proxy, ContractObj, RewardsDistribution, DIVISION_SAFETY_CONSTANT, + rewards_distribution_proxy, RewardsDistribution, DIVISION_SAFETY_CONSTANT, }; const ALICE_ADDRESS: TestAddress = TestAddress::new("alice"); @@ -31,7 +31,6 @@ fn world() -> ScenarioWorld { struct RewardsDistributionTestState { world: ScenarioWorld, - rewards_distribution_whitebox: WhiteboxContract>, } impl RewardsDistributionTestState { @@ -40,15 +39,7 @@ impl RewardsDistributionTestState { world.account(OWNER_ADDRESS).nonce(1); - let rewards_distribution_whitebox = WhiteboxContract::new( - REWARDS_DISTRIBUTION_ADDRESS, - rewards_distribution::contract_obj, - ); - - Self { - world, - rewards_distribution_whitebox, - } + Self { world } } fn deploy_seed_nft_minter_contract(&mut self) -> &mut Self { @@ -110,10 +101,12 @@ fn test_compute_brackets() { .owner(OWNER_ADDRESS) .code(REWARDS_DISTRIBUTION_PATH); - state.world.whitebox_call( - &state.rewards_distribution_whitebox, - ScCallStep::new().from(OWNER_ADDRESS), - |sc| { + state + .world + .tx() + .from(OWNER_ADDRESS) + .to(REWARDS_DISTRIBUTION_ADDRESS) + .whitebox(rewards_distribution::contract_obj, |sc| { let brackets = utils::to_brackets(&[ (10, 2_000), (90, 6_000), @@ -140,8 +133,7 @@ fn test_compute_brackets() { assert_eq!(computed.end_index, expected_end_index); assert_eq!(computed.nft_reward_percent, expected_reward_percent); } - }, - ); + }); } #[test] From 6e2d67345fdba2bafb84790403d4dd6e0514e6b5 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Sat, 24 Aug 2024 07:24:31 +0300 Subject: [PATCH 35/92] allow deprecated --- .../use-module/tests/token_merge_module_whitebox_test.rs | 2 ++ 1 file changed, 2 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 803992d49b..5cc2180d01 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,3 +1,5 @@ +#![allow(deprecated)] // TODO: migrate to unified syntax at some point + use multiversx_sc_scenario::imports::*; use multiversx_sc_modules::token_merge::{ From f9c8de7b6d373e544ed87257f91f4515a5ab5769 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Sat, 24 Aug 2024 08:17:54 +0300 Subject: [PATCH 36/92] TestTokenIdentifier --- .../tests/forwarder_whitebox_legacy_test.rs | 2 +- .../tests/forwarder_whitebox_test.rs | 2 +- .../tests/transfer_role_whitebox_test.rs | 24 +--- .../tests/gov_module_whitebox_test.rs | 117 +++++------------- .../tests/staking_module_whitebox_test.rs | 70 ++++------- .../interaction/expr/test_token_identifier.rs | 8 ++ .../base/src/types/interaction/tx_payment.rs | 2 + .../tx_payment/test_esdt_transfer.rs | 69 +++++++++++ 8 files changed, 137 insertions(+), 157 deletions(-) create mode 100644 framework/base/src/types/interaction/tx_payment/test_esdt_transfer.rs diff --git a/contracts/feature-tests/composability/tests/forwarder_whitebox_legacy_test.rs b/contracts/feature-tests/composability/tests/forwarder_whitebox_legacy_test.rs index f6cfb158f6..88e945529a 100644 --- a/contracts/feature-tests/composability/tests/forwarder_whitebox_legacy_test.rs +++ b/contracts/feature-tests/composability/tests/forwarder_whitebox_legacy_test.rs @@ -63,7 +63,7 @@ fn test_nft_update_attributes_and_send() { .tx() .from(USER_ADDRESS) .to(FORWARDER_ADDRESS) - .single_esdt(&TokenIdentifier::from(NFT_TOKEN_ID), 1, &1u32.into()) + .payment(TestEsdtTransfer(NFT_TOKEN_ID, 0, 1)) .whitebox(forwarder_legacy::contract_obj, |sc| { sc.nft_update_attributes(NFT_TOKEN_ID.to_token_identifier(), 1, new_attributes); diff --git a/contracts/feature-tests/composability/tests/forwarder_whitebox_test.rs b/contracts/feature-tests/composability/tests/forwarder_whitebox_test.rs index c861c561ef..b33b7d98a8 100644 --- a/contracts/feature-tests/composability/tests/forwarder_whitebox_test.rs +++ b/contracts/feature-tests/composability/tests/forwarder_whitebox_test.rs @@ -62,7 +62,7 @@ fn test_nft_update_attributes_and_send() { .tx() .from(USER_ADDRESS) .to(FORWARDER_ADDRESS) - .single_esdt(&TokenIdentifier::from(NFT_TOKEN_ID), 1, &1u32.into()) + .payment(TestEsdtTransfer(NFT_TOKEN_ID, 0, 1)) .whitebox(forwarder::contract_obj, |sc| { sc.nft_update_attributes(NFT_TOKEN_ID.to_token_identifier(), 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 130c2b237c..5ed03c38bc 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 @@ -70,11 +70,7 @@ fn test_transfer_role() { .tx() .from(USER_ADDRESS) .to(TRANSFER_ROLE_FEATURES_ADDRESS) - .single_esdt( - &TokenIdentifier::from(TRANSFER_TOKEN_ID), - 0, - &BigUint::from(100u64), - ) + .payment(TestEsdtTransfer(TRANSFER_TOKEN_ID, 0, 100)) .whitebox(transfer_role_features::contract_obj, |sc| { let payments = ManagedVec::from_single_item(EsdtTokenPayment::new( managed_token_id!(TRANSFER_TOKEN_ID_EXPR), @@ -101,11 +97,7 @@ fn test_transfer_role() { .tx() .from(USER_ADDRESS) .to(TRANSFER_ROLE_FEATURES_ADDRESS) - .single_esdt( - &TokenIdentifier::from(TRANSFER_TOKEN_ID), - 0, - &BigUint::from(100u64), - ) + .payment(TestEsdtTransfer(TRANSFER_TOKEN_ID, 0, 100)) .returns(ExpectError(4u64, "Destination address not whitelisted")) .whitebox(transfer_role_features::contract_obj, |sc| { let payments = ManagedVec::from_single_item(EsdtTokenPayment::new( @@ -126,11 +118,7 @@ fn test_transfer_role() { .tx() .from(USER_ADDRESS) .to(TRANSFER_ROLE_FEATURES_ADDRESS) - .single_esdt( - &TokenIdentifier::from(TRANSFER_TOKEN_ID), - 0, - &BigUint::from(100u64), - ) + .payment(TestEsdtTransfer(TRANSFER_TOKEN_ID, 0, 100)) .whitebox(transfer_role_features::contract_obj, |sc| { let payments = ManagedVec::from_single_item(EsdtTokenPayment::new( managed_token_id!(TRANSFER_TOKEN_ID_EXPR), @@ -159,11 +147,7 @@ fn test_transfer_role() { .tx() .from(USER_ADDRESS) .to(TRANSFER_ROLE_FEATURES_ADDRESS) - .single_esdt( - &TokenIdentifier::from(TRANSFER_TOKEN_ID), - 0, - &BigUint::from(100u64), - ) + .payment(TestEsdtTransfer(TRANSFER_TOKEN_ID, 0, 100)) .whitebox(transfer_role_features::contract_obj, |sc| { let payments = ManagedVec::from_single_item(EsdtTokenPayment::new( managed_token_id!(TRANSFER_TOKEN_ID_EXPR), 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 288d3042f5..800797024b 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,8 +4,7 @@ use multiversx_sc_modules::governance::{ }; use multiversx_sc_scenario::imports::*; -const GOV_TOKEN_ID_EXPR: TestTokenIdentifier = TestTokenIdentifier::new("GOV-123456"); -const GOV_TOKEN_ID: &[u8] = b"GOV-123456"; +const GOV_TOKEN_ID: TestTokenIdentifier = TestTokenIdentifier::new("GOV-123456"); const QUORUM: u64 = 1_500; const MIN_BALANCE_PROPOSAL: u64 = 500; const VOTING_DELAY_BLOCKS: u64 = 10; @@ -42,19 +41,19 @@ fn setup() -> ScenarioWorld { world .account(OWNER_ADDRESS) .nonce(1) - .esdt_balance(GOV_TOKEN_ID_EXPR, INITIAL_GOV_TOKEN_BALANCE); + .esdt_balance(GOV_TOKEN_ID, INITIAL_GOV_TOKEN_BALANCE); world .account(FIRST_USER_ADDRESS) .nonce(1) - .esdt_balance(GOV_TOKEN_ID_EXPR, INITIAL_GOV_TOKEN_BALANCE); + .esdt_balance(GOV_TOKEN_ID, INITIAL_GOV_TOKEN_BALANCE); world .account(SECOND_USER_ADDRESS) .nonce(1) - .esdt_balance(GOV_TOKEN_ID_EXPR, INITIAL_GOV_TOKEN_BALANCE); + .esdt_balance(GOV_TOKEN_ID, INITIAL_GOV_TOKEN_BALANCE); world .account(THIRD_USER_ADDRESS) .nonce(1) - .esdt_balance(GOV_TOKEN_ID_EXPR, INITIAL_GOV_TOKEN_BALANCE); + .esdt_balance(GOV_TOKEN_ID, INITIAL_GOV_TOKEN_BALANCE); // init let new_address = world @@ -66,7 +65,7 @@ fn setup() -> ScenarioWorld { .returns(ReturnsNewBech32Address) .whitebox(use_module::contract_obj, |sc| { sc.init_governance_module( - TokenIdentifier::from(GOV_TOKEN_ID_EXPR), + TokenIdentifier::from(GOV_TOKEN_ID), BigUint::from(QUORUM), BigUint::from(MIN_BALANCE_PROPOSAL), VOTING_DELAY_BLOCKS, @@ -96,11 +95,7 @@ pub fn propose( .tx() .from(proposer) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(GOV_TOKEN_ID_EXPR), - 0, - &BigUint::from(gov_token_amount), - ) + .payment(TestEsdtTransfer(GOV_TOKEN_ID, 0, gov_token_amount)) .whitebox(use_module::contract_obj, |sc| { let mut args_managed = ManagedVec::new(); for arg in args { @@ -151,11 +146,7 @@ fn test_change_gov_config() { .tx() .from(SECOND_USER_ADDRESS) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(GOV_TOKEN_ID), - 0, - &BigUint::from(999u64), - ) + .payment(TestEsdtTransfer(GOV_TOKEN_ID, 0, 999)) .returns(ExpectError(4u64, "Proposal is not active")) .whitebox(use_module::contract_obj, |sc| { sc.vote(proposal_id, VoteType::UpVote); @@ -168,11 +159,7 @@ fn test_change_gov_config() { .tx() .from(SECOND_USER_ADDRESS) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(GOV_TOKEN_ID), - 0, - &BigUint::from(999u64), - ) + .payment(TestEsdtTransfer(GOV_TOKEN_ID, 0, 999)) .whitebox(use_module::contract_obj, |sc| { sc.vote(proposal_id, VoteType::UpVote); }); @@ -218,11 +205,7 @@ fn test_change_gov_config() { .tx() .from(FIRST_USER_ADDRESS) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(GOV_TOKEN_ID), - 0, - &BigUint::from(200u64), - ) + .payment(TestEsdtTransfer(GOV_TOKEN_ID, 0, 200)) .whitebox(use_module::contract_obj, |sc| { sc.vote(proposal_id, VoteType::UpVote); }); @@ -232,11 +215,7 @@ fn test_change_gov_config() { .tx() .from(OWNER_ADDRESS) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(GOV_TOKEN_ID), - 0, - &BigUint::from(200u64), - ) + .payment(TestEsdtTransfer(GOV_TOKEN_ID, 0, 200)) .whitebox(use_module::contract_obj, |sc| { sc.vote(proposal_id, VoteType::DownVote); }); @@ -262,11 +241,7 @@ fn test_change_gov_config() { .tx() .from(FIRST_USER_ADDRESS) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(GOV_TOKEN_ID), - 0, - &BigUint::from(200u64), - ) + .payment(TestEsdtTransfer(GOV_TOKEN_ID, 0, 200)) .returns(ExpectError(4u64, "Already voted for this proposal")) .whitebox(use_module::contract_obj, |sc| { sc.vote(proposal_id, VoteType::UpVote); @@ -277,11 +252,7 @@ fn test_change_gov_config() { .tx() .from(THIRD_USER_ADDRESS) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(GOV_TOKEN_ID), - 0, - &BigUint::from(200u64), - ) + .payment(TestEsdtTransfer(GOV_TOKEN_ID, 0, 200)) .whitebox(use_module::contract_obj, |sc| { sc.vote(proposal_id, VoteType::UpVote); }); @@ -330,16 +301,16 @@ fn test_change_gov_config() { world .check_account(FIRST_USER_ADDRESS) - .esdt_balance(GOV_TOKEN_ID_EXPR, BigUint::from(300u64)); + .esdt_balance(GOV_TOKEN_ID, BigUint::from(300u64)); world .check_account(SECOND_USER_ADDRESS) - .esdt_balance(GOV_TOKEN_ID_EXPR, BigUint::from(1u64)); + .esdt_balance(GOV_TOKEN_ID, BigUint::from(1u64)); world .check_account(THIRD_USER_ADDRESS) - .esdt_balance(GOV_TOKEN_ID_EXPR, BigUint::from(800u64)); + .esdt_balance(GOV_TOKEN_ID, BigUint::from(800u64)); world .check_account(OWNER_ADDRESS) - .esdt_balance(GOV_TOKEN_ID_EXPR, BigUint::from(800u64)); + .esdt_balance(GOV_TOKEN_ID, BigUint::from(800u64)); } #[test] @@ -366,11 +337,7 @@ fn test_down_veto_gov_config() { .tx() .from(FIRST_USER_ADDRESS) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(GOV_TOKEN_ID), - 0, - &BigUint::from(300u64), - ) + .payment(TestEsdtTransfer(GOV_TOKEN_ID, 0, 300)) .whitebox(use_module::contract_obj, |sc| { sc.vote(proposal_id, VoteType::UpVote); }); @@ -382,11 +349,7 @@ fn test_down_veto_gov_config() { .tx() .from(SECOND_USER_ADDRESS) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(GOV_TOKEN_ID), - 0, - &BigUint::from(200u64), - ) + .payment(TestEsdtTransfer(GOV_TOKEN_ID, 0, 200)) .whitebox(use_module::contract_obj, |sc| { sc.vote(proposal_id, VoteType::UpVote); }); @@ -395,11 +358,7 @@ fn test_down_veto_gov_config() { .tx() .from(THIRD_USER_ADDRESS) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(GOV_TOKEN_ID), - 0, - &BigUint::from(200u64), - ) + .payment(TestEsdtTransfer(GOV_TOKEN_ID, 0, 200)) .whitebox(use_module::contract_obj, |sc| { sc.vote(proposal_id, VoteType::DownVetoVote) }); @@ -419,15 +378,15 @@ fn test_down_veto_gov_config() { world .check_account(FIRST_USER_ADDRESS) - .esdt_balance(GOV_TOKEN_ID_EXPR, BigUint::from(200u64)); + .esdt_balance(GOV_TOKEN_ID, BigUint::from(200u64)); world .check_account(SECOND_USER_ADDRESS) - .esdt_balance(GOV_TOKEN_ID_EXPR, BigUint::from(800u64)); + .esdt_balance(GOV_TOKEN_ID, BigUint::from(800u64)); world .check_account(THIRD_USER_ADDRESS) - .esdt_balance(GOV_TOKEN_ID_EXPR, BigUint::from(800u64)); + .esdt_balance(GOV_TOKEN_ID, BigUint::from(800u64)); } #[test] @@ -454,11 +413,7 @@ fn test_abstain_vote_gov_config() { .tx() .from(FIRST_USER_ADDRESS) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(GOV_TOKEN_ID), - 0, - &BigUint::from(500u64), - ) + .payment(TestEsdtTransfer(GOV_TOKEN_ID, 0, 500)) .whitebox(use_module::contract_obj, |sc| { sc.vote(proposal_id, VoteType::UpVote); }); @@ -470,11 +425,7 @@ fn test_abstain_vote_gov_config() { .tx() .from(SECOND_USER_ADDRESS) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(GOV_TOKEN_ID), - 0, - &BigUint::from(400u64), - ) + .payment(TestEsdtTransfer(GOV_TOKEN_ID, 0, 400)) .whitebox(use_module::contract_obj, |sc| { sc.vote(proposal_id, VoteType::DownVote); }); @@ -483,11 +434,7 @@ fn test_abstain_vote_gov_config() { .tx() .from(THIRD_USER_ADDRESS) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(GOV_TOKEN_ID), - 0, - &BigUint::from(600u64), - ) + .payment(TestEsdtTransfer(GOV_TOKEN_ID, 0, 600)) .whitebox(use_module::contract_obj, |sc| { sc.vote(proposal_id, VoteType::AbstainVote); }); @@ -527,13 +474,13 @@ fn test_abstain_vote_gov_config() { world .check_account(FIRST_USER_ADDRESS) - .esdt_balance(GOV_TOKEN_ID_EXPR, BigUint::zero()); + .esdt_balance(GOV_TOKEN_ID, BigUint::zero()); world .check_account(SECOND_USER_ADDRESS) - .esdt_balance(GOV_TOKEN_ID_EXPR, BigUint::from(600u64)); + .esdt_balance(GOV_TOKEN_ID, BigUint::from(600u64)); world .check_account(THIRD_USER_ADDRESS) - .esdt_balance(GOV_TOKEN_ID_EXPR, BigUint::from(400u64)); + .esdt_balance(GOV_TOKEN_ID, BigUint::from(400u64)); } #[test] @@ -560,11 +507,7 @@ fn test_gov_cancel_defeated_proposal() { .tx() .from(SECOND_USER_ADDRESS) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(GOV_TOKEN_ID), - 0, - &BigUint::from(999u64), - ) + .payment(TestEsdtTransfer(GOV_TOKEN_ID, 0, 999)) .whitebox(use_module::contract_obj, |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 0f705ad131..643387b634 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,8 +1,7 @@ use multiversx_sc_modules::staking::StakingModule; use multiversx_sc_scenario::imports::*; -const STAKING_TOKEN_ID_EXPR: TestTokenIdentifier = TestTokenIdentifier::new("STAKE-123456"); -const STAKING_TOKEN_ID: &[u8] = b"STAKE-123456"; +const STAKING_TOKEN_ID: TestTokenIdentifier = TestTokenIdentifier::new("STAKE-123456"); const INITIAL_BALANCE: u64 = 2_000_000; const REQUIRED_STAKE_AMOUNT: u64 = 1_000_000; const SLASH_AMOUNT: u64 = 600_000; @@ -34,27 +33,27 @@ fn test_staking_module() { world .account(ALICE_ADDRESS) .nonce(1) - .esdt_balance(STAKING_TOKEN_ID_EXPR, INITIAL_BALANCE); + .esdt_balance(STAKING_TOKEN_ID, INITIAL_BALANCE); world .account(BOB_ADDRESS) .nonce(1) - .esdt_balance(STAKING_TOKEN_ID_EXPR, INITIAL_BALANCE); + .esdt_balance(STAKING_TOKEN_ID, INITIAL_BALANCE); world .account(CAROL_ADDRESS) .nonce(1) - .esdt_balance(STAKING_TOKEN_ID_EXPR, INITIAL_BALANCE); + .esdt_balance(STAKING_TOKEN_ID, INITIAL_BALANCE); world .account(EVE_ADDRESS) .nonce(1) - .esdt_balance(STAKING_TOKEN_ID_EXPR, INITIAL_BALANCE); + .esdt_balance(STAKING_TOKEN_ID, INITIAL_BALANCE); world .account(PAUL_ADDRESS) .nonce(1) - .esdt_balance(STAKING_TOKEN_ID_EXPR, INITIAL_BALANCE); + .esdt_balance(STAKING_TOKEN_ID, INITIAL_BALANCE); world .account(SALLY_ADDRESS) .nonce(1) - .esdt_balance(STAKING_TOKEN_ID_EXPR, INITIAL_BALANCE); + .esdt_balance(STAKING_TOKEN_ID, INITIAL_BALANCE); // init let new_address = world @@ -73,7 +72,7 @@ fn test_staking_module() { whitelist.push(SALLY_ADDRESS.to_managed_address()); sc.init_staking_module( - &EgldOrEsdtTokenIdentifier::esdt(STAKING_TOKEN_ID), + &EgldOrEsdtTokenIdentifier::esdt(STAKING_TOKEN_ID.to_token_identifier()), &BigUint::from(REQUIRED_STAKE_AMOUNT), &BigUint::from(SLASH_AMOUNT), QUORUM, @@ -88,11 +87,7 @@ fn test_staking_module() { .tx() .from(EVE_ADDRESS) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(STAKING_TOKEN_ID_EXPR), - 0, - &BigUint::from(REQUIRED_STAKE_AMOUNT), - ) + .payment(TestEsdtTransfer(STAKING_TOKEN_ID, 0, REQUIRED_STAKE_AMOUNT)) .returns(ExpectError(4u64, "Only whitelisted members can stake")) .whitebox(use_module::contract_obj, |sc| { sc.stake(); @@ -103,11 +98,11 @@ fn test_staking_module() { .tx() .from(ALICE_ADDRESS) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(STAKING_TOKEN_ID_EXPR), + .payment(TestEsdtTransfer( + STAKING_TOKEN_ID, 0, - &BigUint::from(REQUIRED_STAKE_AMOUNT / 2), - ) + REQUIRED_STAKE_AMOUNT / 2, + )) .whitebox(use_module::contract_obj, |sc| { sc.stake(); }); @@ -126,11 +121,7 @@ fn test_staking_module() { .tx() .from(BOB_ADDRESS) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(STAKING_TOKEN_ID), - 0, - &BigUint::from(REQUIRED_STAKE_AMOUNT), - ) + .payment(TestEsdtTransfer(STAKING_TOKEN_ID, 0, REQUIRED_STAKE_AMOUNT)) .whitebox(use_module::contract_obj, |sc| { sc.stake(); }); @@ -139,11 +130,7 @@ fn test_staking_module() { .tx() .from(CAROL_ADDRESS) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(STAKING_TOKEN_ID), - 0, - &BigUint::from(REQUIRED_STAKE_AMOUNT), - ) + .payment(TestEsdtTransfer(STAKING_TOKEN_ID, 0, REQUIRED_STAKE_AMOUNT)) .whitebox(use_module::contract_obj, |sc| { sc.stake(); }); @@ -152,11 +139,7 @@ fn test_staking_module() { .tx() .from(PAUL_ADDRESS) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(STAKING_TOKEN_ID), - 0, - &BigUint::from(REQUIRED_STAKE_AMOUNT), - ) + .payment(TestEsdtTransfer(STAKING_TOKEN_ID, 0, REQUIRED_STAKE_AMOUNT)) .whitebox(use_module::contract_obj, |sc| { sc.stake(); }); @@ -165,11 +148,7 @@ fn test_staking_module() { .tx() .from(SALLY_ADDRESS) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(STAKING_TOKEN_ID), - 0, - &BigUint::from(REQUIRED_STAKE_AMOUNT), - ) + .payment(TestEsdtTransfer(STAKING_TOKEN_ID, 0, REQUIRED_STAKE_AMOUNT)) .whitebox(use_module::contract_obj, |sc| { sc.stake(); }); @@ -199,11 +178,7 @@ fn test_staking_module() { .tx() .from(ALICE_ADDRESS) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(STAKING_TOKEN_ID_EXPR), - 0, - &BigUint::from(REQUIRED_STAKE_AMOUNT), - ) + .payment(TestEsdtTransfer(STAKING_TOKEN_ID, 0, REQUIRED_STAKE_AMOUNT)) .whitebox(use_module::contract_obj, |sc| { sc.stake(); let alice_staked_amount = sc.staked_amount(&ALICE_ADDRESS.to_managed_address()).get(); @@ -222,7 +197,7 @@ fn test_staking_module() { world .check_account(ALICE_ADDRESS) - .esdt_balance(STAKING_TOKEN_ID_EXPR, BigUint::from(1_000_000u64)); + .esdt_balance(STAKING_TOKEN_ID, BigUint::from(1_000_000u64)); // alice vote to slash bob @@ -386,8 +361,7 @@ fn test_staking_module() { sc.unstake(BigUint::from(400_000u64)); }); - world.check_account(ALICE_ADDRESS).esdt_balance( - TokenIdentifier::from(STAKING_TOKEN_ID_EXPR), - BigUint::from(INITIAL_BALANCE - SLASH_AMOUNT), - ); + world + .check_account(ALICE_ADDRESS) + .esdt_balance(STAKING_TOKEN_ID, INITIAL_BALANCE - SLASH_AMOUNT); } diff --git a/framework/base/src/types/interaction/expr/test_token_identifier.rs b/framework/base/src/types/interaction/expr/test_token_identifier.rs index 56d9a8bcd9..68865d8fbc 100644 --- a/framework/base/src/types/interaction/expr/test_token_identifier.rs +++ b/framework/base/src/types/interaction/expr/test_token_identifier.rs @@ -30,6 +30,14 @@ impl<'a> TestTokenIdentifier<'a> { pub fn to_token_identifier(&self) -> TokenIdentifier { self.name.into() } + + pub fn as_str(&self) -> &str { + self.name + } + + pub fn as_bytes(&self) -> &[u8] { + self.name.as_bytes() + } } impl<'a, Env> AnnotatedValue> for TestTokenIdentifier<'a> diff --git a/framework/base/src/types/interaction/tx_payment.rs b/framework/base/src/types/interaction/tx_payment.rs index c5bcc10637..bed41cc775 100644 --- a/framework/base/src/types/interaction/tx_payment.rs +++ b/framework/base/src/types/interaction/tx_payment.rs @@ -1,3 +1,4 @@ +mod test_esdt_transfer; mod tx_payment_egld; mod tx_payment_egld_or_esdt; mod tx_payment_egld_or_esdt_refs; @@ -11,6 +12,7 @@ mod tx_payment_single_esdt; mod tx_payment_single_esdt_ref; mod tx_payment_single_esdt_triple; +pub use test_esdt_transfer::TestEsdtTransfer; pub use tx_payment_egld::{Egld, EgldPayment}; pub use tx_payment_egld_value::TxEgldValue; pub use tx_payment_multi_esdt::TxPaymentMultiEsdt; diff --git a/framework/base/src/types/interaction/tx_payment/test_esdt_transfer.rs b/framework/base/src/types/interaction/tx_payment/test_esdt_transfer.rs new file mode 100644 index 0000000000..99d00a219e --- /dev/null +++ b/framework/base/src/types/interaction/tx_payment/test_esdt_transfer.rs @@ -0,0 +1,69 @@ +use crate::{ + api::ManagedTypeApi, + types::{ + BigUint, EsdtTokenPayment, FullPaymentData, FunctionCall, ManagedAddress, + TestTokenIdentifier, TxEnv, TxFrom, TxPayment, TxToSpecified, + }, +}; + +/// Syntactic sugar for quickly writing ESDT transfers in tests. +/// +/// The fields are: +/// 1. token identifier, as TestTokenIdentifier +/// 2. nonce +/// 3. amount +/// +/// The amount is represented as u64, since for most tests it is enough. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct TestEsdtTransfer<'a>(pub TestTokenIdentifier<'a>, pub u64, pub u64); + +impl<'a, Api> From> for EsdtTokenPayment +where + Api: ManagedTypeApi, +{ + fn from(value: TestEsdtTransfer<'a>) -> Self { + EsdtTokenPayment::new(value.0.to_token_identifier(), value.1, value.2.into()) + } +} + +impl<'a, Env> TxPayment for TestEsdtTransfer<'a> +where + Env: TxEnv, +{ + #[inline] + fn is_no_payment(&self, _env: &Env) -> bool { + self.2 == 0 + } + + #[inline] + fn perform_transfer_execute( + self, + env: &Env, + to: &ManagedAddress, + gas_limit: u64, + fc: FunctionCall, + ) { + EsdtTokenPayment::from(self).perform_transfer_execute(env, to, gas_limit, fc); + } + + #[inline] + fn with_normalized( + self, + env: &Env, + from: &From, + to: To, + fc: FunctionCall, + f: F, + ) -> R + where + From: TxFrom, + To: TxToSpecified, + F: FnOnce(&ManagedAddress, &BigUint, FunctionCall) -> R, + { + EsdtTokenPayment::from(self).with_normalized(env, from, to, fc, f) + } + + fn into_full_payment_data(self, env: &Env) -> FullPaymentData { + EsdtTokenPayment::from(self).into_full_payment_data(env) + } +} From dc1bcc14871fd59504a1fca5b74e7b53fd2b4b54 Mon Sep 17 00:00:00 2001 From: Andrei Vasilescu Date: Sat, 24 Aug 2024 14:22:04 +0300 Subject: [PATCH 37/92] added keystore signing interactor example + system SC func calls interactor --- Cargo.lock | 296 +++++++++++------- Cargo.toml | 2 + contracts/examples/adder/Cargo.toml | 2 +- .../examples/adder/interactor/.gitignore | 9 + .../examples/adder/interactor/Cargo.toml | 29 ++ .../examples/adder/interactor/alice.json | 23 ++ .../examples/adder/interactor/config.toml | 1 + .../src/basic_interact.rs | 19 +- .../interactor/src/basic_interact_cli.rs | 52 +++ .../interactor/src/basic_interact_config.rs | 26 ++ .../interactor/src/basic_interact_state.rs | 50 +++ .../sys-func-calls/interact/Cargo.toml | 3 +- .../interact/src/basic_interact.rs | 125 ++++++-- .../interact/src/basic_interact_cli.rs | 39 ++- 14 files changed, 514 insertions(+), 162 deletions(-) create mode 100644 contracts/examples/adder/interactor/.gitignore create mode 100644 contracts/examples/adder/interactor/Cargo.toml create mode 100644 contracts/examples/adder/interactor/alice.json create mode 100644 contracts/examples/adder/interactor/config.toml rename contracts/examples/adder/{interact => interactor}/src/basic_interact.rs (91%) create mode 100644 contracts/examples/adder/interactor/src/basic_interact_cli.rs create mode 100644 contracts/examples/adder/interactor/src/basic_interact_config.rs create mode 100644 contracts/examples/adder/interactor/src/basic_interact_state.rs diff --git a/Cargo.lock b/Cargo.lock index fecbf652fe..2c82a6092b 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -60,6 +60,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + [[package]] name = "aes" version = "0.8.4" @@ -201,7 +207,7 @@ dependencies = [ "cc", "cfg-if", "libc", - "miniz_oxide", + "miniz_oxide 0.7.4", "object", "rustc-demangle", ] @@ -258,6 +264,27 @@ dependencies = [ "toml", ] +[[package]] +name = "basic-interact-sys-calls" +version = "0.0.0" +dependencies = [ + "clap", + "multiversx-sc-snippets", + "serde", + "toml", +] + +[[package]] +name = "basic-interactor" +version = "0.0.0" +dependencies = [ + "adder", + "clap", + "multiversx-sc-snippets", + "serde", + "toml", +] + [[package]] name = "bech32" version = "0.9.1" @@ -308,12 +335,6 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90064b8dee6815a6470d60bad07bbbaee885c0e12d04177138fa3291a01b7bc4" -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - [[package]] name = "bitflags" version = "2.6.0" @@ -395,15 +416,18 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.6.1" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12916984aab3fa6e39d655a33e09c0071eb36d6ab3aea5c2d78551f1df6d952" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" [[package]] name = "cc" -version = "1.1.7" +version = "1.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26a5c3fd7bfa1ce3897a3a3501d362b2d87b7f2583ebcb4a949ec25911025cbc" +checksum = "50d2eb3cd3d1bf4529e31c215ee6f93ec5a3d536d9f578f93d9d33ee19562932" +dependencies = [ + "shlex", +] [[package]] name = "cfg-if" @@ -458,9 +482,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.11" +version = "4.5.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35723e6a11662c2afb578bcf0b88bf6ea8e21282a953428f240574fcc3a2b5b3" +checksum = "ed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019" dependencies = [ "clap_builder", "clap_derive", @@ -468,9 +492,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.11" +version = "4.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49eb96cbfa7cfa35017b7cd548c75b14c3118c98b423041d70562665e07fb0fa" +checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6" dependencies = [ "anstream", "anstyle", @@ -480,9 +504,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.11" +version = "4.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d029b67f89d30bbb547c89fd5161293c0aec155fc691d7924b64550662db93e" +checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" dependencies = [ "heck", "proc-macro2", @@ -566,15 +590,15 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" dependencies = [ "libc", ] @@ -1060,12 +1084,12 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.30" +version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +checksum = "9c0596c1eac1f9e04ed902702e9878208b336edc9d6fddc8a48387349bab3666" dependencies = [ "crc32fast", - "miniz_oxide", + "miniz_oxide 0.8.0", ] [[package]] @@ -1341,9 +1365,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" dependencies = [ "atomic-waker", "bytes", @@ -1502,9 +1526,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ab92f4f49ee4fb4f997c784b7a2e0fa70050211e0b6a287f898c3c9785ca956" +checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9" dependencies = [ "bytes", "futures-channel", @@ -1548,9 +1572,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.6" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c" dependencies = [ "equivalent", "hashbrown", @@ -1606,9 +1630,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "js-sys" -version = "0.3.69" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" dependencies = [ "wasm-bindgen", ] @@ -1709,9 +1733,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] name = "linked-list-repeat" @@ -1862,11 +1886,20 @@ dependencies = [ "adler", ] +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + [[package]] name = "mio" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ "hermit-abi", "libc", @@ -1944,7 +1977,7 @@ dependencies = [ name = "multiversx-chain-vm" version = "0.9.0" dependencies = [ - "bitflags 2.6.0", + "bitflags", "colored", "ed25519-dalek", "hex", @@ -1990,7 +2023,7 @@ dependencies = [ name = "multiversx-sc" version = "0.52.3" dependencies = [ - "bitflags 2.6.0", + "bitflags", "hex-literal", "multiversx-sc-codec", "multiversx-sc-derive", @@ -2289,9 +2322,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.2" +version = "0.36.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e" +checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9" dependencies = [ "memchr", ] @@ -2314,7 +2347,7 @@ version = "0.10.66" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" dependencies = [ - "bitflags 2.6.0", + "bitflags", "cfg-if", "foreign-types", "libc", @@ -2551,12 +2584,11 @@ checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "ppv-lite86" -version = "0.2.19" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2288c0e17cc8d342c712bb43a257a80ebffce59cdb33d5000d8348f3ec02528b" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" dependencies = [ "zerocopy", - "zerocopy-derive", ] [[package]] @@ -2779,14 +2811,14 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" dependencies = [ - "bitflags 2.6.0", + "bitflags", ] [[package]] name = "regex" -version = "1.10.5" +version = "1.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", @@ -2813,9 +2845,9 @@ checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "reqwest" -version = "0.12.5" +version = "0.12.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" +checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63" dependencies = [ "base64", "bytes", @@ -2852,7 +2884,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "winreg", + "windows-registry", ] [[package]] @@ -2961,7 +2993,7 @@ version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags 2.6.0", + "bitflags", "errno", "libc", "linux-raw-sys", @@ -2983,9 +3015,9 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "2.1.2" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" +checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" dependencies = [ "base64", "rustls-pki-types", @@ -2993,9 +3025,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" +checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" [[package]] name = "rustls-webpki" @@ -3098,7 +3130,7 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.6.0", + "bitflags", "core-foundation", "core-foundation-sys", "libc", @@ -3156,18 +3188,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.204" +version = "1.0.208" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" +checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.204" +version = "1.0.208" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" +checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf" dependencies = [ "proc-macro2", "quote", @@ -3176,9 +3208,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.121" +version = "1.0.125" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ab380d7d9f22ef3f21ad3e6c1ebe8e4fc7a2000ccba2e4d71fc96f15b2cb609" +checksum = "83c8e735a073ccf5be70aa8066aa984eaf2fa000db6c8d0100ae605b366d31ed" dependencies = [ "indexmap", "itoa", @@ -3270,6 +3302,12 @@ dependencies = [ "keccak", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "signal-hook-registry" version = "1.4.2" @@ -3383,23 +3421,26 @@ name = "sync_wrapper" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +dependencies = [ + "futures-core", +] [[package]] name = "system-configuration" -version = "0.5.1" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ - "bitflags 1.3.2", + "bitflags", "core-foundation", "system-configuration-sys", ] [[package]] name = "system-configuration-sys" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" dependencies = [ "core-foundation-sys", "libc", @@ -3407,14 +3448,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.10.1" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" dependencies = [ "cfg-if", "fastrand", + "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3479,9 +3521,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.39.2" +version = "1.39.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1" +checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5" dependencies = [ "backtrace", "bytes", @@ -3542,9 +3584,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.17" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a44eede9b727419af8095cb2d72fab15487a541f54647ad4414b34096ee4631" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" dependencies = [ "indexmap", "serde", @@ -3564,9 +3606,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.18" +version = "0.22.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1490595c74d930da779e944f5ba2ecdf538af67df1a9848cbd156af43c1b7cf0" +checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" dependencies = [ "indexmap", "serde", @@ -3592,15 +3634,15 @@ dependencies = [ [[package]] name = "tower-layer" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" @@ -3812,19 +3854,20 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" dependencies = [ "bumpalo", "log", @@ -3837,9 +3880,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.42" +version = "0.4.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" dependencies = [ "cfg-if", "js-sys", @@ -3849,9 +3892,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3859,9 +3902,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", @@ -3872,9 +3915,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "wasmparser" @@ -3883,7 +3926,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5309c1090e3e84dad0d382f42064e9933fdaedb87e468cc239f0eabea73ddcb6" dependencies = [ "ahash", - "bitflags 2.6.0", + "bitflags", "hashbrown", "indexmap", "semver", @@ -3903,9 +3946,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.69" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" dependencies = [ "js-sys", "wasm-bindgen", @@ -3913,11 +3956,41 @@ dependencies = [ [[package]] name = "winapi-util" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", +] + +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", ] [[package]] @@ -3938,6 +4011,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-targets" version = "0.48.5" @@ -4061,23 +4143,13 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.16" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b480ae9340fc261e6be3e95a1ba86d54ae3f9171132a73ce8d4bbaf68339507c" +checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" dependencies = [ "memchr", ] -[[package]] -name = "winreg" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] - [[package]] name = "zerocopy" version = "0.7.35" @@ -4121,9 +4193,9 @@ dependencies = [ [[package]] name = "zip" -version = "2.1.5" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b895748a3ebcb69b9d38dcfdf21760859a4b0d0b0015277640c2ef4c69640e6f" +checksum = "dc5e4288ea4057ae23afc69a4472434a87a2495cafce6632fd1c4ec9f5cf3494" dependencies = [ "arbitrary", "crc32fast", diff --git a/Cargo.toml b/Cargo.toml index 2f599c6e03..1ac0063c0b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ members = [ "tools/mxpy-snippet-generator", "tools/payload-macro-generator", # "tools/plotter", + "tools/interactor-system-func-calls/sys-func-calls/interact/", "vm", @@ -52,6 +53,7 @@ members = [ "contracts/examples/adder", "contracts/examples/adder/meta", "contracts/examples/adder/interact", + "contracts/examples/adder/interactor", "contracts/examples/esdt-transfer-with-fee", "contracts/examples/esdt-transfer-with-fee/meta", "contracts/examples/bonding-curve-contract", diff --git a/contracts/examples/adder/Cargo.toml b/contracts/examples/adder/Cargo.toml index 422164f2b7..ed73efa416 100644 --- a/contracts/examples/adder/Cargo.toml +++ b/contracts/examples/adder/Cargo.toml @@ -14,4 +14,4 @@ path = "../../../framework/base" [dev-dependencies.multiversx-sc-scenario] version = "0.52.3" -path = "../../../framework/scenario" +path = "../../../framework/scenario" \ No newline at end of file diff --git a/contracts/examples/adder/interactor/.gitignore b/contracts/examples/adder/interactor/.gitignore new file mode 100644 index 0000000000..b2630809de --- /dev/null +++ b/contracts/examples/adder/interactor/.gitignore @@ -0,0 +1,9 @@ +# Pem files are used for interactions, but shouldn't be committed +*.pem +!adder-owner.pem + +# Temporary storage of deployed contract address, so we can preserve the context between executions. +state.toml + +# Trace file of interactor tooling +interactor_trace.scen.json diff --git a/contracts/examples/adder/interactor/Cargo.toml b/contracts/examples/adder/interactor/Cargo.toml new file mode 100644 index 0000000000..40c6f1d6df --- /dev/null +++ b/contracts/examples/adder/interactor/Cargo.toml @@ -0,0 +1,29 @@ +[[bin]] +name = "basic-interactor" +path = "src/basic_interact.rs" + +[package] +name = "basic-interactor" +version = "0.0.0" +publish = false +edition = "2021" +authors = ["you"] + +[dependencies] +toml = "0.8.6" + +[dependencies.clap] +version = "4.4.7" +features = ["derive"] + +[dependencies.serde] +version = "1.0" +features = ["derive"] + +[dependencies.adder] +path = ".." + +[dependencies.multiversx-sc-snippets] +version = "=0.52.3" +path = "../../../../framework/snippets" + diff --git a/contracts/examples/adder/interactor/alice.json b/contracts/examples/adder/interactor/alice.json new file mode 100644 index 0000000000..8f1a81514e --- /dev/null +++ b/contracts/examples/adder/interactor/alice.json @@ -0,0 +1,23 @@ +{ + "version": 4, + "kind": "secretKey", + "id": "f2c5e236-9039-46cd-8df5-1efcd9466ead", + "address": "0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", + "bech32": "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th", + "crypto": { + "ciphertext": "45de5198c6c477725abc17d26c6b5fc88b1ff22a67a8c4784b297d426d351cf5c891a4c92d63e04cf23f602f660b7b606ed1c5293c85ff40216d9e53c9a07c23", + "cipherparams": { + "iv": "d6442fb1d4c49106152baeb3c539ed2c" + }, + "cipher": "aes-128-ctr", + "kdf": "scrypt", + "kdfparams": { + "dklen": 32, + "salt": "dd69d88742b9d27a0438a4554d4180b070d9af224ea8ff8225fdf74c8e272adb", + "n": 4096, + "r": 8, + "p": 1 + }, + "mac": "b277984f71d0e9b4a6597911775c0ee6d598002645b29f22021e595c2725d204" + } +} diff --git a/contracts/examples/adder/interactor/config.toml b/contracts/examples/adder/interactor/config.toml new file mode 100644 index 0000000000..61ac8dbf87 --- /dev/null +++ b/contracts/examples/adder/interactor/config.toml @@ -0,0 +1 @@ +gateway = 'https://devnet-gateway.multiversx.com' diff --git a/contracts/examples/adder/interact/src/basic_interact.rs b/contracts/examples/adder/interactor/src/basic_interact.rs similarity index 91% rename from contracts/examples/adder/interact/src/basic_interact.rs rename to contracts/examples/adder/interactor/src/basic_interact.rs index 262eb13631..53eb860d52 100644 --- a/contracts/examples/adder/interact/src/basic_interact.rs +++ b/contracts/examples/adder/interactor/src/basic_interact.rs @@ -51,7 +51,6 @@ async fn main() { struct AdderInteract { interactor: Interactor, adder_owner_address: Bech32Address, - wallet_address: Bech32Address, state: State, } @@ -63,24 +62,22 @@ impl AdderInteract { .with_tracer(INTERACTOR_SCENARIO_TRACE_PATH) .await; + // PASSWORD: "alice" let adder_owner_address = - interactor.register_wallet(Wallet::from_pem_file("adder-owner.pem").unwrap()); - let wallet_address = interactor.register_wallet(test_wallets::mike()); + interactor.register_wallet(Wallet::from_keystore_secret("alice.json").unwrap()); Self { interactor, adder_owner_address: adder_owner_address.into(), - wallet_address: wallet_address.into(), state: State::load_state(), } } async fn set_state(&mut self) { - println!("wallet address: {}", self.wallet_address); + println!("wallet address: {}", self.adder_owner_address); self.interactor .retrieve_account(&self.adder_owner_address) .await; - self.interactor.retrieve_account(&self.wallet_address).await; } async fn deploy(&mut self) { @@ -119,7 +116,7 @@ impl AdderInteract { let mut buffer = self.interactor.homogenous_call_buffer(); for _ in 0..count { buffer.push_tx(|tx| { - tx.from(&self.wallet_address) + tx.from(&self.adder_owner_address) .typed(adder_proxy::AdderProxy) .init(0u32) .code(ADDER_CODE_PATH) @@ -147,7 +144,7 @@ impl AdderInteract { let mut buffer = self.interactor.homogenous_call_buffer(); for _ in 0..count { buffer.push_tx(|tx| { - tx.from(&self.wallet_address) + tx.from(&self.adder_owner_address) .to(self.state.current_adder_address()) .typed(adder_proxy::AdderProxy) .add(value) @@ -163,7 +160,7 @@ impl AdderInteract { async fn feed_contract_egld(&mut self) { self.interactor .tx() - .from(&self.wallet_address) + .from(&self.adder_owner_address) .to(self.state.current_adder_address()) .egld(NumExpr("0,050000000000000000")) .prepare_async() @@ -174,7 +171,7 @@ impl AdderInteract { async fn add(&mut self, value: u32) { self.interactor .tx() - .from(&self.wallet_address) + .from(&self.adder_owner_address) .to(self.state.current_adder_address()) .gas(3_000_000) .typed(adder_proxy::AdderProxy) @@ -205,7 +202,7 @@ impl AdderInteract { let response = self .interactor .tx() - .from(&self.wallet_address) + .from(&self.adder_owner_address) .to(self.state.current_adder_address()) .gas(3_000_000) .typed(adder_proxy::AdderProxy) diff --git a/contracts/examples/adder/interactor/src/basic_interact_cli.rs b/contracts/examples/adder/interactor/src/basic_interact_cli.rs new file mode 100644 index 0000000000..6766981802 --- /dev/null +++ b/contracts/examples/adder/interactor/src/basic_interact_cli.rs @@ -0,0 +1,52 @@ +use clap::{Args, Parser, Subcommand}; + +/// Adder Interact CLI +#[derive(Default, PartialEq, Eq, Debug, Parser)] +#[command(version, about)] +#[command(propagate_version = true)] +pub struct InteractCli { + #[command(subcommand)] + pub command: Option, +} + +/// Adder Interact CLI Commands +#[derive(Clone, PartialEq, Eq, Debug, Subcommand)] +pub enum InteractCliCommand { + #[command(name = "add", about = "Add value")] + Add(AddArgs), + #[command(name = "deploy", about = "Deploy contract")] + Deploy, + #[command(name = "feed", about = "Feed contract EGLD")] + Feed, + #[command(name = "multi-deploy", about = "Multiple deploy contracts")] + MultiDeploy(MultiDeployArgs), + #[command(name = "sum", about = "Print sum")] + Sum, + #[command(name = "upgrade", about = "Upgrade contract")] + Upgrade(UpgradeArgs), +} + +#[derive(Default, Clone, PartialEq, Eq, Debug, Args)] +pub struct AddArgs { + /// The value to add + #[arg(short = 'v', long = "value")] + pub value: u32, + + /// Repeat this number of times + #[arg(short = 'c', long = "count", default_value = "1")] + pub count: usize, +} + +#[derive(Default, Clone, PartialEq, Eq, Debug, Args)] +pub struct UpgradeArgs { + /// The value to add + #[arg(short = 'v', long = "value")] + pub value: u32, +} + +#[derive(Default, Clone, PartialEq, Eq, Debug, Args)] +pub struct MultiDeployArgs { + /// The number of contracts to deploy + #[arg(short = 'c', long = "count")] + pub count: usize, +} diff --git a/contracts/examples/adder/interactor/src/basic_interact_config.rs b/contracts/examples/adder/interactor/src/basic_interact_config.rs new file mode 100644 index 0000000000..e17d0cbe65 --- /dev/null +++ b/contracts/examples/adder/interactor/src/basic_interact_config.rs @@ -0,0 +1,26 @@ +use serde::Deserialize; +use std::io::Read; + +/// Config file +const CONFIG_FILE: &str = "config.toml"; + +/// Adder Interact configuration +#[derive(Debug, Deserialize)] +pub struct Config { + gateway: String, +} + +impl Config { + // Deserializes config from file + pub fn load_config() -> Self { + let mut file = std::fs::File::open(CONFIG_FILE).unwrap(); + let mut content = String::new(); + file.read_to_string(&mut content).unwrap(); + toml::from_str(&content).unwrap() + } + + // Returns the gateway + pub fn gateway(&self) -> &str { + &self.gateway + } +} diff --git a/contracts/examples/adder/interactor/src/basic_interact_state.rs b/contracts/examples/adder/interactor/src/basic_interact_state.rs new file mode 100644 index 0000000000..41453e36fd --- /dev/null +++ b/contracts/examples/adder/interactor/src/basic_interact_state.rs @@ -0,0 +1,50 @@ +use multiversx_sc_snippets::imports::*; +use serde::{Deserialize, Serialize}; +use std::{ + io::{Read, Write}, + path::Path, +}; + +/// State file +const STATE_FILE: &str = "state.toml"; + +/// Multisig Interact state +#[derive(Debug, Default, Serialize, Deserialize)] +pub struct State { + adder_address: Option, +} + +impl State { + // Deserializes state from file + pub fn load_state() -> Self { + if Path::new(STATE_FILE).exists() { + let mut file = std::fs::File::open(STATE_FILE).unwrap(); + let mut content = String::new(); + file.read_to_string(&mut content).unwrap(); + toml::from_str(&content).unwrap() + } else { + Self::default() + } + } + + /// Sets the adder address + pub fn set_adder_address(&mut self, address: Bech32Address) { + self.adder_address = Some(address); + } + + /// Returns the adder contract + pub fn current_adder_address(&self) -> &Bech32Address { + self.adder_address + .as_ref() + .expect("no known adder contract, deploy first") + } +} + +impl Drop for State { + // Serializes state to file + fn drop(&mut self) { + let mut file = std::fs::File::create(STATE_FILE).unwrap(); + file.write_all(toml::to_string(self).unwrap().as_bytes()) + .unwrap(); + } +} diff --git a/tools/interactor-system-func-calls/sys-func-calls/interact/Cargo.toml b/tools/interactor-system-func-calls/sys-func-calls/interact/Cargo.toml index ce85dc57c1..837ff49d1c 100644 --- a/tools/interactor-system-func-calls/sys-func-calls/interact/Cargo.toml +++ b/tools/interactor-system-func-calls/sys-func-calls/interact/Cargo.toml @@ -21,4 +21,5 @@ version = "1.0" features = ["derive"] [dependencies.multiversx-sc-snippets] -version = "0.52.3" +version = "=0.52.3" +path = "../../../../framework/snippets" diff --git a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs index 83f8d297fe..ddc37f86f1 100644 --- a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs +++ b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs @@ -16,17 +16,30 @@ async fn main() { let cli = basic_interact_cli::InteractCli::parse(); match &cli.command { - Some(basic_interact_cli::InteractCliCommand::Add(args)) => {}, Some(basic_interact_cli::InteractCliCommand::IssueToken(args)) => { - basic_interact - .issue_token( - args.cost.clone(), - &args.display_name, - &args.ticker, - EsdtTokenType::from(args.token_type), - args.num_decimals, - ) - .await; + match EsdtTokenType::from(args.token_type) { + EsdtTokenType::Fungible => { + basic_interact + .issue_fungible_token( + args.cost.clone(), + &args.display_name, + &args.ticker, + args.num_decimals, + ) + .await; + }, + _ => {}, + } + }, + Some(basic_interact_cli::InteractCliCommand::Mint(args)) => { + basic_interact.mint_token(args.amount.clone()).await; + }, + Some(basic_interact_cli::InteractCliCommand::SetRoles(args)) => { + // let parsed_args = SetRolesArgs::parse(); + basic_interact.set_role(args.roles.clone()).await; + }, + Some(basic_interact_cli::InteractCliCommand::Burn(args)) => { + basic_interact.burn_token(args.amount.clone()).await; }, None => {}, @@ -38,6 +51,7 @@ struct SysFuncCallsInteract { interactor: Interactor, wallet_address: Bech32Address, state: State, + token_id: String, } impl SysFuncCallsInteract { @@ -45,26 +59,22 @@ impl SysFuncCallsInteract { let config = Config::load_config(); let mut interactor = Interactor::new(config.gateway()).await; - let wallet_address = interactor.register_wallet(test_wallets::alice()); + let wallet_address = + interactor.register_wallet(Wallet::from_pem_file("wallet.pem").unwrap()); Self { interactor, wallet_address: wallet_address.into(), state: State::load_state(), + token_id: String::new(), } } - async fn set_state(&mut self) { - println!("wallet address: {}", self.wallet_address); - self.interactor.retrieve_account(&self.wallet_address).await; - } - - async fn issue_token( + async fn issue_fungible_token( &mut self, issue_cost: RustBigUint, token_display_name: &str, token_ticker: &str, - token_type: EsdtTokenType, num_decimals: usize, ) { self.interactor @@ -73,12 +83,81 @@ impl SysFuncCallsInteract { .to(ESDTSystemSCAddress.to_managed_address()) .gas(100_000_000u64) .typed(ESDTSystemSCProxy) - .issue_and_set_all_roles( + .issue_fungible( issue_cost.into(), - token_display_name.into(), - token_ticker.into(), - token_type, - num_decimals, + &token_display_name.into(), + &token_ticker.into(), + &BigUint::from(100000000000000000000u128), + FungibleTokenProperties { + num_decimals: num_decimals, + can_freeze: true, + can_wipe: true, + can_pause: true, + can_mint: true, + can_burn: true, + can_change_owner: true, + can_upgrade: true, + can_add_special_roles: true, + }, + ) + .prepare_async() + .run() + .await; + + // self.interactor.query().to(&self.wallet_address). + } + + async fn set_role(&mut self, roles: Vec) { + let wallet_address = &self.wallet_address.clone().into_address(); + let converted_roles: Vec = + roles.into_iter().map(|r| EsdtLocalRole::from(r)).collect(); + + println!("ROLES: {:?}", converted_roles); + + self.interactor + .tx() + .from(&self.wallet_address) + .to(ESDTSystemSCAddress.to_managed_address()) + .gas(100_000_000u64) + .typed(ESDTSystemSCProxy) + .set_special_roles::>( + &ManagedAddress::from_address(wallet_address), + &TokenIdentifier::from("AND-7d5237"), + converted_roles.into_iter(), + ) + .prepare_async() + .run() + .await; + } + + async fn mint_token(&mut self, amount: RustBigUint) { + self.interactor + .tx() + .from(&self.wallet_address) + .to(&self.wallet_address) + .gas(100_000_000u64) + .typed(UserBuiltinProxy) + .esdt_local_mint( + &TokenIdentifier::from("AND-7d5237"), + 0, + &BigUint::from(amount), + ) + .prepare_async() + .run() + .await; + } + + async fn burn_token(&mut self, amount: RustBigUint) { + self.interactor + .tx() + .from(&self.wallet_address) + .to(&self.wallet_address) + .gas(100_000_000u64) + .typed(UserBuiltinProxy) + .esdt_local_burn( + &TokenIdentifier::from("AND-7d5237"), + 0, + &BigUint::from(amount), ) .prepare_async() .run() diff --git a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_cli.rs b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_cli.rs index 9c404c80e8..fe0597348d 100644 --- a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_cli.rs +++ b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_cli.rs @@ -1,5 +1,5 @@ use clap::{Args, Parser, Subcommand}; -use multiversx_sc_snippets::imports::{EsdtTokenType, RustBigUint}; +use multiversx_sc_snippets::imports::RustBigUint; /// SysFuncCalls Interact CLI #[derive(Default, PartialEq, Eq, Debug, Parser)] @@ -13,21 +13,14 @@ pub struct InteractCli { /// SysFuncCalls Interact CLI Commands #[derive(Clone, PartialEq, Eq, Debug, Subcommand)] pub enum InteractCliCommand { - #[command(name = "add", about = "Add value")] - Add(AddArgs), #[command(name = "issue-token", about = "Issue a token")] IssueToken(IssueTokenArgs), -} - -#[derive(Default, Clone, PartialEq, Eq, Debug, Args)] -pub struct AddArgs { - /// The value to add - #[arg(short = 'v', long = "value")] - pub value: u32, - - /// Repeat this number of times - #[arg(short = 'c', long = "count", default_value = "1")] - pub count: usize, + #[command(name = "mint", about = "Mints fungible tokens")] + Mint(MintArgs), + #[command(name = "set-roles", about = "Set roles")] + SetRoles(SetRolesArgs), + #[command(name = "burn", about = "Burns fungible tokens")] + Burn(BurnArgs), } #[derive(Clone, Debug, PartialEq, Eq, Args)] @@ -43,3 +36,21 @@ pub struct IssueTokenArgs { #[arg(long = "num-decimals")] pub num_decimals: usize, } + +#[derive(Clone, Debug, PartialEq, Eq, Args)] +pub struct MintArgs { + #[arg(long = "amount")] + pub amount: RustBigUint, +} + +#[derive(Clone, Debug, PartialEq, Eq, Parser)] +pub struct SetRolesArgs { + #[arg(long = "roles", value_delimiter = ',')] + pub roles: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq, Args)] +pub struct BurnArgs { + #[arg(long = "amount")] + pub amount: RustBigUint, +} From 266b717dccf2f27bb311e3b53d740ba63bc866a6 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Mon, 26 Aug 2024 08:42:54 +0300 Subject: [PATCH 38/92] test fix --- .../composability/tests/forwarder_whitebox_legacy_test.rs | 2 +- .../composability/tests/forwarder_whitebox_test.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/feature-tests/composability/tests/forwarder_whitebox_legacy_test.rs b/contracts/feature-tests/composability/tests/forwarder_whitebox_legacy_test.rs index 88e945529a..424c1508a4 100644 --- a/contracts/feature-tests/composability/tests/forwarder_whitebox_legacy_test.rs +++ b/contracts/feature-tests/composability/tests/forwarder_whitebox_legacy_test.rs @@ -63,7 +63,7 @@ fn test_nft_update_attributes_and_send() { .tx() .from(USER_ADDRESS) .to(FORWARDER_ADDRESS) - .payment(TestEsdtTransfer(NFT_TOKEN_ID, 0, 1)) + .payment(TestEsdtTransfer(NFT_TOKEN_ID, 1, 1)) .whitebox(forwarder_legacy::contract_obj, |sc| { sc.nft_update_attributes(NFT_TOKEN_ID.to_token_identifier(), 1, new_attributes); diff --git a/contracts/feature-tests/composability/tests/forwarder_whitebox_test.rs b/contracts/feature-tests/composability/tests/forwarder_whitebox_test.rs index b33b7d98a8..c6f2b54a78 100644 --- a/contracts/feature-tests/composability/tests/forwarder_whitebox_test.rs +++ b/contracts/feature-tests/composability/tests/forwarder_whitebox_test.rs @@ -62,7 +62,7 @@ fn test_nft_update_attributes_and_send() { .tx() .from(USER_ADDRESS) .to(FORWARDER_ADDRESS) - .payment(TestEsdtTransfer(NFT_TOKEN_ID, 0, 1)) + .payment(TestEsdtTransfer(NFT_TOKEN_ID, 1, 1)) .whitebox(forwarder::contract_obj, |sc| { sc.nft_update_attributes(NFT_TOKEN_ID.to_token_identifier(), 1, new_attributes); From e21a5aea170f844b2f12ea2fa4f82f2a49735721 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Mon, 26 Aug 2024 08:46:12 +0300 Subject: [PATCH 39/92] clippy fix --- contracts/examples/nft-minter/src/nft_module.rs | 2 +- .../composability/forwarder-legacy/src/fwd_esdt_legacy.rs | 3 +-- .../feature-tests/composability/forwarder/src/fwd_esdt.rs | 3 +-- .../feature-tests/composability/local-esdt-and-nft/src/lib.rs | 3 +-- .../feature-tests/erc-style-contracts/erc1155/src/erc1155.rs | 4 ++-- .../feature-tests/rust-testing-framework-tester/src/lib.rs | 2 +- framework/base/src/types/managed/wrapped/managed_vec_item.rs | 1 + 7 files changed, 8 insertions(+), 10 deletions(-) diff --git a/contracts/examples/nft-minter/src/nft_module.rs b/contracts/examples/nft-minter/src/nft_module.rs index da97c0d171..66f50ea958 100644 --- a/contracts/examples/nft-minter/src/nft_module.rs +++ b/contracts/examples/nft-minter/src/nft_module.rs @@ -123,7 +123,7 @@ pub trait NftModule { ) { match result { ManagedAsyncCallResult::Ok(token_id) => { - self.nft_token_id().set(&token_id.unwrap_esdt()); + self.nft_token_id().set(token_id.unwrap_esdt()); }, ManagedAsyncCallResult::Err(_) => { let returned = self.call_value().egld_or_single_esdt(); diff --git a/contracts/feature-tests/composability/forwarder-legacy/src/fwd_esdt_legacy.rs b/contracts/feature-tests/composability/forwarder-legacy/src/fwd_esdt_legacy.rs index b56db69bb8..6fa20793d8 100644 --- a/contracts/feature-tests/composability/forwarder-legacy/src/fwd_esdt_legacy.rs +++ b/contracts/feature-tests/composability/forwarder-legacy/src/fwd_esdt_legacy.rs @@ -128,8 +128,7 @@ pub trait ForwarderEsdtModule: fwd_storage_legacy::ForwarderStorageModule { // so we can get the token identifier and amount from the call data match result { ManagedAsyncCallResult::Ok(()) => { - self.last_issued_token() - .set(&token_identifier.unwrap_esdt()); + self.last_issued_token().set(token_identifier.unwrap_esdt()); self.last_error_message().clear(); }, ManagedAsyncCallResult::Err(message) => { diff --git a/contracts/feature-tests/composability/forwarder/src/fwd_esdt.rs b/contracts/feature-tests/composability/forwarder/src/fwd_esdt.rs index fcc3912ecc..a4dbaa28b1 100644 --- a/contracts/feature-tests/composability/forwarder/src/fwd_esdt.rs +++ b/contracts/feature-tests/composability/forwarder/src/fwd_esdt.rs @@ -132,8 +132,7 @@ pub trait ForwarderEsdtModule: fwd_storage::ForwarderStorageModule { // so we can get the token identifier and amount from the call data match result { ManagedAsyncCallResult::Ok(()) => { - self.last_issued_token() - .set(&token_identifier.unwrap_esdt()); + self.last_issued_token().set(token_identifier.unwrap_esdt()); self.last_error_message().clear(); }, ManagedAsyncCallResult::Err(message) => { diff --git a/contracts/feature-tests/composability/local-esdt-and-nft/src/lib.rs b/contracts/feature-tests/composability/local-esdt-and-nft/src/lib.rs index 55f0577795..0291d36131 100644 --- a/contracts/feature-tests/composability/local-esdt-and-nft/src/lib.rs +++ b/contracts/feature-tests/composability/local-esdt-and-nft/src/lib.rs @@ -276,8 +276,7 @@ pub trait LocalEsdtAndEsdtNft { // so we can get the token identifier and amount from the call data match result { ManagedAsyncCallResult::Ok(()) => { - self.last_issued_token() - .set(&token_identifier.unwrap_esdt()); + self.last_issued_token().set(token_identifier.unwrap_esdt()); self.last_error_message().clear(); }, ManagedAsyncCallResult::Err(message) => { diff --git a/contracts/feature-tests/erc-style-contracts/erc1155/src/erc1155.rs b/contracts/feature-tests/erc-style-contracts/erc1155/src/erc1155.rs index 725cff90de..b4d8acc941 100644 --- a/contracts/feature-tests/erc-style-contracts/erc1155/src/erc1155.rs +++ b/contracts/feature-tests/erc-style-contracts/erc1155/src/erc1155.rs @@ -160,7 +160,7 @@ pub trait Erc1155 { self.token_owner(type_id, nft_id).set(to); } else { self.token_owner(type_id, nft_id) - .set(&ManagedAddress::zero()); + .set(ManagedAddress::zero()); } } @@ -320,7 +320,7 @@ pub trait Erc1155 { let amount = BigUint::from(1u32); self.decrease_balance(owner, type_id, &amount); self.token_owner(type_id, nft_id) - .set(&ManagedAddress::zero()); + .set(ManagedAddress::zero()); } /// Range is inclusive for both `start` and `end` diff --git a/contracts/feature-tests/rust-testing-framework-tester/src/lib.rs b/contracts/feature-tests/rust-testing-framework-tester/src/lib.rs index ad3766e123..ffc411dad0 100644 --- a/contracts/feature-tests/rust-testing-framework-tester/src/lib.rs +++ b/contracts/feature-tests/rust-testing-framework-tester/src/lib.rs @@ -21,7 +21,7 @@ pub struct StructWithManagedTypes { pub trait RustTestingFrameworkTester: dummy_module::DummyModule { #[init] fn init(&self) -> ManagedBuffer { - self.total_value().set(&BigUint::from(1u32)); + self.total_value().set(BigUint::from(1u32)); b"constructor-result".into() } diff --git a/framework/base/src/types/managed/wrapped/managed_vec_item.rs b/framework/base/src/types/managed/wrapped/managed_vec_item.rs index 648635e143..9f21a13de4 100644 --- a/framework/base/src/types/managed/wrapped/managed_vec_item.rs +++ b/framework/base/src/types/managed/wrapped/managed_vec_item.rs @@ -31,6 +31,7 @@ pub trait ManagedVecItem: 'static { /// - For items with Copy semantics, it should be the type itself. /// - For managed types, ManagedRef does the job. /// - For any other types, `Self` is currently used, although this is technically unsafe. + /// /// TODO: wrap other types in readonly wrapper. type Ref<'a>: Borrow; From d0c0231030e69302cb11ba2ae467b48c0fdd8061 Mon Sep 17 00:00:00 2001 From: Andrei Vasilescu Date: Mon, 26 Aug 2024 09:56:12 +0300 Subject: [PATCH 40/92] modified original interactor --- Cargo.lock | 11 ---- Cargo.toml | 1 - .../adder/{interactor => interact}/alice.json | 0 .../src/basic_interact.rs | 19 ++++--- .../examples/adder/interactor/.gitignore | 9 ---- .../examples/adder/interactor/Cargo.toml | 29 ----------- .../examples/adder/interactor/config.toml | 1 - .../interactor/src/basic_interact_cli.rs | 52 ------------------- .../interactor/src/basic_interact_config.rs | 26 ---------- .../interactor/src/basic_interact_state.rs | 50 ------------------ 10 files changed, 12 insertions(+), 186 deletions(-) rename contracts/examples/adder/{interactor => interact}/alice.json (100%) rename contracts/examples/adder/{interactor => interact}/src/basic_interact.rs (92%) delete mode 100644 contracts/examples/adder/interactor/.gitignore delete mode 100644 contracts/examples/adder/interactor/Cargo.toml delete mode 100644 contracts/examples/adder/interactor/config.toml delete mode 100644 contracts/examples/adder/interactor/src/basic_interact_cli.rs delete mode 100644 contracts/examples/adder/interactor/src/basic_interact_config.rs delete mode 100644 contracts/examples/adder/interactor/src/basic_interact_state.rs diff --git a/Cargo.lock b/Cargo.lock index 2c82a6092b..126235e69e 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -274,17 +274,6 @@ dependencies = [ "toml", ] -[[package]] -name = "basic-interactor" -version = "0.0.0" -dependencies = [ - "adder", - "clap", - "multiversx-sc-snippets", - "serde", - "toml", -] - [[package]] name = "bech32" version = "0.9.1" diff --git a/Cargo.toml b/Cargo.toml index 1ac0063c0b..ba889c374d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,7 +53,6 @@ members = [ "contracts/examples/adder", "contracts/examples/adder/meta", "contracts/examples/adder/interact", - "contracts/examples/adder/interactor", "contracts/examples/esdt-transfer-with-fee", "contracts/examples/esdt-transfer-with-fee/meta", "contracts/examples/bonding-curve-contract", diff --git a/contracts/examples/adder/interactor/alice.json b/contracts/examples/adder/interact/alice.json similarity index 100% rename from contracts/examples/adder/interactor/alice.json rename to contracts/examples/adder/interact/alice.json diff --git a/contracts/examples/adder/interactor/src/basic_interact.rs b/contracts/examples/adder/interact/src/basic_interact.rs similarity index 92% rename from contracts/examples/adder/interactor/src/basic_interact.rs rename to contracts/examples/adder/interact/src/basic_interact.rs index 53eb860d52..2bff1fd441 100644 --- a/contracts/examples/adder/interactor/src/basic_interact.rs +++ b/contracts/examples/adder/interact/src/basic_interact.rs @@ -51,6 +51,7 @@ async fn main() { struct AdderInteract { interactor: Interactor, adder_owner_address: Bech32Address, + wallet_address: Bech32Address, state: State, } @@ -62,22 +63,26 @@ impl AdderInteract { .with_tracer(INTERACTOR_SCENARIO_TRACE_PATH) .await; - // PASSWORD: "alice" let adder_owner_address = + interactor.register_wallet(Wallet::from_pem_file("adder-owner.pem").unwrap()); + // PASSWORD: alice + let wallet_address = interactor.register_wallet(Wallet::from_keystore_secret("alice.json").unwrap()); Self { interactor, adder_owner_address: adder_owner_address.into(), + wallet_address: wallet_address.into(), state: State::load_state(), } } async fn set_state(&mut self) { - println!("wallet address: {}", self.adder_owner_address); + println!("wallet address: {}", self.wallet_address); self.interactor .retrieve_account(&self.adder_owner_address) .await; + self.interactor.retrieve_account(&self.wallet_address).await; } async fn deploy(&mut self) { @@ -116,7 +121,7 @@ impl AdderInteract { let mut buffer = self.interactor.homogenous_call_buffer(); for _ in 0..count { buffer.push_tx(|tx| { - tx.from(&self.adder_owner_address) + tx.from(&self.wallet_address) .typed(adder_proxy::AdderProxy) .init(0u32) .code(ADDER_CODE_PATH) @@ -144,7 +149,7 @@ impl AdderInteract { let mut buffer = self.interactor.homogenous_call_buffer(); for _ in 0..count { buffer.push_tx(|tx| { - tx.from(&self.adder_owner_address) + tx.from(&self.wallet_address) .to(self.state.current_adder_address()) .typed(adder_proxy::AdderProxy) .add(value) @@ -160,7 +165,7 @@ impl AdderInteract { async fn feed_contract_egld(&mut self) { self.interactor .tx() - .from(&self.adder_owner_address) + .from(&self.wallet_address) .to(self.state.current_adder_address()) .egld(NumExpr("0,050000000000000000")) .prepare_async() @@ -171,7 +176,7 @@ impl AdderInteract { async fn add(&mut self, value: u32) { self.interactor .tx() - .from(&self.adder_owner_address) + .from(&self.wallet_address) .to(self.state.current_adder_address()) .gas(3_000_000) .typed(adder_proxy::AdderProxy) @@ -202,7 +207,7 @@ impl AdderInteract { let response = self .interactor .tx() - .from(&self.adder_owner_address) + .from(&self.wallet_address) .to(self.state.current_adder_address()) .gas(3_000_000) .typed(adder_proxy::AdderProxy) diff --git a/contracts/examples/adder/interactor/.gitignore b/contracts/examples/adder/interactor/.gitignore deleted file mode 100644 index b2630809de..0000000000 --- a/contracts/examples/adder/interactor/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -# Pem files are used for interactions, but shouldn't be committed -*.pem -!adder-owner.pem - -# Temporary storage of deployed contract address, so we can preserve the context between executions. -state.toml - -# Trace file of interactor tooling -interactor_trace.scen.json diff --git a/contracts/examples/adder/interactor/Cargo.toml b/contracts/examples/adder/interactor/Cargo.toml deleted file mode 100644 index 40c6f1d6df..0000000000 --- a/contracts/examples/adder/interactor/Cargo.toml +++ /dev/null @@ -1,29 +0,0 @@ -[[bin]] -name = "basic-interactor" -path = "src/basic_interact.rs" - -[package] -name = "basic-interactor" -version = "0.0.0" -publish = false -edition = "2021" -authors = ["you"] - -[dependencies] -toml = "0.8.6" - -[dependencies.clap] -version = "4.4.7" -features = ["derive"] - -[dependencies.serde] -version = "1.0" -features = ["derive"] - -[dependencies.adder] -path = ".." - -[dependencies.multiversx-sc-snippets] -version = "=0.52.3" -path = "../../../../framework/snippets" - diff --git a/contracts/examples/adder/interactor/config.toml b/contracts/examples/adder/interactor/config.toml deleted file mode 100644 index 61ac8dbf87..0000000000 --- a/contracts/examples/adder/interactor/config.toml +++ /dev/null @@ -1 +0,0 @@ -gateway = 'https://devnet-gateway.multiversx.com' diff --git a/contracts/examples/adder/interactor/src/basic_interact_cli.rs b/contracts/examples/adder/interactor/src/basic_interact_cli.rs deleted file mode 100644 index 6766981802..0000000000 --- a/contracts/examples/adder/interactor/src/basic_interact_cli.rs +++ /dev/null @@ -1,52 +0,0 @@ -use clap::{Args, Parser, Subcommand}; - -/// Adder Interact CLI -#[derive(Default, PartialEq, Eq, Debug, Parser)] -#[command(version, about)] -#[command(propagate_version = true)] -pub struct InteractCli { - #[command(subcommand)] - pub command: Option, -} - -/// Adder Interact CLI Commands -#[derive(Clone, PartialEq, Eq, Debug, Subcommand)] -pub enum InteractCliCommand { - #[command(name = "add", about = "Add value")] - Add(AddArgs), - #[command(name = "deploy", about = "Deploy contract")] - Deploy, - #[command(name = "feed", about = "Feed contract EGLD")] - Feed, - #[command(name = "multi-deploy", about = "Multiple deploy contracts")] - MultiDeploy(MultiDeployArgs), - #[command(name = "sum", about = "Print sum")] - Sum, - #[command(name = "upgrade", about = "Upgrade contract")] - Upgrade(UpgradeArgs), -} - -#[derive(Default, Clone, PartialEq, Eq, Debug, Args)] -pub struct AddArgs { - /// The value to add - #[arg(short = 'v', long = "value")] - pub value: u32, - - /// Repeat this number of times - #[arg(short = 'c', long = "count", default_value = "1")] - pub count: usize, -} - -#[derive(Default, Clone, PartialEq, Eq, Debug, Args)] -pub struct UpgradeArgs { - /// The value to add - #[arg(short = 'v', long = "value")] - pub value: u32, -} - -#[derive(Default, Clone, PartialEq, Eq, Debug, Args)] -pub struct MultiDeployArgs { - /// The number of contracts to deploy - #[arg(short = 'c', long = "count")] - pub count: usize, -} diff --git a/contracts/examples/adder/interactor/src/basic_interact_config.rs b/contracts/examples/adder/interactor/src/basic_interact_config.rs deleted file mode 100644 index e17d0cbe65..0000000000 --- a/contracts/examples/adder/interactor/src/basic_interact_config.rs +++ /dev/null @@ -1,26 +0,0 @@ -use serde::Deserialize; -use std::io::Read; - -/// Config file -const CONFIG_FILE: &str = "config.toml"; - -/// Adder Interact configuration -#[derive(Debug, Deserialize)] -pub struct Config { - gateway: String, -} - -impl Config { - // Deserializes config from file - pub fn load_config() -> Self { - let mut file = std::fs::File::open(CONFIG_FILE).unwrap(); - let mut content = String::new(); - file.read_to_string(&mut content).unwrap(); - toml::from_str(&content).unwrap() - } - - // Returns the gateway - pub fn gateway(&self) -> &str { - &self.gateway - } -} diff --git a/contracts/examples/adder/interactor/src/basic_interact_state.rs b/contracts/examples/adder/interactor/src/basic_interact_state.rs deleted file mode 100644 index 41453e36fd..0000000000 --- a/contracts/examples/adder/interactor/src/basic_interact_state.rs +++ /dev/null @@ -1,50 +0,0 @@ -use multiversx_sc_snippets::imports::*; -use serde::{Deserialize, Serialize}; -use std::{ - io::{Read, Write}, - path::Path, -}; - -/// State file -const STATE_FILE: &str = "state.toml"; - -/// Multisig Interact state -#[derive(Debug, Default, Serialize, Deserialize)] -pub struct State { - adder_address: Option, -} - -impl State { - // Deserializes state from file - pub fn load_state() -> Self { - if Path::new(STATE_FILE).exists() { - let mut file = std::fs::File::open(STATE_FILE).unwrap(); - let mut content = String::new(); - file.read_to_string(&mut content).unwrap(); - toml::from_str(&content).unwrap() - } else { - Self::default() - } - } - - /// Sets the adder address - pub fn set_adder_address(&mut self, address: Bech32Address) { - self.adder_address = Some(address); - } - - /// Returns the adder contract - pub fn current_adder_address(&self) -> &Bech32Address { - self.adder_address - .as_ref() - .expect("no known adder contract, deploy first") - } -} - -impl Drop for State { - // Serializes state to file - fn drop(&mut self) { - let mut file = std::fs::File::create(STATE_FILE).unwrap(); - file.write_all(toml::to_string(self).unwrap().as_bytes()) - .unwrap(); - } -} From 30c251a83b376023d6501d1eb5c9997130eb3a5b Mon Sep 17 00:00:00 2001 From: Andrei Vasilescu Date: Mon, 26 Aug 2024 10:00:16 +0300 Subject: [PATCH 41/92] small refactor in from_keystore_secret function --- .../examples/adder/interact/src/basic_interact.rs | 6 +++--- sdk/core/src/wallet.rs | 11 +++++------ 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/contracts/examples/adder/interact/src/basic_interact.rs b/contracts/examples/adder/interact/src/basic_interact.rs index 2bff1fd441..4765ec6fbe 100644 --- a/contracts/examples/adder/interact/src/basic_interact.rs +++ b/contracts/examples/adder/interact/src/basic_interact.rs @@ -65,9 +65,9 @@ impl AdderInteract { let adder_owner_address = interactor.register_wallet(Wallet::from_pem_file("adder-owner.pem").unwrap()); - // PASSWORD: alice - let wallet_address = - interactor.register_wallet(Wallet::from_keystore_secret("alice.json").unwrap()); + // PASSWORD: "alice" + let wallet_address = interactor + .register_wallet(Wallet::from_keystore_secret("alice.json", "alice").unwrap()); Self { interactor, diff --git a/sdk/core/src/wallet.rs b/sdk/core/src/wallet.rs index bf1362a314..e197c13c02 100644 --- a/sdk/core/src/wallet.rs +++ b/sdk/core/src/wallet.rs @@ -156,12 +156,11 @@ impl Wallet { (private_key_str, public_key_str) } - pub fn from_keystore_secret(file_path: &str) -> Result { - let decyption_params = - Self::validate_keystore_password(file_path, Self::get_keystore_password()) - .unwrap_or_else(|e| { - panic!("Error: {:?}", e); - }); + pub fn from_keystore_secret(file_path: &str, password: &str) -> Result { + let decyption_params = Self::validate_keystore_password(file_path, password.to_string()) + .unwrap_or_else(|e| { + panic!("Error: {:?}", e); + }); let priv_key = PrivateKey::from_hex_str( hex::encode(Self::decrypt_secret_key(decyption_params)).as_str(), )?; From d0b70560592e5f34318710ada96e262702bb7a0c Mon Sep 17 00:00:00 2001 From: Andrei Vasilescu Date: Mon, 26 Aug 2024 12:05:07 +0300 Subject: [PATCH 42/92] added token ticker saving in interactor storage --- .../interact/src/basic_interact.rs | 61 +++++++++++++------ .../interact/src/basic_interact_state.rs | 12 ---- 2 files changed, 43 insertions(+), 30 deletions(-) diff --git a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs index ddc37f86f1..798d74159f 100644 --- a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs +++ b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs @@ -17,19 +17,15 @@ async fn main() { let cli = basic_interact_cli::InteractCli::parse(); match &cli.command { Some(basic_interact_cli::InteractCliCommand::IssueToken(args)) => { - match EsdtTokenType::from(args.token_type) { - EsdtTokenType::Fungible => { - basic_interact - .issue_fungible_token( - args.cost.clone(), - &args.display_name, - &args.ticker, - args.num_decimals, - ) - .await; - }, - _ => {}, - } + basic_interact + .issue_token( + args.cost.clone(), + &args.display_name, + &args.ticker, + args.num_decimals, + args.token_type.into(), + ) + .await; }, Some(basic_interact_cli::InteractCliCommand::Mint(args)) => { basic_interact.mint_token(args.amount.clone()).await; @@ -70,7 +66,7 @@ impl SysFuncCallsInteract { } } - async fn issue_fungible_token( + async fn _issue_fungible_token( &mut self, issue_cost: RustBigUint, token_display_name: &str, @@ -103,8 +99,37 @@ impl SysFuncCallsInteract { .prepare_async() .run() .await; + } + + async fn issue_token( + &mut self, + issue_cost: RustBigUint, + token_display_name: &str, + token_ticker: &str, + num_decimals: usize, + token_type: EsdtTokenType, + ) { + let token_id = self + .interactor + .tx() + .from(&self.wallet_address) + .to(ESDTSystemSCAddress.to_managed_address()) + .gas(100_000_000u64) + .typed(ESDTSystemSCProxy) + .issue_and_set_all_roles( + issue_cost.into(), + token_display_name.into(), + token_ticker.into(), + token_type, + num_decimals, + ) + .returns(ReturnsResultUnmanaged) + .prepare_async() + .run() + .await; - // self.interactor.query().to(&self.wallet_address). + println!("TOKEN ID: {:?}", token_id.to_string()); + self.token_id = token_id.to_string(); } async fn set_role(&mut self, roles: Vec) { @@ -122,7 +147,7 @@ impl SysFuncCallsInteract { .typed(ESDTSystemSCProxy) .set_special_roles::>( &ManagedAddress::from_address(wallet_address), - &TokenIdentifier::from("AND-7d5237"), + &TokenIdentifier::from(&self.token_id), converted_roles.into_iter(), ) .prepare_async() @@ -138,7 +163,7 @@ impl SysFuncCallsInteract { .gas(100_000_000u64) .typed(UserBuiltinProxy) .esdt_local_mint( - &TokenIdentifier::from("AND-7d5237"), + &TokenIdentifier::from(&self.token_id), 0, &BigUint::from(amount), ) @@ -155,7 +180,7 @@ impl SysFuncCallsInteract { .gas(100_000_000u64) .typed(UserBuiltinProxy) .esdt_local_burn( - &TokenIdentifier::from("AND-7d5237"), + &TokenIdentifier::from(&self.token_id), 0, &BigUint::from(amount), ) diff --git a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_state.rs b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_state.rs index 41453e36fd..459b6f0bf5 100644 --- a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_state.rs +++ b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_state.rs @@ -26,18 +26,6 @@ impl State { Self::default() } } - - /// Sets the adder address - pub fn set_adder_address(&mut self, address: Bech32Address) { - self.adder_address = Some(address); - } - - /// Returns the adder contract - pub fn current_adder_address(&self) -> &Bech32Address { - self.adder_address - .as_ref() - .expect("no known adder contract, deploy first") - } } impl Drop for State { From 112120f1dbc39b182ecbcff268df80ef571a4746 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Mon, 26 Aug 2024 14:48:02 +0300 Subject: [PATCH 43/92] ed25519-dalek reverted downgrade --- Cargo.lock | 520 +++++++++++++++++++------------------ vm/Cargo.toml | 2 +- vm/src/crypto_functions.rs | 27 +- 3 files changed, 281 insertions(+), 268 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fecbf652fe..afd520f5eb 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -60,6 +60,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + [[package]] name = "aes" version = "0.8.4" @@ -201,7 +207,7 @@ dependencies = [ "cc", "cfg-if", "libc", - "miniz_oxide", + "miniz_oxide 0.7.4", "object", "rustc-demangle", ] @@ -296,8 +302,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93f2635620bf0b9d4576eb7bb9a38a55df78bd1205d26fa994b25911a69f212f" dependencies = [ "bitcoin_hashes", - "rand 0.8.5", - "rand_core 0.6.4", + "rand", + "rand_core", "serde", "unicode-normalization", ] @@ -308,27 +314,12 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90064b8dee6815a6470d60bad07bbbaee885c0e12d04177138fa3291a01b7bc4" -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - [[package]] name = "bitflags" version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "generic-array", -] - [[package]] name = "block-buffer" version = "0.10.4" @@ -395,15 +386,18 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.6.1" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12916984aab3fa6e39d655a33e09c0071eb36d6ab3aea5c2d78551f1df6d952" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" [[package]] name = "cc" -version = "1.1.7" +version = "1.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26a5c3fd7bfa1ce3897a3a3501d362b2d87b7f2583ebcb4a949ec25911025cbc" +checksum = "50d2eb3cd3d1bf4529e31c215ee6f93ec5a3d536d9f578f93d9d33ee19562932" +dependencies = [ + "shlex", +] [[package]] name = "cfg-if" @@ -458,9 +452,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.11" +version = "4.5.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35723e6a11662c2afb578bcf0b88bf6ea8e21282a953428f240574fcc3a2b5b3" +checksum = "ed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019" dependencies = [ "clap_builder", "clap_derive", @@ -468,9 +462,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.11" +version = "4.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49eb96cbfa7cfa35017b7cd548c75b14c3118c98b423041d70562665e07fb0fa" +checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6" dependencies = [ "anstream", "anstyle", @@ -480,9 +474,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.11" +version = "4.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d029b67f89d30bbb547c89fd5161293c0aec155fc691d7924b64550662db93e" +checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" dependencies = [ "heck", "proc-macro2", @@ -536,6 +530,12 @@ dependencies = [ "vault", ] +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + [[package]] name = "convert_case" version = "0.6.0" @@ -566,15 +566,15 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" dependencies = [ "libc", ] @@ -702,22 +702,25 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "3.2.0" +version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ - "byteorder", - "digest 0.9.0", - "rand_core 0.5.1", + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest", + "fiat-crypto", + "rustc_version", "subtle", "zeroize", ] [[package]] -name = "derive_arbitrary" -version = "1.3.2" +name = "curve25519-dalek-derive" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", @@ -725,12 +728,24 @@ dependencies = [ ] [[package]] -name = "digest" -version = "0.9.0" +name = "der" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ - "generic-array", + "const-oid", + "zeroize", +] + +[[package]] +name = "derive_arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -739,7 +754,7 @@ version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer 0.10.4", + "block-buffer", "crypto-common", "subtle", ] @@ -773,24 +788,25 @@ dependencies = [ [[package]] name = "ed25519" -version = "1.5.3" +version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" dependencies = [ + "pkcs8", "signature", ] [[package]] name = "ed25519-dalek" -version = "1.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" dependencies = [ "curve25519-dalek", "ed25519", - "rand 0.7.3", "serde", - "sha2 0.9.9", + "sha2", + "subtle", "zeroize", ] @@ -1037,9 +1053,15 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" + +[[package]] +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "first-contract" @@ -1060,12 +1082,12 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.30" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" dependencies = [ "crc32fast", - "miniz_oxide", + "miniz_oxide 0.8.0", ] [[package]] @@ -1296,17 +1318,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - [[package]] name = "getrandom" version = "0.2.15" @@ -1316,7 +1327,7 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", "wasm-bindgen", ] @@ -1341,9 +1352,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" dependencies = [ "atomic-waker", "bytes", @@ -1398,7 +1409,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.7", + "digest", ] [[package]] @@ -1502,9 +1513,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ab92f4f49ee4fb4f997c784b7a2e0fa70050211e0b6a287f898c3c9785ca956" +checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9" dependencies = [ "bytes", "futures-channel", @@ -1548,9 +1559,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.6" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c" dependencies = [ "equivalent", "hashbrown", @@ -1606,9 +1617,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "js-sys" -version = "0.3.69" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" dependencies = [ "wasm-bindgen", ] @@ -1709,9 +1720,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] name = "linked-list-repeat" @@ -1862,15 +1873,24 @@ dependencies = [ "adler", ] +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + [[package]] name = "mio" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ "hermit-abi", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", "windows-sys 0.52.0", ] @@ -1944,7 +1964,7 @@ dependencies = [ name = "multiversx-chain-vm" version = "0.9.0" dependencies = [ - "bitflags 2.6.0", + "bitflags", "colored", "ed25519-dalek", "hex", @@ -1953,9 +1973,9 @@ dependencies = [ "multiversx-chain-vm-executor", "num-bigint", "num-traits", - "rand 0.8.5", + "rand", "rand_seeder", - "sha2 0.10.8", + "sha2", "sha3", ] @@ -1970,11 +1990,11 @@ name = "multiversx-price-aggregator-sc" version = "0.52.3" dependencies = [ "arrayvec", - "getrandom 0.2.15", + "getrandom", "multiversx-sc", "multiversx-sc-modules", "multiversx-sc-scenario", - "rand 0.8.5", + "rand", ] [[package]] @@ -1990,7 +2010,7 @@ dependencies = [ name = "multiversx-sc" version = "0.52.3" dependencies = [ - "bitflags 2.6.0", + "bitflags", "hex-literal", "multiversx-sc-codec", "multiversx-sc-derive", @@ -2099,7 +2119,7 @@ dependencies = [ "pathdiff", "serde", "serde_json", - "sha2 0.10.8", + "sha2", "unwrap-infallible", ] @@ -2142,13 +2162,13 @@ dependencies = [ "log", "pbkdf2", "pem", - "rand 0.8.5", + "rand", "reqwest", "scrypt", "serde", "serde_json", "serde_repr", - "sha2 0.10.8", + "sha2", "sha3", "tokio", "uuid", @@ -2289,9 +2309,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.2" +version = "0.36.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e" +checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9" dependencies = [ "memchr", ] @@ -2302,19 +2322,13 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" -[[package]] -name = "opaque-debug" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" - [[package]] name = "openssl" version = "0.10.66" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" dependencies = [ - "bitflags 2.6.0", + "bitflags", "cfg-if", "foreign-types", "libc", @@ -2439,7 +2453,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" dependencies = [ "base64ct", - "rand_core 0.6.4", + "rand_core", "subtle", ] @@ -2475,7 +2489,7 @@ version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" dependencies = [ - "digest 0.10.7", + "digest", "hmac", ] @@ -2543,6 +2557,16 @@ dependencies = [ "ping-pong-egld", ] +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + [[package]] name = "pkg-config" version = "0.3.30" @@ -2551,12 +2575,11 @@ checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "ppv-lite86" -version = "0.2.19" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2288c0e17cc8d342c712bb43a257a80ebffce59cdb33d5000d8348f3ec02528b" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" dependencies = [ "zerocopy", - "zerocopy-derive", ] [[package]] @@ -2669,19 +2692,6 @@ dependencies = [ "nibble_vec", ] -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc", -] - [[package]] name = "rand" version = "0.8.5" @@ -2689,18 +2699,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", + "rand_chacha", + "rand_core", ] [[package]] @@ -2710,16 +2710,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", + "rand_core", ] [[package]] @@ -2728,16 +2719,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.15", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", + "getrandom", ] [[package]] @@ -2746,7 +2728,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf2890aaef0aa82719a50e808de264f9484b74b442e1a3a0e5ee38243ac40bdb" dependencies = [ - "rand_core 0.6.4", + "rand_core", ] [[package]] @@ -2779,14 +2761,14 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" dependencies = [ - "bitflags 2.6.0", + "bitflags", ] [[package]] name = "regex" -version = "1.10.5" +version = "1.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", @@ -2813,9 +2795,9 @@ checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "reqwest" -version = "0.12.5" +version = "0.12.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" +checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63" dependencies = [ "base64", "bytes", @@ -2852,7 +2834,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "winreg", + "windows-registry", ] [[package]] @@ -2880,7 +2862,7 @@ checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.15", + "getrandom", "libc", "spin", "untrusted", @@ -2961,7 +2943,7 @@ version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags 2.6.0", + "bitflags", "errno", "libc", "linux-raw-sys", @@ -2983,9 +2965,9 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "2.1.2" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" +checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" dependencies = [ "base64", "rustls-pki-types", @@ -2993,9 +2975,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" +checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" [[package]] name = "rustls-webpki" @@ -3072,7 +3054,7 @@ dependencies = [ "password-hash", "pbkdf2", "salsa20", - "sha2 0.10.8", + "sha2", ] [[package]] @@ -3098,7 +3080,7 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.6.0", + "bitflags", "core-foundation", "core-foundation-sys", "libc", @@ -3156,18 +3138,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.204" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" +checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.204" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" +checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" dependencies = [ "proc-macro2", "quote", @@ -3176,9 +3158,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.121" +version = "1.0.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ab380d7d9f22ef3f21ad3e6c1ebe8e4fc7a2000ccba2e4d71fc96f15b2cb609" +checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad" dependencies = [ "indexmap", "itoa", @@ -3236,19 +3218,6 @@ dependencies = [ "set-repeat", ] -[[package]] -name = "sha2" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", -] - [[package]] name = "sha2" version = "0.10.8" @@ -3257,7 +3226,7 @@ checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.7", + "digest", ] [[package]] @@ -3266,10 +3235,16 @@ version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" dependencies = [ - "digest 0.10.7", + "digest", "keccak", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "signal-hook-registry" version = "1.4.2" @@ -3281,9 +3256,12 @@ dependencies = [ [[package]] name = "signature" -version = "1.6.4" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "rand_core", +] [[package]] name = "simd-adler32" @@ -3339,6 +3317,16 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + [[package]] name = "str-repeat" version = "0.0.0" @@ -3383,23 +3371,26 @@ name = "sync_wrapper" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +dependencies = [ + "futures-core", +] [[package]] name = "system-configuration" -version = "0.5.1" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ - "bitflags 1.3.2", + "bitflags", "core-foundation", "system-configuration-sys", ] [[package]] name = "system-configuration-sys" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" dependencies = [ "core-foundation-sys", "libc", @@ -3407,14 +3398,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.10.1" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" dependencies = [ "cfg-if", "fastrand", + "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3479,9 +3471,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.39.2" +version = "1.39.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1" +checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5" dependencies = [ "backtrace", "bytes", @@ -3542,9 +3534,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.17" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a44eede9b727419af8095cb2d72fab15487a541f54647ad4414b34096ee4631" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" dependencies = [ "indexmap", "serde", @@ -3564,9 +3556,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.18" +version = "0.22.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1490595c74d930da779e944f5ba2ecdf538af67df1a9848cbd156af43c1b7cf0" +checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" dependencies = [ "indexmap", "serde", @@ -3592,15 +3584,15 @@ dependencies = [ [[package]] name = "tower-layer" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" @@ -3731,7 +3723,7 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" dependencies = [ - "getrandom 0.2.15", + "getrandom", ] [[package]] @@ -3798,12 +3790,6 @@ dependencies = [ "try-lock", ] -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -3812,19 +3798,20 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" dependencies = [ "bumpalo", "log", @@ -3837,9 +3824,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.42" +version = "0.4.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" dependencies = [ "cfg-if", "js-sys", @@ -3849,9 +3836,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3859,9 +3846,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", @@ -3872,9 +3859,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "wasmparser" @@ -3883,7 +3870,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5309c1090e3e84dad0d382f42064e9933fdaedb87e468cc239f0eabea73ddcb6" dependencies = [ "ahash", - "bitflags 2.6.0", + "bitflags", "hashbrown", "indexmap", "semver", @@ -3903,9 +3890,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.69" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" dependencies = [ "js-sys", "wasm-bindgen", @@ -3913,11 +3900,41 @@ dependencies = [ [[package]] name = "winapi-util" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", +] + +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", ] [[package]] @@ -3938,6 +3955,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-targets" version = "0.48.5" @@ -4061,23 +4087,13 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.16" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b480ae9340fc261e6be3e95a1ba86d54ae3f9171132a73ce8d4bbaf68339507c" +checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" dependencies = [ "memchr", ] -[[package]] -name = "winreg" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] - [[package]] name = "zerocopy" version = "0.7.35" @@ -4104,26 +4120,12 @@ name = "zeroize" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] [[package]] name = "zip" -version = "2.1.5" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b895748a3ebcb69b9d38dcfdf21760859a4b0d0b0015277640c2ef4c69640e6f" +checksum = "dc5e4288ea4057ae23afc69a4472434a87a2495cafce6632fd1c4ec9f5cf3494" dependencies = [ "arbitrary", "crc32fast", diff --git a/vm/Cargo.toml b/vm/Cargo.toml index baf8ec3894..31bb9afcdf 100644 --- a/vm/Cargo.toml +++ b/vm/Cargo.toml @@ -32,7 +32,7 @@ bitflags = "=2.6.0" colored = "2.1.0" rand = { version= "0.8.5", optional = true } rand_seeder = { version= "0.2.2", optional = true } -ed25519-dalek = { version = "1.0.1" , optional = true } +ed25519-dalek = { version = "2.1.0" , optional = true } [dependencies.multiversx-chain-vm-executor] version = "0.2.0" diff --git a/vm/src/crypto_functions.rs b/vm/src/crypto_functions.rs index 9d61e9ccc9..fed81f654a 100644 --- a/vm/src/crypto_functions.rs +++ b/vm/src/crypto_functions.rs @@ -18,19 +18,30 @@ pub fn keccak256(data: &[u8]) -> [u8; KECCAK256_RESULT_LEN] { #[cfg(feature = "wasm-incopatible")] pub fn verify_ed25519(key: &[u8], message: &[u8], signature: &[u8]) -> bool { - use ed25519_dalek::*; + use ed25519_dalek::{Signature, VerifyingKey, Verifier}; - let public = PublicKey::from_bytes(key); - if public.is_err() { + let key_32: [u8; 32] = if let Ok(key_32) = key.try_into() { + key_32 + } else { return false; - } + }; + let signature_64: [u8; 64] = if let Ok(signature_64) = signature.try_into() { + signature_64 + } else { + return false; + }; - let sig = Signature::from_bytes(signature); - if sig.is_err() { + let verifying_key_result = VerifyingKey::from_bytes(&key_32); + let verifying_key = if let Ok(verifying_key) = verifying_key_result { + verifying_key + } else { return false; - } + }; + + let sig = Signature::from_bytes(&signature_64); - public.unwrap().verify(message, &sig.unwrap()).is_ok() + let result = verifying_key.verify(message, &sig); + result.is_ok() } #[cfg(not(feature = "wasm-incopatible"))] From 2a1327911f10710f6c9ed22a3a44e5e0ef67af03 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Mon, 26 Aug 2024 14:49:07 +0300 Subject: [PATCH 44/92] wasm-incompatible feature typo --- framework/scenario/Cargo.toml | 4 ++-- vm/Cargo.toml | 2 +- vm/src/crypto_functions.rs | 6 +++--- vm/src/tx_mock.rs | 8 ++++---- vm/src/tx_mock/blockchain_rng_unsupported.rs | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/framework/scenario/Cargo.toml b/framework/scenario/Cargo.toml index 9cf7f2a553..0e13cb71dd 100644 --- a/framework/scenario/Cargo.toml +++ b/framework/scenario/Cargo.toml @@ -32,8 +32,8 @@ colored = "2.0" unwrap-infallible = "0.1.5" [features] -default = ["wasm-incopatible"] -wasm-incopatible = ["multiversx-chain-vm/wasm-incopatible"] +default = ["wasm-incompatible"] +wasm-incompatible = ["multiversx-chain-vm/wasm-incompatible"] run-go-tests = [] [dependencies.multiversx-sc] diff --git a/vm/Cargo.toml b/vm/Cargo.toml index 31bb9afcdf..568c7e512c 100644 --- a/vm/Cargo.toml +++ b/vm/Cargo.toml @@ -18,7 +18,7 @@ categories = ["cryptography::cryptocurrencies", "development-tools::debugging"] [features] # not supported when compiling to wasm -wasm-incopatible = ["rand", "rand_seeder", "ed25519-dalek"] +wasm-incompatible = ["rand", "rand_seeder", "ed25519-dalek"] [dependencies] num-bigint = "0.4" diff --git a/vm/src/crypto_functions.rs b/vm/src/crypto_functions.rs index fed81f654a..a1277ceac5 100644 --- a/vm/src/crypto_functions.rs +++ b/vm/src/crypto_functions.rs @@ -16,7 +16,7 @@ pub fn keccak256(data: &[u8]) -> [u8; KECCAK256_RESULT_LEN] { hasher.finalize().into() } -#[cfg(feature = "wasm-incopatible")] +#[cfg(feature = "wasm-incompatible")] pub fn verify_ed25519(key: &[u8], message: &[u8], signature: &[u8]) -> bool { use ed25519_dalek::{Signature, VerifyingKey, Verifier}; @@ -44,7 +44,7 @@ pub fn verify_ed25519(key: &[u8], message: &[u8], signature: &[u8]) -> bool { result.is_ok() } -#[cfg(not(feature = "wasm-incopatible"))] +#[cfg(not(feature = "wasm-incompatible"))] pub fn verify_ed25519(_key: &[u8], _message: &[u8], _signature: &[u8]) -> bool { - panic!("verify_ed25519 not supported for wasm builds, feature `wasm-incopatible` needs to be enabled") + panic!("verify_ed25519 not supported for wasm builds, feature `wasm-incompatible` needs to be enabled") } diff --git a/vm/src/tx_mock.rs b/vm/src/tx_mock.rs index bd508d569e..ce63ddfe7a 100644 --- a/vm/src/tx_mock.rs +++ b/vm/src/tx_mock.rs @@ -37,12 +37,12 @@ pub use tx_panic::*; pub use tx_result::*; pub use tx_result_calls::*; -#[cfg(feature = "wasm-incopatible")] +#[cfg(feature = "wasm-incompatible")] mod blockchain_rng; -#[cfg(feature = "wasm-incopatible")] +#[cfg(feature = "wasm-incompatible")] pub use blockchain_rng::BlockchainRng; -#[cfg(not(feature = "wasm-incopatible"))] +#[cfg(not(feature = "wasm-incompatible"))] mod blockchain_rng_unsupported; -#[cfg(not(feature = "wasm-incopatible"))] +#[cfg(not(feature = "wasm-incompatible"))] pub use blockchain_rng_unsupported::BlockchainRng; diff --git a/vm/src/tx_mock/blockchain_rng_unsupported.rs b/vm/src/tx_mock/blockchain_rng_unsupported.rs index 698be4ac11..6339cbaffc 100644 --- a/vm/src/tx_mock/blockchain_rng_unsupported.rs +++ b/vm/src/tx_mock/blockchain_rng_unsupported.rs @@ -9,6 +9,6 @@ impl BlockchainRng { } pub fn next_bytes(&mut self, _length: usize) -> Vec { - panic!("BlockchainRng not supported for wasm builds, feature `wasm-incopatible` needs to be enabled") + panic!("BlockchainRng not supported for wasm builds, feature `wasm-incompatible` needs to be enabled") } } From 12d3da51879b2cdf88aeea15e1ffc906c94d633c Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Mon, 26 Aug 2024 14:53:54 +0300 Subject: [PATCH 45/92] dependency upgrade --- Cargo.lock | 24 ++++++++++++------------ data/codec-derive/Cargo.toml | 4 ++-- data/codec/Cargo.toml | 2 +- framework/derive/Cargo.toml | 4 ++-- framework/meta-lib/Cargo.toml | 4 ++-- vm/Cargo.toml | 2 +- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index afd520f5eb..b7fe71048c 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -181,9 +181,9 @@ dependencies = [ [[package]] name = "arrayvec" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "atomic-waker" @@ -2675,9 +2675,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -2724,9 +2724,9 @@ dependencies = [ [[package]] name = "rand_seeder" -version = "0.2.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf2890aaef0aa82719a50e808de264f9484b74b442e1a3a0e5ee38243ac40bdb" +checksum = "4a9febe641d2842ffc76ee962668a17578767c4e01735e4802b21ed9a24b2e4e" dependencies = [ "rand_core", ] @@ -3357,9 +3357,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.72" +version = "2.0.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" +checksum = "578e081a14e0cefc3279b0472138c513f37b41a08d5a3cca9b6e4e8ceb6cd525" dependencies = [ "proc-macro2", "quote", @@ -3865,9 +3865,9 @@ checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "wasmparser" -version = "0.214.0" +version = "0.216.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5309c1090e3e84dad0d382f42064e9933fdaedb87e468cc239f0eabea73ddcb6" +checksum = "bcdee6bea3619d311fb4b299721e89a986c3470f804b6d534340e412589028e3" dependencies = [ "ahash", "bitflags", @@ -3879,9 +3879,9 @@ dependencies = [ [[package]] name = "wasmprinter" -version = "0.214.0" +version = "0.216.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58d4f2b3f7bd2ba10f99e03f885ff90d5db3455e163bccecebbbf60406bd8980" +checksum = "8f82916f3892e53620639217d6ec78fe15c678352a3fbf3f3745b6417d0bd70f" dependencies = [ "anyhow", "termcolor", diff --git a/data/codec-derive/Cargo.toml b/data/codec-derive/Cargo.toml index 934b041232..707de3c33a 100644 --- a/data/codec-derive/Cargo.toml +++ b/data/codec-derive/Cargo.toml @@ -22,6 +22,6 @@ default = ["syn/full", "syn/parsing", "syn/extra-traits"] [dependencies] proc-macro2 = "=1.0.86" -quote = "=1.0.36" -syn = "=2.0.72" +quote = "=1.0.37" +syn = "=2.0.76" hex = "=0.4.3" diff --git a/data/codec/Cargo.toml b/data/codec/Cargo.toml index b09697b84c..be2e7f39f4 100644 --- a/data/codec/Cargo.toml +++ b/data/codec/Cargo.toml @@ -22,7 +22,7 @@ version = "=0.20.1" optional = true [dependencies] -arrayvec = { version = "=0.7.4", default-features = false } +arrayvec = { version = "=0.7.6", default-features = false } num-bigint = { version = "0.4", optional = true } # can only be used in std contexts unwrap-infallible = "0.1.5" diff --git a/framework/derive/Cargo.toml b/framework/derive/Cargo.toml index 50f6ef6dd0..d4246c314b 100644 --- a/framework/derive/Cargo.toml +++ b/framework/derive/Cargo.toml @@ -15,8 +15,8 @@ categories = ["cryptography::cryptocurrencies", "development-tools::procedural-m [dependencies] proc-macro2 = "=1.0.86" -quote = "=1.0.36" -syn = "=2.0.72" +quote = "=1.0.37" +syn = "=2.0.76" hex = "=0.4.3" radix_trie = "=0.2.1" diff --git a/framework/meta-lib/Cargo.toml b/framework/meta-lib/Cargo.toml index f3149ee0c8..484e9034cb 100644 --- a/framework/meta-lib/Cargo.toml +++ b/framework/meta-lib/Cargo.toml @@ -26,8 +26,8 @@ colored = "2.0" lazy_static = "1.4.0" convert_case = "0.6.0" hex = "0.4" -wasmparser = "0.214" -wasmprinter = "0.214" +wasmparser = "0.216" +wasmprinter = "0.216" semver = "1.0.20" [dependencies.multiversx-sc] diff --git a/vm/Cargo.toml b/vm/Cargo.toml index 568c7e512c..b823a5df66 100644 --- a/vm/Cargo.toml +++ b/vm/Cargo.toml @@ -31,7 +31,7 @@ hex-literal = "=0.4.1" bitflags = "=2.6.0" colored = "2.1.0" rand = { version= "0.8.5", optional = true } -rand_seeder = { version= "0.2.2", optional = true } +rand_seeder = { version= "0.3.0", optional = true } ed25519-dalek = { version = "2.1.0" , optional = true } [dependencies.multiversx-chain-vm-executor] From 259aaf2ee02f6fc5483ace28190473279d468e99 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Mon, 26 Aug 2024 15:13:45 +0300 Subject: [PATCH 46/92] rand_seeder & ed25519-dalek no longer wasm-incompatible --- vm/Cargo.toml | 6 +++--- vm/src/crypto_functions.rs | 8 +------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/vm/Cargo.toml b/vm/Cargo.toml index b823a5df66..7e5349688d 100644 --- a/vm/Cargo.toml +++ b/vm/Cargo.toml @@ -18,7 +18,7 @@ categories = ["cryptography::cryptocurrencies", "development-tools::debugging"] [features] # not supported when compiling to wasm -wasm-incompatible = ["rand", "rand_seeder", "ed25519-dalek"] +wasm-incompatible = ["rand"] [dependencies] num-bigint = "0.4" @@ -31,8 +31,8 @@ hex-literal = "=0.4.1" bitflags = "=2.6.0" colored = "2.1.0" rand = { version= "0.8.5", optional = true } -rand_seeder = { version= "0.3.0", optional = true } -ed25519-dalek = { version = "2.1.0" , optional = true } +rand_seeder = "0.3.0" +ed25519-dalek = "2.1.0" [dependencies.multiversx-chain-vm-executor] version = "0.2.0" diff --git a/vm/src/crypto_functions.rs b/vm/src/crypto_functions.rs index a1277ceac5..3dae63aad7 100644 --- a/vm/src/crypto_functions.rs +++ b/vm/src/crypto_functions.rs @@ -16,9 +16,8 @@ pub fn keccak256(data: &[u8]) -> [u8; KECCAK256_RESULT_LEN] { hasher.finalize().into() } -#[cfg(feature = "wasm-incompatible")] pub fn verify_ed25519(key: &[u8], message: &[u8], signature: &[u8]) -> bool { - use ed25519_dalek::{Signature, VerifyingKey, Verifier}; + use ed25519_dalek::{Signature, Verifier, VerifyingKey}; let key_32: [u8; 32] = if let Ok(key_32) = key.try_into() { key_32 @@ -43,8 +42,3 @@ pub fn verify_ed25519(key: &[u8], message: &[u8], signature: &[u8]) -> bool { let result = verifying_key.verify(message, &sig); result.is_ok() } - -#[cfg(not(feature = "wasm-incompatible"))] -pub fn verify_ed25519(_key: &[u8], _message: &[u8], _signature: &[u8]) -> bool { - panic!("verify_ed25519 not supported for wasm builds, feature `wasm-incompatible` needs to be enabled") -} From 91763211a17e083a3c1e06359f83b32c83eb30b6 Mon Sep 17 00:00:00 2001 From: Andrei Vasilescu Date: Mon, 26 Aug 2024 15:34:55 +0300 Subject: [PATCH 47/92] added more sys calls (SFTs/MetaESDTs) --- .../interact/src/basic_interact.rs | 189 ++++++++++++++++-- .../interact/src/basic_interact_cli.rs | 89 ++++++++- 2 files changed, 256 insertions(+), 22 deletions(-) diff --git a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs index 798d74159f..1286264025 100644 --- a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs +++ b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs @@ -2,6 +2,7 @@ mod basic_interact_cli; mod basic_interact_config; mod basic_interact_state; +use basic_interact_cli::NftDummyAttributes; use basic_interact_config::Config; use basic_interact_state::State; use clap::Parser; @@ -28,14 +29,62 @@ async fn main() { .await; }, Some(basic_interact_cli::InteractCliCommand::Mint(args)) => { - basic_interact.mint_token(args.amount.clone()).await; + basic_interact + .mint_token(&args.token_id, args.amount.clone()) + .await; }, Some(basic_interact_cli::InteractCliCommand::SetRoles(args)) => { // let parsed_args = SetRolesArgs::parse(); - basic_interact.set_role(args.roles.clone()).await; + basic_interact + .set_role(&args.token_id, args.roles.clone()) + .await; }, Some(basic_interact_cli::InteractCliCommand::Burn(args)) => { - basic_interact.burn_token(args.amount.clone()).await; + basic_interact + .burn_token(&args.token_id, args.amount.clone()) + .await; + }, + Some(basic_interact_cli::InteractCliCommand::IssueFungible(args)) => { + basic_interact + ._issue_fungible_token( + args.cost.clone(), + &args.display_name, + &args.ticker, + args.supply.clone(), + args.num_decimals, + ) + .await; + }, + Some(basic_interact_cli::InteractCliCommand::IssueSft(args)) => { + basic_interact + .issue_semi_fungible_token(args.cost.clone(), &args.display_name, &args.ticker) + .await; + }, + Some(basic_interact_cli::InteractCliCommand::MintSft(args)) => { + basic_interact + .mint_sft( + &args.token_id, + args.amount.clone(), + &args.name, + args.royalties.clone(), + &args.hash, + ) + .await; + }, + Some(basic_interact_cli::InteractCliCommand::RegisterMetaEsdt(args)) => { + basic_interact + .register_meta_esdt( + args.cost.clone(), + &args.display_name, + &args.ticker, + args.num_decimals, + ) + .await; + }, + Some(basic_interact_cli::InteractCliCommand::ChangeSftMetaEsdt(args)) => { + basic_interact + .change_sft_meta_esdt(&args.token_id, args.num_decimals) + .await; }, None => {}, @@ -47,7 +96,6 @@ struct SysFuncCallsInteract { interactor: Interactor, wallet_address: Bech32Address, state: State, - token_id: String, } impl SysFuncCallsInteract { @@ -62,7 +110,6 @@ impl SysFuncCallsInteract { interactor, wallet_address: wallet_address.into(), state: State::load_state(), - token_id: String::new(), } } @@ -71,6 +118,7 @@ impl SysFuncCallsInteract { issue_cost: RustBigUint, token_display_name: &str, token_ticker: &str, + initial_supply: RustBigUint, num_decimals: usize, ) { self.interactor @@ -83,7 +131,7 @@ impl SysFuncCallsInteract { issue_cost.into(), &token_display_name.into(), &token_ticker.into(), - &BigUint::from(100000000000000000000u128), + &initial_supply.into(), FungibleTokenProperties { num_decimals: num_decimals, can_freeze: true, @@ -101,6 +149,37 @@ impl SysFuncCallsInteract { .await; } + async fn issue_semi_fungible_token( + &mut self, + issue_cost: RustBigUint, + token_display_name: &str, + token_ticker: &str, + ) { + self.interactor + .tx() + .from(&self.wallet_address) + .to(ESDTSystemSCAddress.to_managed_address()) + .gas(100_000_000u64) + .typed(ESDTSystemSCProxy) + .issue_semi_fungible( + issue_cost.into(), + &token_display_name.into(), + &token_ticker.into(), + SemiFungibleTokenProperties { + can_freeze: true, + can_wipe: true, + can_pause: true, + can_transfer_create_role: true, + can_change_owner: true, + can_upgrade: true, + can_add_special_roles: true, + }, + ) + .prepare_async() + .run() + .await; + } + async fn issue_token( &mut self, issue_cost: RustBigUint, @@ -129,10 +208,9 @@ impl SysFuncCallsInteract { .await; println!("TOKEN ID: {:?}", token_id.to_string()); - self.token_id = token_id.to_string(); } - async fn set_role(&mut self, roles: Vec) { + async fn set_role(&mut self, token_id: &str, roles: Vec) { let wallet_address = &self.wallet_address.clone().into_address(); let converted_roles: Vec = roles.into_iter().map(|r| EsdtLocalRole::from(r)).collect(); @@ -147,7 +225,7 @@ impl SysFuncCallsInteract { .typed(ESDTSystemSCProxy) .set_special_roles::>( &ManagedAddress::from_address(wallet_address), - &TokenIdentifier::from(&self.token_id), + &TokenIdentifier::from(token_id), converted_roles.into_iter(), ) .prepare_async() @@ -155,35 +233,108 @@ impl SysFuncCallsInteract { .await; } - async fn mint_token(&mut self, amount: RustBigUint) { + async fn mint_sft( + &mut self, + token_id: &str, + amount: RustBigUint, + name: &str, + royalties: RustBigUint, + hash: &str, + ) { self.interactor .tx() .from(&self.wallet_address) .to(&self.wallet_address) .gas(100_000_000u64) .typed(UserBuiltinProxy) - .esdt_local_mint( - &TokenIdentifier::from(&self.token_id), - 0, + .esdt_nft_create( + &TokenIdentifier::from(token_id), &BigUint::from(amount), + &ManagedBuffer::from(name), + &royalties.into(), + &ManagedBuffer::from(hash), + &NftDummyAttributes { + creation_epoch: 2104, + cool_factor: 5, + }, + &ManagedVec::new(), + ) + .prepare_async() + .run() + .await; + } + + async fn register_meta_esdt( + &mut self, + issue_cost: RustBigUint, + token_display_name: &str, + token_ticker: &str, + num_decimals: usize, + ) { + let meta_esdt = self + .interactor + .tx() + .from(&self.wallet_address) + .to(ESDTSystemSCAddress.to_managed_address()) + .gas(100_000_000u64) + .typed(ESDTSystemSCProxy) + .register_meta_esdt( + issue_cost.into(), + &token_display_name.into(), + &token_ticker.into(), + MetaTokenProperties { + num_decimals: num_decimals, + can_freeze: true, + can_wipe: true, + can_transfer_create_role: true, + can_change_owner: true, + can_upgrade: true, + can_pause: true, + can_add_special_roles: true, + }, ) + .returns(ReturnsResultUnmanaged) .prepare_async() .run() .await; + + println!("META ESDT: {:?}", meta_esdt.to_string()); } - async fn burn_token(&mut self, amount: RustBigUint) { + async fn change_sft_meta_esdt(&mut self, token_id: &str, num_decimals: usize) { + self.interactor + .tx() + .from(&self.wallet_address) + .to(ESDTSystemSCAddress.to_managed_address()) + .gas(100_000_000u64) + .typed(ESDTSystemSCProxy) + .change_sft_to_meta_esdt(&TokenIdentifier::from(token_id), num_decimals) + .prepare_async() + .run() + .await; + } + + async fn mint_token(&mut self, token_id: &str, amount: RustBigUint) { self.interactor .tx() .from(&self.wallet_address) .to(&self.wallet_address) .gas(100_000_000u64) .typed(UserBuiltinProxy) - .esdt_local_burn( - &TokenIdentifier::from(&self.token_id), - 0, - &BigUint::from(amount), - ) + .esdt_local_mint(&TokenIdentifier::from(token_id), 0, &BigUint::from(amount)) + .prepare_async() + .run() + .await; + } + + async fn burn_token(&mut self, token_id: &str, amount: RustBigUint) { + self.interactor + .tx() + .from(&self.wallet_address) + .to(&self.wallet_address) + .gas(100_000_000u64) + .typed(UserBuiltinProxy) + .esdt_local_burn(&TokenIdentifier::from(token_id), 0, &BigUint::from(amount)) .prepare_async() .run() .await; diff --git a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_cli.rs b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_cli.rs index fe0597348d..704006a557 100644 --- a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_cli.rs +++ b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_cli.rs @@ -1,5 +1,5 @@ use clap::{Args, Parser, Subcommand}; -use multiversx_sc_snippets::imports::RustBigUint; +use multiversx_sc_snippets::{imports::RustBigUint, multiversx_sc::proxy_imports::*}; /// SysFuncCalls Interact CLI #[derive(Default, PartialEq, Eq, Debug, Parser)] @@ -13,14 +13,27 @@ pub struct InteractCli { /// SysFuncCalls Interact CLI Commands #[derive(Clone, PartialEq, Eq, Debug, Subcommand)] pub enum InteractCliCommand { - #[command(name = "issue-token", about = "Issue a token")] + #[command(name = "issue-token", about = "Issues a token")] IssueToken(IssueTokenArgs), #[command(name = "mint", about = "Mints fungible tokens")] Mint(MintArgs), - #[command(name = "set-roles", about = "Set roles")] + #[command(name = "set-roles", about = "Sets roles")] SetRoles(SetRolesArgs), #[command(name = "burn", about = "Burns fungible tokens")] Burn(BurnArgs), + #[command( + name = "issue-fungible", + about = "Issues fungible tokens and sends them to your wallet" + )] + IssueFungible(IssueFungibleArgs), + #[command(name = "issue-sft", about = "Issues a SFT")] + IssueSft(IssueSftArgs), + #[command(name = "mint-sft", about = "Mints a SFT")] + MintSft(MintSFTArgs), + #[command(name = "register-meta-esdt", about = "Registers a meta ESDT")] + RegisterMetaEsdt(RegisterMetaEsdtArgs), + #[command(name = "change-sft-meta-esdt", about = "Changes a SFT to a Meta ESDT")] + ChangeSftMetaEsdt(ChangeSftMetaEsdtArgs), } #[derive(Clone, Debug, PartialEq, Eq, Args)] @@ -39,18 +52,88 @@ pub struct IssueTokenArgs { #[derive(Clone, Debug, PartialEq, Eq, Args)] pub struct MintArgs { + #[arg(long = "token-id")] + pub token_id: String, #[arg(long = "amount")] pub amount: RustBigUint, } #[derive(Clone, Debug, PartialEq, Eq, Parser)] pub struct SetRolesArgs { + #[arg(long = "token-id")] + pub token_id: String, #[arg(long = "roles", value_delimiter = ',')] pub roles: Vec, } #[derive(Clone, Debug, PartialEq, Eq, Args)] pub struct BurnArgs { + #[arg(long = "token-id")] + pub token_id: String, #[arg(long = "amount")] pub amount: RustBigUint, } + +#[derive(Clone, Debug, PartialEq, Eq, Args)] +pub struct IssueFungibleArgs { + #[arg(short = 'c', long = "cost", default_value = "50000000000000000")] + pub cost: RustBigUint, + #[arg(long = "display-name")] + pub display_name: String, + #[arg(long = "token-ticker")] + pub ticker: String, + #[arg(long = "num-decimals")] + pub num_decimals: usize, + #[arg(short = 's', long = "supply")] + pub supply: RustBigUint, +} + +#[derive(Clone, Debug, PartialEq, Eq, Args)] +pub struct IssueSftArgs { + #[arg(short = 'c', long = "cost", default_value = "50000000000000000")] + pub cost: RustBigUint, + #[arg(long = "display-name")] + pub display_name: String, + #[arg(long = "token-ticker")] + pub ticker: String, +} + +#[derive(TopEncode, TopDecode, Clone, Debug, PartialEq, Eq)] +pub struct NftDummyAttributes { + pub creation_epoch: u64, + pub cool_factor: u8, +} + +#[derive(Clone, Debug, PartialEq, Eq, Args)] +pub struct MintSFTArgs { + #[arg(long = "token-id")] + pub token_id: String, + #[arg(short = 'a', long = "amount")] + pub amount: RustBigUint, + #[arg(short = 'n', long = "name")] + pub name: String, + #[arg(short = 'r', long = "royalties")] + pub royalties: RustBigUint, + #[arg(long = "hash")] + pub hash: String, +} + +#[derive(Clone, Debug, PartialEq, Eq, Args)] +pub struct RegisterMetaEsdtArgs { + #[arg(short = 'c', long = "cost", default_value = "50000000000000000")] + pub cost: RustBigUint, + #[arg(long = "display-name")] + pub display_name: String, + #[arg(long = "token-ticker")] + pub ticker: String, + #[arg(long = "num-decimals")] + pub num_decimals: usize, +} + +#[derive(Clone, Debug, PartialEq, Eq, Args)] +pub struct ChangeSftMetaEsdtArgs { + #[arg(long = "token-id")] + pub token_id: String, + #[arg(long = "num-decimals")] + pub num_decimals: usize, +} From 82cd85aa89ab08e087cb0d18e17151a2f3f6f782 Mon Sep 17 00:00:00 2001 From: Andrei Vasilescu Date: Mon, 26 Aug 2024 16:38:51 +0300 Subject: [PATCH 48/92] updated bech32 crate v0.11 --- Cargo.lock | 4 ++-- framework/scenario/Cargo.toml | 2 +- framework/scenario/src/bech32.rs | 9 ++++----- sdk/core/Cargo.toml | 2 +- sdk/core/src/crypto/public_key.rs | 5 +++-- sdk/core/src/data/address.rs | 8 ++++---- sdk/scenario-format/Cargo.toml | 2 +- sdk/scenario-format/src/value_interpreter/functions.rs | 5 ++--- tools/mxpy-snippet-generator/Cargo.toml | 2 +- tools/mxpy-snippet-generator/src/helper_types.rs | 4 +--- 10 files changed, 20 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b7fe71048c..ac352c58c6 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -266,9 +266,9 @@ dependencies = [ [[package]] name = "bech32" -version = "0.9.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" +checksum = "d965446196e3b7decd44aa7ee49e31d630118f90ef12f97900f262eb915c951d" [[package]] name = "benchmark-common" diff --git a/framework/scenario/Cargo.toml b/framework/scenario/Cargo.toml index 0e13cb71dd..796ab19bf0 100644 --- a/framework/scenario/Cargo.toml +++ b/framework/scenario/Cargo.toml @@ -21,7 +21,7 @@ base64 = "0.22" num-bigint = "0.4" num-traits = "0.2" hex = "0.4" -bech32 = "0.9" +bech32 = "0.11" log = "0.4.17" sha2 = "0.10.6" serde = "1.0" diff --git a/framework/scenario/src/bech32.rs b/framework/scenario/src/bech32.rs index aa224cee95..ef934cf225 100644 --- a/framework/scenario/src/bech32.rs +++ b/framework/scenario/src/bech32.rs @@ -1,10 +1,9 @@ -use bech32::{FromBase32, ToBase32, Variant}; +use bech32::{Bech32, Hrp}; use multiversx_sc::types::heap::Address; pub fn decode(bech32_address: &str) -> Address { - let (_, dest_address_bytes_u5, _) = bech32::decode(bech32_address) + let (_hrp, dest_address_bytes) = bech32::decode(bech32_address) .unwrap_or_else(|err| panic!("bech32 decode error for {bech32_address}: {err}")); - let dest_address_bytes = Vec::::from_base32(&dest_address_bytes_u5).unwrap(); if dest_address_bytes.len() != 32 { panic!("Invalid address length after decoding") } @@ -13,6 +12,6 @@ pub fn decode(bech32_address: &str) -> Address { } pub fn encode(address: &Address) -> String { - bech32::encode("erd", address.as_bytes().to_base32(), Variant::Bech32) - .expect("bech32 encode error") + let hrp = Hrp::parse("erd").expect("invalid hrp"); + bech32::encode::(hrp, address.as_bytes()).expect("bech32 encode error") } diff --git a/sdk/core/Cargo.toml b/sdk/core/Cargo.toml index e84f8cd4cb..2387e4cce8 100644 --- a/sdk/core/Cargo.toml +++ b/sdk/core/Cargo.toml @@ -31,7 +31,7 @@ hex = "0.4.3" base64 = "0.22" pbkdf2 = { version = "0.12.2", default-features = false } zeroize = "1.4.2" -bech32 = "0.9" +bech32 = "0.11" itertools = "0.13.0" pem = "3.0.2" log = "0.4.17" diff --git a/sdk/core/src/crypto/public_key.rs b/sdk/core/src/crypto/public_key.rs index 89b5211262..473a0388fe 100644 --- a/sdk/core/src/crypto/public_key.rs +++ b/sdk/core/src/crypto/public_key.rs @@ -2,7 +2,7 @@ use std::fmt::Display; use super::private_key::PrivateKey; use anyhow::Result; -use bech32::{self, ToBase32, Variant}; +use bech32::{self, Bech32, Hrp}; use serde::{ de::{Deserialize, Deserializer}, ser::{Serialize, Serializer}, @@ -23,7 +23,8 @@ impl PublicKey { } pub fn to_address(&self) -> Result { - let address = bech32::encode("erd", self.0.to_base32(), Variant::Bech32)?; + let hrp = Hrp::parse("erd")?; + let address = bech32::encode::(hrp, &self.0)?; Ok(address) } diff --git a/sdk/core/src/data/address.rs b/sdk/core/src/data/address.rs index f8ac4212c3..49d92ea608 100644 --- a/sdk/core/src/data/address.rs +++ b/sdk/core/src/data/address.rs @@ -2,7 +2,7 @@ use std::fmt::{Debug, Display}; use crate::crypto::public_key::PublicKey; use anyhow::Result; -use bech32::{FromBase32, ToBase32, Variant}; +use bech32::{Bech32, Hrp}; use serde::{ de::{Deserialize, Deserializer}, ser::{Serialize, Serializer}, @@ -21,8 +21,7 @@ impl Address { } pub fn from_bech32_string(bech32: &str) -> Result { - let (_, data, _) = bech32::decode(bech32)?; - let data = Vec::::from_base32(&data)?; + let (_hrp, data) = bech32::decode(bech32)?; let mut bits: [u8; 32] = [0u8; 32]; bits.copy_from_slice(&data); @@ -31,7 +30,8 @@ impl Address { } pub fn to_bech32_string(&self) -> Result { - let address = bech32::encode("erd", self.0.to_base32(), Variant::Bech32)?; + let hrp = Hrp::parse("erd")?; + let address = bech32::encode::(hrp, &self.0)?; Ok(address) } diff --git a/sdk/scenario-format/Cargo.toml b/sdk/scenario-format/Cargo.toml index b66e3403ce..a79c6c31a7 100644 --- a/sdk/scenario-format/Cargo.toml +++ b/sdk/scenario-format/Cargo.toml @@ -20,4 +20,4 @@ num-bigint = "0.4" num-traits = "0.2" hex = "0.4" sha3 = "0.10.8" -bech32 = "0.9.0" +bech32 = "0.11.0" diff --git a/sdk/scenario-format/src/value_interpreter/functions.rs b/sdk/scenario-format/src/value_interpreter/functions.rs index 32895e84d7..b4ce547ad7 100644 --- a/sdk/scenario-format/src/value_interpreter/functions.rs +++ b/sdk/scenario-format/src/value_interpreter/functions.rs @@ -1,5 +1,4 @@ use crate::value_interpreter::*; -use bech32::FromBase32; use sha3::{Digest, Keccak256}; pub const SC_ADDRESS_NUM_LEADING_ZEROS: usize = 8; @@ -71,6 +70,6 @@ pub(crate) fn sc_address_expression(input: &str, vm_type: &VMIdentifier) -> Vec< } pub(crate) fn bech32(input: &str) -> Vec { - let (_, decoded, _) = bech32::decode(input).expect("bech32 decode error"); - Vec::::from_base32(&decoded).expect("bech32 base64 decode error") + let (_hrp, decoded) = bech32::decode(input).expect("bech32 decode error"); + decoded } diff --git a/tools/mxpy-snippet-generator/Cargo.toml b/tools/mxpy-snippet-generator/Cargo.toml index 58236c7f78..838f8a1dc2 100644 --- a/tools/mxpy-snippet-generator/Cargo.toml +++ b/tools/mxpy-snippet-generator/Cargo.toml @@ -14,7 +14,7 @@ version = "0.52.3" path = "../../framework/base" [dependencies] -bech32 = "0.9" +bech32 = "0.11" num-bigint = "0.4" num-traits = "0.2" hex = "0.4" diff --git a/tools/mxpy-snippet-generator/src/helper_types.rs b/tools/mxpy-snippet-generator/src/helper_types.rs index d2cb746a51..e012ef2cb6 100644 --- a/tools/mxpy-snippet-generator/src/helper_types.rs +++ b/tools/mxpy-snippet-generator/src/helper_types.rs @@ -1,4 +1,3 @@ -use bech32::FromBase32; use multiversx_sc::types::heap::Address; use crate::constants::*; @@ -79,8 +78,7 @@ impl TransactionType { } pub fn bech32_to_bytes(bech32_address: &str) -> Address { - let (_, dest_address_bytes_u5, _) = bech32::decode(bech32_address).unwrap(); - let dest_address_bytes = Vec::::from_base32(&dest_address_bytes_u5).unwrap(); + let (_hrp, dest_address_bytes) = bech32::decode(bech32_address).unwrap(); if dest_address_bytes.len() != ADDRESS_LEN { panic!("Invalid address length after decoding") } From b49b9df02f096fcb8523f08add5c0bb425dbfa12 Mon Sep 17 00:00:00 2001 From: Andrei Vasilescu Date: Mon, 26 Aug 2024 18:25:53 +0300 Subject: [PATCH 49/92] added unset-roles --- .../interact/src/basic_interact.rs | 33 ++++++++++++++++++- .../interact/src/basic_interact_cli.rs | 12 +++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs index 1286264025..95b103d1ee 100644 --- a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs +++ b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs @@ -7,7 +7,7 @@ use basic_interact_config::Config; use basic_interact_state::State; use clap::Parser; -use multiversx_sc_snippets::imports::*; +use multiversx_sc_snippets::{hex, imports::*}; #[tokio::main] async fn main() { @@ -86,6 +86,11 @@ async fn main() { .change_sft_meta_esdt(&args.token_id, args.num_decimals) .await; }, + Some(basic_interact_cli::InteractCliCommand::UnsetRoles(args)) => { + basic_interact + .unset_roles(&args.address, &args.token_id, args.roles.clone()) + .await; + }, None => {}, } @@ -339,4 +344,30 @@ impl SysFuncCallsInteract { .run() .await; } + + async fn unset_roles(&mut self, address: &str, token_id: &str, roles: Vec) { + let converted_roles: Vec = + roles.into_iter().map(|r| EsdtLocalRole::from(r)).collect(); + + println!("ROLES: {:?}", converted_roles); + + let bech32_addr = Bech32Address::from_bech32_string(address.to_string()); + let addr = bech32_addr.to_address(); + let managed_addr: ManagedAddress = ManagedAddress::from_address(&addr); + + self.interactor + .tx() + .from(&self.wallet_address) + .to(ESDTSystemSCAddress.to_managed_address()) + .gas(100_000_000u64) + .typed(ESDTSystemSCProxy) + .unset_special_roles( + &managed_addr, + &TokenIdentifier::from(token_id), + converted_roles.into_iter(), + ) + .prepare_async() + .run() + .await; + } } diff --git a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_cli.rs b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_cli.rs index 704006a557..d39c41dbda 100644 --- a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_cli.rs +++ b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_cli.rs @@ -34,6 +34,8 @@ pub enum InteractCliCommand { RegisterMetaEsdt(RegisterMetaEsdtArgs), #[command(name = "change-sft-meta-esdt", about = "Changes a SFT to a Meta ESDT")] ChangeSftMetaEsdt(ChangeSftMetaEsdtArgs), + #[command(name = "unset-roles", about = "Unsets the roles of a token")] + UnsetRoles(UnsetRolesArgs), } #[derive(Clone, Debug, PartialEq, Eq, Args)] @@ -137,3 +139,13 @@ pub struct ChangeSftMetaEsdtArgs { #[arg(long = "num-decimals")] pub num_decimals: usize, } + +#[derive(Clone, Debug, PartialEq, Eq, Parser)] +pub struct UnsetRolesArgs { + #[arg(short = 'a', long = "address")] + pub address: String, + #[arg(long = "token-id")] + pub token_id: String, + #[arg(long = "roles", value_delimiter = ',')] + pub roles: Vec, +} From 911900e5cbc76b1378a365a9703499f5361bd570 Mon Sep 17 00:00:00 2001 From: Andrei Vasilescu Date: Mon, 26 Aug 2024 18:42:24 +0300 Subject: [PATCH 50/92] added transfering ownership example for nft/sft/fungible --- .../interact/src/basic_interact.rs | 54 +++++++++++++++++++ .../interact/src/basic_interact_cli.rs | 23 ++++++++ 2 files changed, 77 insertions(+) diff --git a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs index 95b103d1ee..a1b3324d01 100644 --- a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs +++ b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs @@ -91,6 +91,16 @@ async fn main() { .unset_roles(&args.address, &args.token_id, args.roles.clone()) .await; }, + Some(basic_interact_cli::InteractCliCommand::TransferOwnership(args)) => { + basic_interact + .transfer_ownership(&args.token_id, &args.new_owner) + .await; + }, + Some(basic_interact_cli::InteractCliCommand::TransferNftCreateRole(args)) => { + basic_interact + .transfer_nft_create_role(&args.token_id, &args.old_owner, &args.new_owner) + .await; + }, None => {}, } @@ -370,4 +380,48 @@ impl SysFuncCallsInteract { .run() .await; } + + async fn transfer_ownership(&mut self, token_id: &str, new_owner: &str) { + let bech32_addr = Bech32Address::from_bech32_string(new_owner.to_string()); + let addr = bech32_addr.to_address(); + let managed_addr: ManagedAddress = ManagedAddress::from_address(&addr); + + self.interactor + .tx() + .from(&self.wallet_address) + .to(ESDTSystemSCAddress.to_managed_address()) + .gas(100_000_000u64) + .typed(ESDTSystemSCProxy) + .transfer_ownership(&TokenIdentifier::from(token_id), &managed_addr) + .prepare_async() + .run() + .await; + } + + async fn transfer_nft_create_role(&mut self, token_id: &str, old_owner: &str, new_owner: &str) { + let bech32_addr_new_owner = Bech32Address::from_bech32_string(new_owner.to_string()); + let addr_new_owner = bech32_addr_new_owner.to_address(); + let managed_addr_new_owner: ManagedAddress = + ManagedAddress::from_address(&addr_new_owner); + + let bech32_addr_old_owner = Bech32Address::from_bech32_string(old_owner.to_string()); + let addr_old_owner = bech32_addr_old_owner.to_address(); + let managed_addr_old_owner: ManagedAddress = + ManagedAddress::from_address(&addr_old_owner); + + self.interactor + .tx() + .from(&self.wallet_address) + .to(ESDTSystemSCAddress.to_managed_address()) + .gas(100_000_000u64) + .typed(ESDTSystemSCProxy) + .transfer_nft_create_role( + &TokenIdentifier::from(token_id), + &managed_addr_old_owner, + &managed_addr_new_owner, + ) + .prepare_async() + .run() + .await; + } } diff --git a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_cli.rs b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_cli.rs index d39c41dbda..eaca398af6 100644 --- a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_cli.rs +++ b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_cli.rs @@ -36,6 +36,10 @@ pub enum InteractCliCommand { ChangeSftMetaEsdt(ChangeSftMetaEsdtArgs), #[command(name = "unset-roles", about = "Unsets the roles of a token")] UnsetRoles(UnsetRolesArgs), + #[command(name = "transfer-ownership", about = "Transfers ownership of a token")] + TransferOwnership(TransferOwnershipArgs), + #[command(name = "transfer-nft-create-role", about = "Transfers NFT create role")] + TransferNftCreateRole(TransferNftCreateRoleArgs), } #[derive(Clone, Debug, PartialEq, Eq, Args)] @@ -149,3 +153,22 @@ pub struct UnsetRolesArgs { #[arg(long = "roles", value_delimiter = ',')] pub roles: Vec, } + +#[derive(Clone, Debug, PartialEq, Eq, Args)] +pub struct TransferOwnershipArgs { + #[arg(long = "token-id")] + pub token_id: String, + #[arg(long = "new-owner")] + pub new_owner: String, +} + +#[derive(Clone, Debug, PartialEq, Eq, Args)] + +pub struct TransferNftCreateRoleArgs { + #[arg(long = "token-id")] + pub token_id: String, + #[arg(long = "old-owner")] + pub old_owner: String, + #[arg(long = "new-owner")] + pub new_owner: String, +} From 29751a95fac290385b4dae232ba3222b3e51d03f Mon Sep 17 00:00:00 2001 From: JustEatAnApple Date: Mon, 26 Aug 2024 19:14:06 +0300 Subject: [PATCH 51/92] [WIP] Added more system func calls --- .../interact/src/basic_interact.rs | 255 +++++++++++++++++- .../interact/src/basic_interact_cli.rs | 91 +++++++ 2 files changed, 339 insertions(+), 7 deletions(-) diff --git a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs index a1b3324d01..023875cd40 100644 --- a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs +++ b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs @@ -7,7 +7,7 @@ use basic_interact_config::Config; use basic_interact_state::State; use clap::Parser; -use multiversx_sc_snippets::{hex, imports::*}; +use multiversx_sc_snippets::imports::*; #[tokio::main] async fn main() { @@ -44,6 +44,58 @@ async fn main() { .burn_token(&args.token_id, args.amount.clone()) .await; }, + Some(basic_interact_cli::InteractCliCommand::PauseToken(args)) => { + basic_interact.pause_token(&args.token_id).await; + }, + Some(basic_interact_cli::InteractCliCommand::UnpauseToken(args)) => { + basic_interact.unpause_token(&args.token_id).await; + }, + Some(basic_interact_cli::InteractCliCommand::FreezeToken(args)) => { + basic_interact + .freeze_token(&args.token_id, &args.address) + .await; + }, + Some(basic_interact_cli::InteractCliCommand::UnfreezeToken(args)) => { + basic_interact + .unfreeze_token(&args.token_id, &args.address) + .await; + }, + Some(basic_interact_cli::InteractCliCommand::FreezeNFT(args)) => { + basic_interact + .freeze_nft(&args.token_id, args.nft_nonce, &args.address) + .await; + }, + Some(basic_interact_cli::InteractCliCommand::UnfreezeNFT(args)) => { + basic_interact + .unfreeze_nft(&args.token_id, args.nft_nonce, &args.address) + .await; + }, + Some(basic_interact_cli::InteractCliCommand::WipeToken(args)) => { + basic_interact + .wipe_token(&args.token_id, &args.address) + .await; + }, + Some(basic_interact_cli::InteractCliCommand::WipeNFT(args)) => { + basic_interact + .wipe_nft(&args.token_id, args.nft_nonce, &args.address) + .await; + }, + Some(basic_interact_cli::InteractCliCommand::IssueNFT(args)) => { + basic_interact + .issue_non_fungible_token(args.cost.clone(), &args.display_name, &args.ticker) + .await; + }, + Some(basic_interact_cli::InteractCliCommand::CreateNFT(args)) => { + basic_interact + .create_nft( + &args.token_id, + args.amount.clone(), + &args.name, + args.royalties, + &args.hash, + ) + .await; + }, Some(basic_interact_cli::InteractCliCommand::IssueFungible(args)) => { basic_interact ._issue_fungible_token( @@ -148,7 +200,7 @@ impl SysFuncCallsInteract { &token_ticker.into(), &initial_supply.into(), FungibleTokenProperties { - num_decimals: num_decimals, + num_decimals, can_freeze: true, can_wipe: true, can_pause: true, @@ -164,6 +216,37 @@ impl SysFuncCallsInteract { .await; } + async fn issue_non_fungible_token( + &mut self, + issue_cost: RustBigUint, + token_display_name: &str, + token_ticker: &str, + ) { + self.interactor + .tx() + .from(&self.wallet_address) + .to(ESDTSystemSCAddress.to_managed_address()) + .gas(100_000_000u64) + .typed(ESDTSystemSCProxy) + .issue_non_fungible( + issue_cost.into(), + &token_display_name.into(), + &token_ticker.into(), + NonFungibleTokenProperties { + can_freeze: true, + can_wipe: true, + can_pause: true, + can_transfer_create_role: true, + can_change_owner: true, + can_upgrade: true, + can_add_special_roles: true, + }, + ) + .prepare_async() + .run() + .await; + } + async fn issue_semi_fungible_token( &mut self, issue_cost: RustBigUint, @@ -227,8 +310,7 @@ impl SysFuncCallsInteract { async fn set_role(&mut self, token_id: &str, roles: Vec) { let wallet_address = &self.wallet_address.clone().into_address(); - let converted_roles: Vec = - roles.into_iter().map(|r| EsdtLocalRole::from(r)).collect(); + let converted_roles: Vec = roles.into_iter().map(EsdtLocalRole::from).collect(); println!("ROLES: {:?}", converted_roles); @@ -298,7 +380,7 @@ impl SysFuncCallsInteract { &token_display_name.into(), &token_ticker.into(), MetaTokenProperties { - num_decimals: num_decimals, + num_decimals, can_freeze: true, can_wipe: true, can_transfer_create_role: true, @@ -355,9 +437,168 @@ impl SysFuncCallsInteract { .await; } + async fn pause_token(&mut self, token_id: &str) { + self.interactor + .tx() + .from(&self.wallet_address) + .to(ESDTSystemSCAddress.to_managed_address()) + .gas(100_000_000u64) + .typed(ESDTSystemSCProxy) + .pause(&TokenIdentifier::from(token_id)) + .prepare_async() + .run() + .await; + } + + async fn unpause_token(&mut self, token_id: &str) { + self.interactor + .tx() + .from(&self.wallet_address) + .to(ESDTSystemSCAddress.to_managed_address()) + .gas(100_000_000u64) + .typed(ESDTSystemSCProxy) + .unpause(&TokenIdentifier::from(token_id)) + .prepare_async() + .run() + .await; + } + + async fn freeze_token(&mut self, token_id: &str, address: &str) { + let address = Bech32Address::from_bech32_string(address.to_string()).to_address(); + let managed_address: ManagedAddress = ManagedAddress::from_address(&address); + self.interactor + .tx() + .from(&self.wallet_address) + .to(ESDTSystemSCAddress.to_managed_address()) + .gas(100_000_000u64) + .typed(ESDTSystemSCProxy) + .freeze(&TokenIdentifier::from(token_id), &managed_address) + .prepare_async() + .run() + .await; + } + + async fn unfreeze_token(&mut self, token_id: &str, address: &str) { + let address = Bech32Address::from_bech32_string(address.to_string()).to_address(); + let managed_address: ManagedAddress = ManagedAddress::from_address(&address); + self.interactor + .tx() + .from(&self.wallet_address) + .to(ESDTSystemSCAddress.to_managed_address()) + .gas(100_000_000u64) + .typed(ESDTSystemSCProxy) + .unfreeze(&TokenIdentifier::from(token_id), &managed_address) + .prepare_async() + .run() + .await; + } + + async fn freeze_nft(&mut self, token_id: &str, nonce: u64, address: &str) { + let address = Bech32Address::from_bech32_string(address.to_string()).to_address(); + let managed_address: ManagedAddress = ManagedAddress::from_address(&address); + self.interactor + .tx() + .from(&self.wallet_address) + .to(ESDTSystemSCAddress.to_managed_address()) + .gas(100_000_000u64) + .typed(ESDTSystemSCProxy) + .freeze_nft( + &TokenIdentifier::from(token_id), + nonce, + &managed_address, + ) + .prepare_async() + .run() + .await; + } + + async fn unfreeze_nft(&mut self, token_id: &str, nonce: u64, address: &str) { + let address = Bech32Address::from_bech32_string(address.to_string()).to_address(); + let managed_address: ManagedAddress = ManagedAddress::from_address(&address); + self.interactor + .tx() + .from(&self.wallet_address) + .to(ESDTSystemSCAddress.to_managed_address()) + .gas(100_000_000u64) + .typed(ESDTSystemSCProxy) + .unfreeze_nft( + &TokenIdentifier::from(token_id), + nonce, + &managed_address, + ) + .prepare_async() + .run() + .await; + } + + async fn wipe_token(&mut self, token_id: &str, address: &str) { + let address = Bech32Address::from_bech32_string(address.to_string()).to_address(); + let managed_address: ManagedAddress = ManagedAddress::from_address(&address); + self.interactor + .tx() + .from(&self.wallet_address) + .to(&ESDTSystemSCAddress.to_managed_address()) + .gas(100_000_000u64) + .typed(ESDTSystemSCProxy) + .wipe(&TokenIdentifier::from(token_id), &managed_address) + .prepare_async() + .run() + .await; + } + + async fn wipe_nft(&mut self, token_id: &str, nonce: u64, address: &str) { + let address = Bech32Address::from_bech32_string(address.to_string()).to_address(); + let managed_address: ManagedAddress = ManagedAddress::from_address(&address); + self.interactor + .tx() + .from(&self.wallet_address) + .to(ESDTSystemSCAddress.to_managed_address()) + .gas(100_000_000u64) + .typed(ESDTSystemSCProxy) + .wipe_nft( + &TokenIdentifier::from(token_id), + nonce, + &managed_address, + ) + .prepare_async() + .run() + .await; + } + + async fn create_nft( + &mut self, + token_id: &str, + amount: RustBigUint, + name: &str, + royalties: u64, + hash: &str, + ) { + self.interactor + .tx() + .from(&self.wallet_address) + .to(&self.wallet_address) + .gas(100_000_000u64) + .typed(UserBuiltinProxy) + .esdt_nft_create( + &TokenIdentifier::from(token_id), + &BigUint::from(amount), + &ManagedBuffer::from(name), + &BigUint::from(royalties), + &ManagedBuffer::from(hash), + &NftDummyAttributes { + creation_epoch: 2104, + cool_factor: 5, + }, + &ManagedVec::new(), + ) + .prepare_async() + .run() + .await; + } + async fn unset_roles(&mut self, address: &str, token_id: &str, roles: Vec) { - let converted_roles: Vec = - roles.into_iter().map(|r| EsdtLocalRole::from(r)).collect(); + let converted_roles: Vec = roles.into_iter().map(EsdtLocalRole::from).collect(); + println!("ROLES: {:?}", converted_roles); diff --git a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_cli.rs b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_cli.rs index eaca398af6..f740ff3d30 100644 --- a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_cli.rs +++ b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_cli.rs @@ -21,6 +21,26 @@ pub enum InteractCliCommand { SetRoles(SetRolesArgs), #[command(name = "burn", about = "Burns fungible tokens")] Burn(BurnArgs), + #[command(name = "pause-token", about = "Pauses a fungible token")] + PauseToken(PauseTokenArgs), + #[command(name = "unpause-token", about = "Unpauses a fungible token")] + UnpauseToken(PauseTokenArgs), + #[command(name = "freeze-token", about = "Freezes a fungible token for an address")] + FreezeToken(FreezeTokenArgs), + #[command(name = "unfreeze-token", about = "Unfreezes a fungible token for an address")] + UnfreezeToken(FreezeTokenArgs), + #[command(name = "freeze-nft", about = "Freezes a non-fungible token for an address")] + FreezeNFT(FreezeNFTArgs), + #[command(name = "unfreeze-nft", about = "Unfreezes a non-fungible token for an address")] + UnfreezeNFT(FreezeNFTArgs), + #[command(name = "wipe-token", about = "Wipes a fungible token for an address")] + WipeToken(WipeTokenArgs), + #[command(name = "wipe-nft", about = "Freezes a non-fungible token for an address")] + WipeNFT(WipeNFTArgs), + #[command(name = "issue-non-fungible-token", about = "Create a NFT Collection")] + IssueNFT(IssueNFTArgs), + #[command(name = "create-nft", about = "Issue a NFT")] + CreateNFT(CreateNFTArgs), #[command( name = "issue-fungible", about = "Issues fungible tokens and sends them to your wallet" @@ -94,6 +114,16 @@ pub struct IssueFungibleArgs { pub supply: RustBigUint, } +#[derive(Clone, Debug, PartialEq, Eq, Args)] +pub struct IssueNFTArgs { + #[arg(short = 'c', long = "cost", default_value = "50000000000000000")] + pub cost: RustBigUint, + #[arg(short = 'd', long = "display-name")] + pub display_name: String, + #[arg(long = "token-ticker")] + pub ticker: String, +} + #[derive(Clone, Debug, PartialEq, Eq, Args)] pub struct IssueSftArgs { #[arg(short = 'c', long = "cost", default_value = "50000000000000000")] @@ -172,3 +202,64 @@ pub struct TransferNftCreateRoleArgs { #[arg(long = "new-owner")] pub new_owner: String, } + +#[derive(Clone, Debug, PartialEq, Eq, Args)] +pub struct PauseTokenArgs { + #[arg(long = "token-id", default_value = "")] + pub token_id: String, +} + +#[derive(Clone, Debug, PartialEq, Eq, Args)] +pub struct FreezeTokenArgs { + #[arg(long = "token-id", default_value = "")] + pub token_id: String, + #[arg(short = 'a', long = "address")] + pub address: String, +} + +#[derive(Clone, Debug, PartialEq, Eq, Args)] +pub struct FreezeNFTArgs { + #[arg(long = "token-id", default_value = "")] + pub token_id: String, + #[arg(long = "nonce")] + pub nft_nonce: u64, + #[arg(short = 'a', long = "address")] + pub address: String, +} + +#[derive(Clone, Debug, PartialEq, Eq, Args)] +pub struct WipeTokenArgs { + #[arg(long = "token-id", default_value = "")] + pub token_id: String, + #[arg(short = 'a', long = "address")] + pub address: String, +} + +#[derive(Clone, Debug, PartialEq, Eq, Args)] +pub struct WipeNFTArgs { + #[arg(long = "token-id", default_value = "")] + pub token_id: String, + #[arg(long = "nonce")] + pub nft_nonce: u64, + #[arg(short = 'a', long = "address")] + pub address: String, +} + +#[derive(Clone, Debug, PartialEq, Eq, Args)] +pub struct CreateNFTArgs { + // token amount name hash royalities attributes uris + #[arg(long = "token-id")] + pub token_id: String, + #[arg(short = 'a', long = "amount")] + pub amount: RustBigUint, + #[arg(short = 'n', long = "name")] + pub name: String, + #[arg(long = "hash")] + pub hash: String, + #[arg(short = 'r', long = "royalities")] + pub royalties: u64, + // #[long = "attributes")] + // pub attributes: String, + // #[arg(long = "uris")] + // pub uris: String, +} From 85e06df3496266cf457141df360f13617c4d68a7 Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Mon, 26 Aug 2024 23:37:41 +0300 Subject: [PATCH 52/92] added esdt processing for transfer step in interactor --- .../src/scenario/tx_to_step/tx_to_step_transfer.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/framework/scenario/src/scenario/tx_to_step/tx_to_step_transfer.rs b/framework/scenario/src/scenario/tx_to_step/tx_to_step_transfer.rs index d2bf9636c9..d2baa6bc6c 100644 --- a/framework/scenario/src/scenario/tx_to_step/tx_to_step_transfer.rs +++ b/framework/scenario/src/scenario/tx_to_step/tx_to_step_transfer.rs @@ -1,6 +1,6 @@ use multiversx_sc::types::{Tx, TxEnv, TxFromSpecified, TxGas, TxPayment, TxToSpecified}; -use crate::scenario_model::TransferStep; +use crate::{imports::TxESDT, scenario_model::TransferStep}; use super::{address_annotated, gas_annotated, StepWrapper, TxToStep}; @@ -48,6 +48,12 @@ where let full_payment_data = payment.into_full_payment_data(env); if let Some(annotated_egld_payment) = full_payment_data.egld { step.tx.egld_value = annotated_egld_payment.into(); + } else { + step.tx.esdt_value = full_payment_data + .multi_esdt + .iter() + .map(TxESDT::from) + .collect(); } step From a86a9d838a60ae201583962a0ca24271cfa04355 Mon Sep 17 00:00:00 2001 From: Andrei Vasilescu Date: Tue, 27 Aug 2024 10:51:01 +0300 Subject: [PATCH 53/92] system SC func calls interactor example done --- .../interact/src/basic_interact.rs | 64 ++++++++++++------- .../interact/src/basic_interact_cli.rs | 45 +++++++++---- 2 files changed, 71 insertions(+), 38 deletions(-) diff --git a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs index 023875cd40..05c26126ff 100644 --- a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs +++ b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs @@ -34,7 +34,6 @@ async fn main() { .await; }, Some(basic_interact_cli::InteractCliCommand::SetRoles(args)) => { - // let parsed_args = SetRolesArgs::parse(); basic_interact .set_role(&args.token_id, args.roles.clone()) .await; @@ -80,9 +79,9 @@ async fn main() { .wipe_nft(&args.token_id, args.nft_nonce, &args.address) .await; }, - Some(basic_interact_cli::InteractCliCommand::IssueNFT(args)) => { + Some(basic_interact_cli::InteractCliCommand::IssueNFTCollection(args)) => { basic_interact - .issue_non_fungible_token(args.cost.clone(), &args.display_name, &args.ticker) + .issue_non_fungible_collection(args.cost.clone(), &args.display_name, &args.ticker) .await; }, Some(basic_interact_cli::InteractCliCommand::CreateNFT(args)) => { @@ -153,6 +152,9 @@ async fn main() { .transfer_nft_create_role(&args.token_id, &args.old_owner, &args.new_owner) .await; }, + Some(basic_interact_cli::InteractCliCommand::ControlChanges(args)) => { + basic_interact.control_changes(&args.token_id).await; + }, None => {}, } @@ -170,8 +172,7 @@ impl SysFuncCallsInteract { let config = Config::load_config(); let mut interactor = Interactor::new(config.gateway()).await; - let wallet_address = - interactor.register_wallet(Wallet::from_pem_file("wallet.pem").unwrap()); + let wallet_address = interactor.register_wallet(test_wallets::alice()); Self { interactor, @@ -216,7 +217,7 @@ impl SysFuncCallsInteract { .await; } - async fn issue_non_fungible_token( + async fn issue_non_fungible_collection( &mut self, issue_cost: RustBigUint, token_display_name: &str, @@ -310,7 +311,8 @@ impl SysFuncCallsInteract { async fn set_role(&mut self, token_id: &str, roles: Vec) { let wallet_address = &self.wallet_address.clone().into_address(); - let converted_roles: Vec = roles.into_iter().map(EsdtLocalRole::from).collect(); + let converted_roles: Vec = + roles.into_iter().map(EsdtLocalRole::from).collect(); println!("ROLES: {:?}", converted_roles); @@ -502,11 +504,7 @@ impl SysFuncCallsInteract { .to(ESDTSystemSCAddress.to_managed_address()) .gas(100_000_000u64) .typed(ESDTSystemSCProxy) - .freeze_nft( - &TokenIdentifier::from(token_id), - nonce, - &managed_address, - ) + .freeze_nft(&TokenIdentifier::from(token_id), nonce, &managed_address) .prepare_async() .run() .await; @@ -521,11 +519,7 @@ impl SysFuncCallsInteract { .to(ESDTSystemSCAddress.to_managed_address()) .gas(100_000_000u64) .typed(ESDTSystemSCProxy) - .unfreeze_nft( - &TokenIdentifier::from(token_id), - nonce, - &managed_address, - ) + .unfreeze_nft(&TokenIdentifier::from(token_id), nonce, &managed_address) .prepare_async() .run() .await; @@ -555,11 +549,7 @@ impl SysFuncCallsInteract { .to(ESDTSystemSCAddress.to_managed_address()) .gas(100_000_000u64) .typed(ESDTSystemSCProxy) - .wipe_nft( - &TokenIdentifier::from(token_id), - nonce, - &managed_address, - ) + .wipe_nft(&TokenIdentifier::from(token_id), nonce, &managed_address) .prepare_async() .run() .await; @@ -597,8 +587,8 @@ impl SysFuncCallsInteract { } async fn unset_roles(&mut self, address: &str, token_id: &str, roles: Vec) { - let converted_roles: Vec = roles.into_iter().map(EsdtLocalRole::from).collect(); - + let converted_roles: Vec = + roles.into_iter().map(EsdtLocalRole::from).collect(); println!("ROLES: {:?}", converted_roles); @@ -665,4 +655,30 @@ impl SysFuncCallsInteract { .run() .await; } + + async fn control_changes(&mut self, token_id: &str) { + self.interactor + .tx() + .from(&self.wallet_address) + .to(ESDTSystemSCAddress.to_managed_address()) + .gas(100_000_000u64) + .typed(ESDTSystemSCProxy) + .control_changes( + &TokenIdentifier::from(token_id), + &TokenPropertyArguments { + can_freeze: Some(true), + can_wipe: Some(true), + can_pause: Some(true), + can_transfer_create_role: Some(true), + can_mint: Some(true), + can_burn: Some(true), + can_change_owner: Some(true), + can_upgrade: Some(true), + can_add_special_roles: Some(true), + }, + ) + .prepare_async() + .run() + .await; + } } diff --git a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_cli.rs b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_cli.rs index f740ff3d30..3386feffff 100644 --- a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_cli.rs +++ b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_cli.rs @@ -25,20 +25,35 @@ pub enum InteractCliCommand { PauseToken(PauseTokenArgs), #[command(name = "unpause-token", about = "Unpauses a fungible token")] UnpauseToken(PauseTokenArgs), - #[command(name = "freeze-token", about = "Freezes a fungible token for an address")] + #[command( + name = "freeze-token", + about = "Freezes a fungible token for an address" + )] FreezeToken(FreezeTokenArgs), - #[command(name = "unfreeze-token", about = "Unfreezes a fungible token for an address")] + #[command( + name = "unfreeze-token", + about = "Unfreezes a fungible token for an address" + )] UnfreezeToken(FreezeTokenArgs), - #[command(name = "freeze-nft", about = "Freezes a non-fungible token for an address")] + #[command( + name = "freeze-nft", + about = "Freezes a non-fungible token for an address" + )] FreezeNFT(FreezeNFTArgs), - #[command(name = "unfreeze-nft", about = "Unfreezes a non-fungible token for an address")] + #[command( + name = "unfreeze-nft", + about = "Unfreezes a non-fungible token for an address" + )] UnfreezeNFT(FreezeNFTArgs), #[command(name = "wipe-token", about = "Wipes a fungible token for an address")] WipeToken(WipeTokenArgs), - #[command(name = "wipe-nft", about = "Freezes a non-fungible token for an address")] + #[command( + name = "wipe-nft", + about = "Freezes a non-fungible token for an address" + )] WipeNFT(WipeNFTArgs), - #[command(name = "issue-non-fungible-token", about = "Create a NFT Collection")] - IssueNFT(IssueNFTArgs), + #[command(name = "issue-nft-collection", about = "Create a NFT Collection")] + IssueNFTCollection(IssueNftCollectionArgs), #[command(name = "create-nft", about = "Issue a NFT")] CreateNFT(CreateNFTArgs), #[command( @@ -60,6 +75,8 @@ pub enum InteractCliCommand { TransferOwnership(TransferOwnershipArgs), #[command(name = "transfer-nft-create-role", about = "Transfers NFT create role")] TransferNftCreateRole(TransferNftCreateRoleArgs), + #[command(name = "control-changes", about = "Controls changes")] + ControlChanges(ControlChangesArgs), } #[derive(Clone, Debug, PartialEq, Eq, Args)] @@ -115,7 +132,7 @@ pub struct IssueFungibleArgs { } #[derive(Clone, Debug, PartialEq, Eq, Args)] -pub struct IssueNFTArgs { +pub struct IssueNftCollectionArgs { #[arg(short = 'c', long = "cost", default_value = "50000000000000000")] pub cost: RustBigUint, #[arg(short = 'd', long = "display-name")] @@ -193,7 +210,6 @@ pub struct TransferOwnershipArgs { } #[derive(Clone, Debug, PartialEq, Eq, Args)] - pub struct TransferNftCreateRoleArgs { #[arg(long = "token-id")] pub token_id: String, @@ -247,7 +263,6 @@ pub struct WipeNFTArgs { #[derive(Clone, Debug, PartialEq, Eq, Args)] pub struct CreateNFTArgs { - // token amount name hash royalities attributes uris #[arg(long = "token-id")] pub token_id: String, #[arg(short = 'a', long = "amount")] @@ -258,8 +273,10 @@ pub struct CreateNFTArgs { pub hash: String, #[arg(short = 'r', long = "royalities")] pub royalties: u64, - // #[long = "attributes")] - // pub attributes: String, - // #[arg(long = "uris")] - // pub uris: String, +} + +#[derive(Clone, Debug, PartialEq, Eq, Args)] +pub struct ControlChangesArgs { + #[arg(long = "token-id")] + pub token_id: String, } From 48a41f93c7fd2afbe83c0158866d704a26ea01e7 Mon Sep 17 00:00:00 2001 From: BiancaIalangi Date: Tue, 27 Aug 2024 12:56:25 +0300 Subject: [PATCH 54/92] unified - whitebox token_merge --- .../tests/token_merge_module_whitebox_test.rs | 966 ++++++++---------- 1 file changed, 420 insertions(+), 546 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 5cc2180d01..51cd7fa6df 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,5 +1,3 @@ -#![allow(deprecated)] // TODO: migrate to unified syntax at some point - use multiversx_sc_scenario::imports::*; use multiversx_sc_modules::token_merge::{ @@ -7,18 +5,15 @@ use multiversx_sc_modules::token_merge::{ }; use use_module::token_merge_mod_impl::{CustomAttributes, TokenMergeModImpl}; -const OWNER_ADDRESS_EXPR: &str = "address:owner"; -const USER_ADDRESS_EXPR: &str = "address:user"; +const OWNER_ADDRESS_EXPR: TestAddress = TestAddress::new("owner"); +const USER_ADDRESS_EXPR: TestAddress = TestAddress::new("user"); -const USE_MODULE_ADDRESS_EXPR: &str = "sc:use-module"; -const USE_MODULE_PATH_EXPR: &str = "mxsc:output/use-module.mxsc.json"; +const USE_MODULE_ADDRESS_EXPR: TestSCAddress = TestSCAddress::new("use-module"); +const USE_MODULE_PATH_EXPR: MxscPath = MxscPath::new("mxsc:output/use-module.mxsc.json"); -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 MERGED_TOKEN_ID_EXPR: TestTokenIdentifier = TestTokenIdentifier::new("MERGED-123456"); +const NFT_TOKEN_ID_EXPR: TestTokenIdentifier = TestTokenIdentifier::new("NFT-123456"); +const FUNGIBLE_TOKEN_ID_EXPR: TestTokenIdentifier = TestTokenIdentifier::new("FUN-123456"); const NFT_AMOUNT: u64 = 1; const FUNGIBLE_AMOUNT: u64 = 100; @@ -43,561 +38,462 @@ fn world() -> ScenarioWorld { fn test_token_merge() { 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(), ]; - - 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, 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| { + let first_uris = FIRST_URIS + .iter() + .map(|first_uri| managed_buffer!(first_uri)) + .collect(); + let second_uris = SECOND_URIS + .iter() + .map(|second_uri| managed_buffer!(second_uri)) + .collect(); + + world.account(OWNER_ADDRESS_EXPR).nonce(1); + world + .account(USER_ADDRESS_EXPR) + .nonce(1) + .esdt_balance(FUNGIBLE_TOKEN_ID_EXPR, FUNGIBLE_AMOUNT) + .esdt_nft_all_properties( + NFT_TOKEN_ID_EXPR, + FIRST_NFT_NONCE, + NFT_AMOUNT, + managed_buffer!(FIRST_ATTRIBUTES), + FIRST_ROYALTIES, + None::
, + (), + first_uris, + ) + .esdt_nft_all_properties( + NFT_TOKEN_ID_EXPR, + SECOND_NFT_NONCE, + NFT_AMOUNT, + managed_buffer!(SECOND_ATTRIBUTES), + SECOND_ROYALTIES, + None::
, + (), + second_uris, + ); + + world + .account(USE_MODULE_ADDRESS_EXPR) + .nonce(1) + .code(USE_MODULE_PATH_EXPR) + .owner(OWNER_ADDRESS_EXPR) + .esdt_roles(MERGED_TOKEN_ID_EXPR, roles); + + world + .tx() + .from(OWNER_ADDRESS_EXPR) + .to(USE_MODULE_ADDRESS_EXPR) + .whitebox(use_module::contract_obj, |sc| { sc.merged_token() - .set_token_id(managed_token_id!(MERGED_TOKEN_ID)); + .set_token_id(MERGED_TOKEN_ID_EXPR.to_token_identifier()); let _ = sc .mergeable_tokens_whitelist() - .insert(managed_token_id!(NFT_TOKEN_ID)); + .insert(NFT_TOKEN_ID_EXPR.to_token_identifier()); let _ = sc .mergeable_tokens_whitelist() - .insert(managed_token_id!(FUNGIBLE_TOKEN_ID)); - }, - ); + .insert(FUNGIBLE_TOKEN_ID_EXPR.to_token_identifier()); + }); // merge two NFTs let nft_transfers = vec![ - TxESDT { - esdt_token_identifier: NFT_TOKEN_ID.into(), - nonce: FIRST_NFT_NONCE.into(), - esdt_value: NFT_AMOUNT.into(), - }, - TxESDT { - esdt_token_identifier: NFT_TOKEN_ID.into(), - nonce: SECOND_NFT_NONCE.into(), - esdt_value: NFT_AMOUNT.into(), - }, + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT), + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT), ]; - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new() - .from(USER_ADDRESS_EXPR) - .multi_esdt_transfer(nft_transfers), - |sc| { + world + .tx() + .from(USER_ADDRESS_EXPR) + .to(USE_MODULE_ADDRESS_EXPR) + .multi_esdt(nft_transfers) + .whitebox(use_module::contract_obj, |sc| { let merged_token = sc.merge_tokens_endpoint(); assert_eq!( merged_token.token_identifier, - managed_token_id!(MERGED_TOKEN_ID) + MERGED_TOKEN_ID_EXPR.to_token_identifier() ); 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), + &USER_ADDRESS_EXPR.to_managed_address(), + &MERGED_TOKEN_ID_EXPR.to_token_identifier(), 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 expected_uri = [ + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT), + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT), + ]; let actual_uri = MergedTokenInstances::decode_from_first_uri(&merged_token_data.uris); - assert_eq!(expected_uri, actual_uri.into_instances()); + + for (expected, uri) in expected_uri.iter().zip(actual_uri.into_instances()) { + let token_identifier_string = uri.token_identifier.to_string(); + let actual_transfer = TestEsdtTransfer( + TestTokenIdentifier::new(&token_identifier_string), + uri.token_nonce, + uri.amount.to_u64().unwrap(), + ); + + assert_eq!(expected, &actual_transfer); + } 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_account(USER_ADDRESS_EXPR) + .esdt_nft_balance_and_attributes(MERGED_TOKEN_ID_EXPR, 1, NFT_AMOUNT, &Empty); - world.check_state_step(CheckStateStep::new().put_account( - USE_MODULE_ADDRESS_EXPR, - CheckAccount::new().esdt_nft_balance_and_attributes( + world + .check_account(USE_MODULE_ADDRESS_EXPR) + .esdt_nft_balance_and_attributes( NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT, - Some(FIRST_ATTRIBUTES), - ), - )); + FIRST_ATTRIBUTES, + ); - world.check_state_step(CheckStateStep::new().put_account( - USE_MODULE_ADDRESS_EXPR, - CheckAccount::new().esdt_nft_balance_and_attributes( + world + .check_account(USE_MODULE_ADDRESS_EXPR) + .esdt_nft_balance_and_attributes( NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT, - Some(SECOND_ATTRIBUTES), - ), - )); + 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| { + world + .tx() + .from(USER_ADDRESS_EXPR) + .to(USE_MODULE_ADDRESS_EXPR) + .payment(TestEsdtTransfer(MERGED_TOKEN_ID_EXPR, 1, NFT_AMOUNT)) + .whitebox(use_module::contract_obj, |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( + let expected_output_tokens = vec![ + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT), + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT), + ]; + assert_eq!(output_tokens, expected_output_tokens.into()); + }); + + world + .check_account(USER_ADDRESS_EXPR) + .esdt_nft_balance_and_attributes( NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT, - Some(FIRST_ATTRIBUTES), - ), - )); + FIRST_ATTRIBUTES, + ); - world.check_state_step(CheckStateStep::new().put_account( - USER_ADDRESS_EXPR, - CheckAccount::new().esdt_nft_balance_and_attributes( + world + .check_account(USER_ADDRESS_EXPR) + .esdt_nft_balance_and_attributes( NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT, - Some(SECOND_ATTRIBUTES), - ), - )); + SECOND_ATTRIBUTES, + ); // merge the NFT with fungible let esdt_transfers = vec![ - TxESDT { - esdt_token_identifier: NFT_TOKEN_ID.into(), - nonce: FIRST_NFT_NONCE.into(), - esdt_value: NFT_AMOUNT.into(), - }, - TxESDT { - esdt_token_identifier: FUNGIBLE_TOKEN_ID.into(), - nonce: 0u64.into(), - esdt_value: FUNGIBLE_AMOUNT.into(), - }, + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT), + TestEsdtTransfer(FUNGIBLE_TOKEN_ID_EXPR, 0u64, FUNGIBLE_AMOUNT), ]; - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new() - .from(USER_ADDRESS_EXPR) - .multi_esdt_transfer(esdt_transfers), - |sc| { + world + .tx() + .from(USER_ADDRESS_EXPR) + .to(USE_MODULE_ADDRESS_EXPR) + .multi_esdt(esdt_transfers) + .whitebox(use_module::contract_obj, |sc| { let merged_token = sc.merge_tokens_endpoint(); assert_eq!( merged_token.token_identifier, - managed_token_id!(MERGED_TOKEN_ID) + MERGED_TOKEN_ID_EXPR.to_token_identifier() ); 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), + &USER_ADDRESS_EXPR.to_managed_address(), + &MERGED_TOKEN_ID_EXPR.to_token_identifier(), 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 expected_uri = [ + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT), + TestEsdtTransfer(FUNGIBLE_TOKEN_ID_EXPR, 0, FUNGIBLE_AMOUNT), + ]; let actual_uri = MergedTokenInstances::decode_from_first_uri(&merged_token_data.uris); - assert_eq!(expected_uri, actual_uri.into_instances()); + for (expected, uri) in expected_uri.iter().zip(actual_uri.into_instances()) { + let token_identifier_string = uri.token_identifier.to_string(); + let actual_transfer = TestEsdtTransfer( + TestTokenIdentifier::new(&token_identifier_string), + uri.token_nonce, + uri.amount.to_u64().unwrap(), + ); + + assert_eq!(expected, &actual_transfer); + } 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, - ), - )); + }); + + world + .check_account(USER_ADDRESS_EXPR) + .esdt_nft_balance_and_attributes(MERGED_TOKEN_ID_EXPR, 2, NFT_AMOUNT, &Empty); // merge NFT with an already merged token let combined_transfers = vec![ - TxESDT { - esdt_token_identifier: NFT_TOKEN_ID.into(), - nonce: SECOND_NFT_NONCE.into(), - esdt_value: NFT_AMOUNT.into(), - }, - TxESDT { - esdt_token_identifier: MERGED_TOKEN_ID.into(), - nonce: 2u64.into(), - esdt_value: NFT_AMOUNT.into(), - }, + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT), + TestEsdtTransfer(MERGED_TOKEN_ID_EXPR, 2u64, NFT_AMOUNT), ]; - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new() - .from(USER_ADDRESS_EXPR) - .multi_esdt_transfer(combined_transfers), - |sc| { + world + .tx() + .from(USER_ADDRESS_EXPR) + .to(USE_MODULE_ADDRESS_EXPR) + .multi_esdt(combined_transfers) + .whitebox(use_module::contract_obj, |sc| { let merged_token = sc.merge_tokens_endpoint(); assert_eq!( merged_token.token_identifier, - managed_token_id!(MERGED_TOKEN_ID) + MERGED_TOKEN_ID_EXPR.to_token_identifier() ); 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), + &USER_ADDRESS_EXPR.to_managed_address(), + &MERGED_TOKEN_ID_EXPR.into(), 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 expected_uri = [ + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT), + TestEsdtTransfer(FUNGIBLE_TOKEN_ID_EXPR, 0, FUNGIBLE_AMOUNT), + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT), + ]; let actual_uri = MergedTokenInstances::decode_from_first_uri(&merged_token_data.uris); - assert_eq!(expected_uri, actual_uri.into_instances()); + for (expected, uri) in expected_uri.iter().zip(actual_uri.into_instances()) { + let token_identifier_string = uri.token_identifier.to_string(); + let actual_transfer = TestEsdtTransfer( + TestTokenIdentifier::new(&token_identifier_string), + uri.token_nonce, + uri.amount.to_u64().unwrap(), + ); + + assert_eq!(expected, &actual_transfer); + } 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| { + }); + + world + .check_account(USER_ADDRESS_EXPR) + .esdt_nft_balance_and_attributes(MERGED_TOKEN_ID_EXPR, 3, NFT_AMOUNT, &Empty); + + world + .tx() + .from(USER_ADDRESS_EXPR) + .to(USE_MODULE_ADDRESS_EXPR) + .payment(TestEsdtTransfer(MERGED_TOKEN_ID_EXPR, 3, NFT_AMOUNT)) + .whitebox(use_module::contract_obj, |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( + let expected_output_tokens = vec![ + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT), + TestEsdtTransfer(FUNGIBLE_TOKEN_ID_EXPR, 0, FUNGIBLE_AMOUNT), + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT), + ]; + + assert_eq!(output_tokens, expected_output_tokens.into()); + }); + + world + .check_account(USER_ADDRESS_EXPR) + .esdt_nft_balance_and_attributes( NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT, - Some(FIRST_ATTRIBUTES), - ), - )); + FIRST_ATTRIBUTES, + ); - world.check_state_step(CheckStateStep::new().put_account( - USER_ADDRESS_EXPR, - CheckAccount::new().esdt_nft_balance_and_attributes( + world + .check_account(USER_ADDRESS_EXPR) + .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), - )); + SECOND_ATTRIBUTES, + ); + + world + .check_account(USER_ADDRESS_EXPR) + .esdt_balance(FUNGIBLE_TOKEN_ID_EXPR, FUNGIBLE_AMOUNT); } #[test] fn test_partial_split() { 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(), ]; - - 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, 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| { + let first_uris = FIRST_URIS + .iter() + .map(|first_uri| managed_buffer!(first_uri)) + .collect(); + let second_uris = SECOND_URIS + .iter() + .map(|second_uri| managed_buffer!(second_uri)) + .collect(); + + world.account(OWNER_ADDRESS_EXPR).nonce(1); + world + .account(USER_ADDRESS_EXPR) + .nonce(1) + .esdt_balance(FUNGIBLE_TOKEN_ID_EXPR, FUNGIBLE_AMOUNT) + .esdt_nft_all_properties( + NFT_TOKEN_ID_EXPR, + FIRST_NFT_NONCE, + NFT_AMOUNT, + managed_buffer!(FIRST_ATTRIBUTES), + FIRST_ROYALTIES, + None::, + (), + first_uris, + ) + .esdt_nft_all_properties( + NFT_TOKEN_ID_EXPR, + SECOND_NFT_NONCE, + NFT_AMOUNT, + managed_buffer!(SECOND_ATTRIBUTES), + SECOND_ROYALTIES, + None::, + (), + second_uris, + ); + + world + .account(USE_MODULE_ADDRESS_EXPR) + .nonce(1) + .code(USE_MODULE_PATH_EXPR) + .owner(OWNER_ADDRESS_EXPR) + .esdt_roles(MERGED_TOKEN_ID_EXPR, roles); + + world + .tx() + .from(OWNER_ADDRESS_EXPR) + .to(USE_MODULE_ADDRESS_EXPR) + .whitebox(use_module::contract_obj, |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)); - }, - ); + .set_token_id(MERGED_TOKEN_ID_EXPR.to_token_identifier()); + sc.mergeable_tokens_whitelist() + .insert(NFT_TOKEN_ID_EXPR.to_token_identifier()); + sc.mergeable_tokens_whitelist() + .insert(FUNGIBLE_TOKEN_ID_EXPR.to_token_identifier()); + }); // merge 2 NFTs and a fungible token let esdt_transfers = vec![ - TxESDT { - esdt_token_identifier: NFT_TOKEN_ID.into(), - nonce: FIRST_NFT_NONCE.into(), - esdt_value: NFT_AMOUNT.into(), - }, - TxESDT { - esdt_token_identifier: NFT_TOKEN_ID.into(), - nonce: SECOND_NFT_NONCE.into(), - esdt_value: NFT_AMOUNT.into(), - }, - TxESDT { - esdt_token_identifier: FUNGIBLE_TOKEN_ID.into(), - nonce: 0u64.into(), - esdt_value: FUNGIBLE_AMOUNT.into(), - }, + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT), + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT), + TestEsdtTransfer(FUNGIBLE_TOKEN_ID_EXPR, 0u64, FUNGIBLE_AMOUNT), ]; - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new() - .from(USER_ADDRESS_EXPR) - .multi_esdt_transfer(esdt_transfers), - |sc| { + world + .tx() + .from(USER_ADDRESS_EXPR) + .to(USE_MODULE_ADDRESS_EXPR) + .multi_esdt(esdt_transfers) + .whitebox(use_module::contract_obj, |sc| { let merged_token = sc.merge_tokens_endpoint(); assert_eq!( merged_token.token_identifier, - managed_token_id!(MERGED_TOKEN_ID) + MERGED_TOKEN_ID_EXPR.to_token_identifier() ); 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), + &USER_ADDRESS_EXPR.to_managed_address(), + &MERGED_TOKEN_ID_EXPR.to_token_identifier(), 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 expected_uri = [ + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT), + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT), + TestEsdtTransfer(FUNGIBLE_TOKEN_ID_EXPR, 0, FUNGIBLE_AMOUNT), + ]; let actual_uri = MergedTokenInstances::decode_from_first_uri(&merged_token_data.uris); - assert_eq!(expected_uri, actual_uri.into_instances()); - }, - ); + for (expected, uri) in expected_uri.iter().zip(actual_uri.into_instances()) { + let token_identifier_string = uri.token_identifier.to_string(); + let actual_transfer = TestEsdtTransfer( + TestTokenIdentifier::new(&token_identifier_string), + uri.token_nonce, + uri.amount.to_u64().unwrap(), + ); + + assert_eq!(expected, &actual_transfer); + } + }); // 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| { + world + .tx() + .from(USER_ADDRESS_EXPR) + .to(USE_MODULE_ADDRESS_EXPR) + .payment(TestEsdtTransfer(MERGED_TOKEN_ID_EXPR, 1, NFT_AMOUNT)) + .whitebox(use_module::contract_obj, |sc| { let mut tokens_to_remove = ManagedVec::new(); tokens_to_remove.push(EsdtTokenPayment::new( - managed_token_id!(FUNGIBLE_TOKEN_ID), + FUNGIBLE_TOKEN_ID_EXPR.to_token_identifier(), 0, managed_biguint!(40), )); - let output_payments = sc.split_token_partial_endpoint(tokens_to_remove); + 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), + FUNGIBLE_TOKEN_ID_EXPR.to_token_identifier(), 0, managed_biguint!(40), )); expected_output_payments.push(EsdtTokenPayment::new( - managed_token_id!(MERGED_TOKEN_ID), + MERGED_TOKEN_ID_EXPR.to_token_identifier(), 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| { + world + .tx() + .from(USER_ADDRESS_EXPR) + .to(USE_MODULE_ADDRESS_EXPR) + .payment(TestEsdtTransfer(MERGED_TOKEN_ID_EXPR, 2, NFT_AMOUNT)) + .whitebox(use_module::contract_obj, |sc| { let mut tokens_to_remove = ManagedVec::new(); tokens_to_remove.push(EsdtTokenPayment::new( - managed_token_id!(NFT_TOKEN_ID), + NFT_TOKEN_ID_EXPR.to_token_identifier(), FIRST_NFT_NONCE, managed_biguint!(NFT_AMOUNT), )); @@ -605,12 +501,12 @@ fn test_partial_split() { let mut expected_output_payments = ManagedVec::new(); expected_output_payments.push(EsdtTokenPayment::new( - managed_token_id!(NFT_TOKEN_ID), + NFT_TOKEN_ID_EXPR.to_token_identifier(), FIRST_NFT_NONCE, managed_biguint!(NFT_AMOUNT), )); expected_output_payments.push(EsdtTokenPayment::new( - managed_token_id!(MERGED_TOKEN_ID), + MERGED_TOKEN_ID_EXPR.to_token_identifier(), 3, managed_biguint!(NFT_AMOUNT), )); @@ -618,112 +514,102 @@ fn test_partial_split() { // 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), + &USER_ADDRESS_EXPR.to_managed_address(), + &MERGED_TOKEN_ID_EXPR.to_token_identifier(), 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 expected_uri = [ + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT), + TestEsdtTransfer(FUNGIBLE_TOKEN_ID_EXPR, 0, FUNGIBLE_AMOUNT - 40), + ]; let actual_uri = MergedTokenInstances::decode_from_first_uri(&merged_token_data.uris); - assert_eq!(expected_uri, actual_uri.into_instances()); + for (expected, uri) in expected_uri.iter().zip(actual_uri.into_instances()) { + let token_identifier_string = uri.token_identifier.to_string(); + let actual_transfer = TestEsdtTransfer( + TestTokenIdentifier::new(&token_identifier_string), + uri.token_nonce, + uri.amount.to_u64().unwrap(), + ); + + assert_eq!(expected, &actual_transfer); + } assert_eq!( merged_token_data.royalties, managed_biguint!(SECOND_ROYALTIES) ); - }, - ); + }); } #[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(), ]; - 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, 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| { + let first_uris = FIRST_URIS + .iter() + .map(|first_uri| managed_buffer!(first_uri)) + .collect(); + let second_uris = SECOND_URIS + .iter() + .map(|second_uri| managed_buffer!(second_uri)) + .collect(); + world.account(OWNER_ADDRESS_EXPR).nonce(1); + world + .account(USER_ADDRESS_EXPR) + .nonce(1) + .esdt_balance(FUNGIBLE_TOKEN_ID_EXPR, FUNGIBLE_AMOUNT) + .esdt_nft_all_properties( + NFT_TOKEN_ID_EXPR, + FIRST_NFT_NONCE, + NFT_AMOUNT, + managed_buffer!(FIRST_ATTRIBUTES), + FIRST_ROYALTIES, + None::, + (), + first_uris, + ) + .esdt_nft_all_properties( + NFT_TOKEN_ID_EXPR, + SECOND_NFT_NONCE, + NFT_AMOUNT, + managed_buffer!(SECOND_ATTRIBUTES), + SECOND_ROYALTIES, + None::, + (), + second_uris, + ); + world + .account(USE_MODULE_ADDRESS_EXPR) + .nonce(1) + .code(USE_MODULE_PATH_EXPR) + .owner(OWNER_ADDRESS_EXPR) + .esdt_roles(MERGED_TOKEN_ID_EXPR, roles); + + world + .tx() + .from(OWNER_ADDRESS_EXPR) + .to(USE_MODULE_ADDRESS_EXPR) + .whitebox(use_module::contract_obj, |sc| { sc.merged_token() - .set_token_id(managed_token_id!(MERGED_TOKEN_ID)); + .set_token_id(MERGED_TOKEN_ID_EXPR.to_token_identifier()); let _ = sc .mergeable_tokens_whitelist() - .insert(managed_token_id!(NFT_TOKEN_ID)); + .insert(NFT_TOKEN_ID_EXPR.to_token_identifier()); let _ = sc .mergeable_tokens_whitelist() - .insert(managed_token_id!(FUNGIBLE_TOKEN_ID)); - }, - ); + .insert(FUNGIBLE_TOKEN_ID_EXPR.to_token_identifier()); + }); // merge two NFTs let nft_transfers = vec![ - TxESDT { - esdt_token_identifier: NFT_TOKEN_ID.into(), - nonce: FIRST_NFT_NONCE.into(), - esdt_value: NFT_AMOUNT.into(), - }, - TxESDT { - esdt_token_identifier: NFT_TOKEN_ID.into(), - nonce: SECOND_NFT_NONCE.into(), - esdt_value: NFT_AMOUNT.into(), - }, + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT), + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT), ]; let expected_attributes = CustomAttributes { @@ -731,39 +617,41 @@ fn test_custom_attributes() { second: 10u64, }; - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new() - .from(USER_ADDRESS_EXPR) - .multi_esdt_transfer(nft_transfers), - |sc| { + world + .tx() + .from(USER_ADDRESS_EXPR) + .to(USE_MODULE_ADDRESS_EXPR) + .multi_esdt(nft_transfers) + .whitebox(use_module::contract_obj, |sc| { let merged_token = sc.merge_tokens_custom_attributes_endpoint(); assert_eq!( merged_token.token_identifier, - managed_token_id!(MERGED_TOKEN_ID) + MERGED_TOKEN_ID_EXPR.to_token_identifier() ); 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), + &USER_ADDRESS_EXPR.to_managed_address(), + &MERGED_TOKEN_ID_EXPR.to_token_identifier(), 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 expected_uri = [ + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT), + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT), + ]; let actual_uri = MergedTokenInstances::decode_from_first_uri(&merged_token_data.uris); - assert_eq!(expected_uri, actual_uri.into_instances()); + for (expected, uri) in expected_uri.iter().zip(actual_uri.into_instances()) { + let token_identifier_string = uri.token_identifier.to_string(); + let actual_transfer = TestEsdtTransfer( + TestTokenIdentifier::new(&token_identifier_string), + uri.token_nonce, + uri.amount.to_u64().unwrap(), + ); + + assert_eq!(expected, &actual_transfer); + } let actual_attributes: CustomAttributes = merged_token_data.decode_attributes(); assert_eq!(expected_attributes, actual_attributes); @@ -772,40 +660,26 @@ fn test_custom_attributes() { 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_account(USER_ADDRESS_EXPR) + .esdt_nft_balance_and_attributes(MERGED_TOKEN_ID_EXPR, 1, NFT_AMOUNT, expected_attributes); - world.check_state_step(CheckStateStep::new().put_account( - USE_MODULE_ADDRESS_EXPR, - CheckAccount::new().esdt_nft_balance_and_attributes( + world + .check_account(USE_MODULE_ADDRESS_EXPR) + .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( + FIRST_ATTRIBUTES, + ); + world + .check_account(USE_MODULE_ADDRESS_EXPR) + .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() + SECOND_ATTRIBUTES, + ); } From e2daf814025e18ddb82d47e4eed652caf98111b8 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Tue, 27 Aug 2024 15:06:47 +0300 Subject: [PATCH 55/92] verify_bls_aggregated_signature test fix --- ..._verify_bls_aggregated_signature.scen.json | 37 ++++++++++++------- .../basic-features/src/crypto_features.rs | 2 +- .../contract_base/wrappers/crypto_wrapper.rs | 4 +- 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_aggregated_signature.scen.json b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_aggregated_signature.scen.json index 46617194c5..d8e46f2389 100644 --- a/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_aggregated_signature.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_aggregated_signature.scen.json @@ -19,22 +19,28 @@ }, { "step": "scCall", - "id": "1", + "id": "bls multi - ok", "tx": { "from": "address:an_account", "to": "sc:basic-features-crypto", "function": "verify_bls_aggregated_signature", "arguments": [ - "0x9cfb3532e21737e8f9eec99b04f000b27ec277d2477d881273ea07d3af96dc3e153878ed002bcd10e8320242caab49024b8c934b437b17e743b9706757f0e7b2e9fb28295d7f82af8875e0776ae8918c25206519b3f73dcbbd53cafeb5cec716", - "0x6d65737361676530", - "0x84737000b07fbce9b649449f9de6aae76347f5bb5eefcd017f53e874601ccf5f96c9b4ca5f85ea5f6ef6243c38c9ab99" + [ + "nested:0x95f1d96b582f35294eb7dd4589b158e108e1d94cd0dd71ef16140e9b37126ec52dac6f57397f1e041acd7bb77df1d214f9f894e3b7fbf7abeaabc9fab8ff5c2ef05f9841322f301fdb900ac59479c334ac76a2d4ff992cd49bc9b530c25ee293", + "nested:0x97aa2862418eb4ea74fddcb511eef9b771e07ff901e7e6abb35847a4bb81e58f189fc9bce4186c6129014fb43002300e959702ef4b9d0c32ebe4d795457095d65b5414efb36edbb8dc66d84a445a92472d4a31cedd4700d5ebb885eb11d3430b", + "nested:0x37b73265936a2aaafe652a4dd451a1851c2dbbb32208604787479b31033e2a354615562ea2a5488f9134843362477a139050a0e798dd5ce0f01b35b8d473454ae99633aadde9237f84c87eb366144cca4de3d2cc6acc35e522a3294bf1186800", + "nested:0xf46c10d114dcd3019dd4bcd4152fda678c56144eb177c67a6411213b86e206e4e56a9aad1eab0313b13031fda046d715ec4a02612b083dfae0d82a23b643e1a89756c0df3d65c27e87a9c1289628d1a8404f0668a3d87c7451ba1c78fc452693", + "nested:0xaa0a97917df9240c537c89e873d7baa5ce1796e8fedfb23cf682b80fa19b8baae35af3754f9b8149985cb2a1fbda0f02c2942d2c99d9af556c9a5e90b8170e6a96379a45dd69351abfb814a16b5665abb7ddb8b096ee9f273de81845cda9728a" + ], + "str:message0", + "0xae12858363e8caa5b398d3febdd7bc01bc2fae1fef8f486ff4d84a5f3342f2d38085904eb10b73c0879a45d23585ce8f" ], "gasLimit": "50,000,000", "gasPrice": "0" }, "expect": { "out": [ - "0x01" + "true" ], "status": "", "logs": "*", @@ -44,24 +50,29 @@ }, { "step": "scCall", - "id": "2", + "id": "bls multi - fail", "tx": { "from": "address:an_account", "to": "sc:basic-features-crypto", "function": "verify_bls_aggregated_signature", "arguments": [ - "0x9cfb3532e21737e8f9eec99b04f000b27ec277d2477d881273ea07d3af96dc3e153878ed002bcd10e8320242caab49024b8c934b437b17e743b9706757f0e7b2e9fb28295d7f82af8875e0776ae8918c25206519b3f73dcbbd53cafeb5cec716", - "0x6d657373616765323133", - "0x84737000b07fbce9b649449f9de6aae76347f5bb5eefcd017f53e874601ccf5f96c9b4ca5f85ea5f6ef6243c38c9ab99" + [ + "nested:0x95f1d96b582f35294eb7dd4589b158e108e1d94cd0dd71ef16140e9b37126ec52dac6f57397f1e041acd7bb77df1d214f9f894e3b7fbf7abeaabc9fab8ff5c2ef05f9841322f301fdb900ac59479c334ac76a2d4ff992cd49bc9b530c25ee293", + "nested:0x97aa2862418eb4ea74fddcb511eef9b771e07ff901e7e6abb35847a4bb81e58f189fc9bce4186c6129014fb43002300e959702ef4b9d0c32ebe4d795457095d65b5414efb36edbb8dc66d84a445a92472d4a31cedd4700d5ebb885eb11d3430b", + "nested:0x37b73265936a2aaafe652a4dd451a1851c2dbbb32208604787479b31033e2a354615562ea2a5488f9134843362477a139050a0e798dd5ce0f01b35b8d473454ae99633aadde9237f84c87eb366144cca4de3d2cc6acc35e522a3294bf1186800", + "nested:0xf46c10d114dcd3019dd4bcd4152fda678c56144eb177c67a6411213b86e206e4e56a9aad1eab0313b13031fda046d715ec4a02612b083dfae0d82a23b643e1a89756c0df3d65c27e87a9c1289628d1a8404f0668a3d87c7451ba1c78fc452693", + "nested:0xaa0a97917df9240c537c89e873d7baa5ce1796e8fedfb23cf682b80fa19b8baae35af3754f9b8149985cb2a1fbda0f02c2942d2c99d9af556c9a5e90b8170e6a96379a45dd69351abfb814a16b5665abb7ddb8b096ee9f273de81845cda9728a" + ], + "str:message0", + "0x0012858363e8caa5b398d3febdd7bc01bc2fae1fef8f486ff4d84a5f3342f2d38085904eb10b73c0879a45d23585ce8f" ], "gasLimit": "50,000,000", "gasPrice": "0" }, "expect": { - "out": [ - "0x00" - ], - "status": "", + "out": [], + "status": "10", + "message": "str:err blsSignatureDeserialize 0012858363e8caa5b398d3febdd7bc01bc2fae1fef8f486ff4d84a5f3342f2d38085904eb10b73c0879a45d23585ce8f", "logs": "*", "gas": "*", "refund": "*" diff --git a/contracts/feature-tests/basic-features/src/crypto_features.rs b/contracts/feature-tests/basic-features/src/crypto_features.rs index 4a9c7dbb6f..8da0c83984 100644 --- a/contracts/feature-tests/basic-features/src/crypto_features.rs +++ b/contracts/feature-tests/basic-features/src/crypto_features.rs @@ -92,7 +92,7 @@ pub trait CryptoFeatures { #[label("crypto-ei-1.4")] fn verify_bls_aggregated_signature( &self, - key: ManagedBuffer, + key: ManagedVec, message: ManagedBuffer, signature: ManagedBuffer, ) -> bool { diff --git a/framework/base/src/contract_base/wrappers/crypto_wrapper.rs b/framework/base/src/contract_base/wrappers/crypto_wrapper.rs index 76b8fcd996..eb98f93a56 100644 --- a/framework/base/src/contract_base/wrappers/crypto_wrapper.rs +++ b/framework/base/src/contract_base/wrappers/crypto_wrapper.rs @@ -5,7 +5,7 @@ use crate::{ use_raw_handle, CryptoApi, CryptoApiImpl, StaticVarApiImpl, KECCAK256_RESULT_LEN, SHA256_RESULT_LEN, }, - types::{ManagedBuffer, ManagedByteArray, ManagedType, MessageHashType}, + types::{ManagedBuffer, ManagedByteArray, ManagedType, ManagedVec, MessageHashType}, }; #[derive(Default)] @@ -158,7 +158,7 @@ where pub fn verify_bls_aggregated_signature( &self, - key: &ManagedBuffer, + key: &ManagedVec>, message: &ManagedBuffer, signature: &ManagedBuffer, ) -> bool { From 29c5bec8ecacf5e7240ee4c0910ac5659f1345d7 Mon Sep 17 00:00:00 2001 From: Andrei Vasilescu Date: Tue, 27 Aug 2024 18:28:58 +0300 Subject: [PATCH 56/92] fixed ReturnsNewTokenIdentifier + sugestive prints in interactor functions --- framework/snippets/src/network_response.rs | 23 ++++--- .../interact/src/basic_interact.rs | 66 ++++++++++++++----- .../interact/src/basic_interact_cli.rs | 8 +-- 3 files changed, 68 insertions(+), 29 deletions(-) diff --git a/framework/snippets/src/network_response.rs b/framework/snippets/src/network_response.rs index d505e7a525..4d828e12c7 100644 --- a/framework/snippets/src/network_response.rs +++ b/framework/snippets/src/network_response.rs @@ -103,25 +103,31 @@ fn process_new_deployed_address(tx: &TransactionOnNetwork) -> Option
{ } fn process_new_issued_token_identifier(tx: &TransactionOnNetwork) -> Option { + let original_tx_data = String::from_utf8(base64_decode(tx.data.as_ref().unwrap())).unwrap(); + for scr in tx.smart_contract_results.iter() { if scr.sender.to_bech32_string().unwrap() != ESDTSystemSCAddress.to_bech32_string() { continue; } - let Some(prev_tx) = tx + let prev_tx_data: &str = if let Some(prev_tx) = tx .smart_contract_results .iter() .find(|e| e.hash == scr.prev_tx_hash) - else { + { + prev_tx.data.as_ref() + } else if &scr.prev_tx_hash == tx.hash.as_ref().unwrap() { + &original_tx_data + } else { continue; }; - let is_issue_fungible = prev_tx.data.starts_with("issue@"); - let is_issue_semi_fungible = prev_tx.data.starts_with("issueSemiFungible@"); - let is_issue_non_fungible = prev_tx.data.starts_with("issueNonFungible@"); - let is_register_meta_esdt = prev_tx.data.starts_with("registerMetaESDT@"); + let is_issue_fungible = prev_tx_data.starts_with("issue@"); + let is_issue_semi_fungible = prev_tx_data.starts_with("issueSemiFungible@"); + let is_issue_non_fungible = prev_tx_data.starts_with("issueNonFungible@"); + let is_register_meta_esdt = prev_tx_data.starts_with("registerMetaESDT@"); let is_register_and_set_all_roles_esdt = - prev_tx.data.starts_with("registerAndSetAllRoles@"); + prev_tx_data.starts_with("registerAndSetAllRoles@"); if !is_issue_fungible && !is_issue_semi_fungible @@ -135,12 +141,11 @@ fn process_new_issued_token_identifier(tx: &TransactionOnNetwork) -> Option { basic_interact - .set_role(&args.token_id, args.roles.clone()) + .set_roles(&args.token_id, args.roles.clone()) .await; }, Some(basic_interact_cli::InteractCliCommand::Burn(args)) => { @@ -97,7 +97,7 @@ async fn main() { }, Some(basic_interact_cli::InteractCliCommand::IssueFungible(args)) => { basic_interact - ._issue_fungible_token( + .issue_fungible_token( args.cost.clone(), &args.display_name, &args.ticker, @@ -106,9 +106,9 @@ async fn main() { ) .await; }, - Some(basic_interact_cli::InteractCliCommand::IssueSft(args)) => { + Some(basic_interact_cli::InteractCliCommand::IssueSftCollection(args)) => { basic_interact - .issue_semi_fungible_token(args.cost.clone(), &args.display_name, &args.ticker) + .issue_semi_fungible_collection(args.cost.clone(), &args.display_name, &args.ticker) .await; }, Some(basic_interact_cli::InteractCliCommand::MintSft(args)) => { @@ -181,7 +181,7 @@ impl SysFuncCallsInteract { } } - async fn _issue_fungible_token( + async fn issue_fungible_token( &mut self, issue_cost: RustBigUint, token_display_name: &str, @@ -189,7 +189,9 @@ impl SysFuncCallsInteract { initial_supply: RustBigUint, num_decimals: usize, ) { - self.interactor + println!("Issuing fungible token..."); + let res = self + .interactor .tx() .from(&self.wallet_address) .to(ESDTSystemSCAddress.to_managed_address()) @@ -212,9 +214,12 @@ impl SysFuncCallsInteract { can_add_special_roles: true, }, ) + .returns(ReturnsNewTokenIdentifier) .prepare_async() .run() .await; + + println!("TOKEN ID: {:?}", res); } async fn issue_non_fungible_collection( @@ -223,7 +228,9 @@ impl SysFuncCallsInteract { token_display_name: &str, token_ticker: &str, ) { - self.interactor + println!("Issuing NFT Collection..."); + let nft_collection_id = self + .interactor .tx() .from(&self.wallet_address) .to(ESDTSystemSCAddress.to_managed_address()) @@ -243,18 +250,23 @@ impl SysFuncCallsInteract { can_add_special_roles: true, }, ) + .returns(ReturnsNewTokenIdentifier) .prepare_async() .run() .await; + + println!("NFT Collection ID: {:?}", nft_collection_id); } - async fn issue_semi_fungible_token( + async fn issue_semi_fungible_collection( &mut self, issue_cost: RustBigUint, token_display_name: &str, token_ticker: &str, ) { - self.interactor + println!("Issuing SFT Collection..."); + let sft_collection_id = self + .interactor .tx() .from(&self.wallet_address) .to(ESDTSystemSCAddress.to_managed_address()) @@ -274,9 +286,12 @@ impl SysFuncCallsInteract { can_add_special_roles: true, }, ) + .returns(ReturnsNewTokenIdentifier) .prepare_async() .run() .await; + + println!("SFT Collection ID: {:?}", sft_collection_id); } async fn issue_token( @@ -287,6 +302,9 @@ impl SysFuncCallsInteract { num_decimals: usize, token_type: EsdtTokenType, ) { + println!( + "Registering token... Don't forget to mint afterwards in order to receive the tokens!" + ); let token_id = self .interactor .tx() @@ -301,20 +319,20 @@ impl SysFuncCallsInteract { token_type, num_decimals, ) - .returns(ReturnsResultUnmanaged) + .returns(ReturnsNewTokenIdentifier) .prepare_async() .run() .await; - println!("TOKEN ID: {:?}", token_id.to_string()); + println!("TOKEN ID: {:?}", token_id); } - async fn set_role(&mut self, token_id: &str, roles: Vec) { + async fn set_roles(&mut self, token_id: &str, roles: Vec) { let wallet_address = &self.wallet_address.clone().into_address(); let converted_roles: Vec = roles.into_iter().map(EsdtLocalRole::from).collect(); - println!("ROLES: {:?}", converted_roles); + println!("Setting the following roles: {:?}", converted_roles); self.interactor .tx() @@ -370,6 +388,7 @@ impl SysFuncCallsInteract { token_ticker: &str, num_decimals: usize, ) { + println!("Registering meta ESDT... Don't forget to mint afterwards in order to receive the tokens!"); let meta_esdt = self .interactor .tx() @@ -392,15 +411,16 @@ impl SysFuncCallsInteract { can_add_special_roles: true, }, ) - .returns(ReturnsResultUnmanaged) + .returns(ReturnsNewTokenIdentifier) .prepare_async() .run() .await; - println!("META ESDT: {:?}", meta_esdt.to_string()); + println!("Meta-ESDT ID: {:?}", meta_esdt); } async fn change_sft_meta_esdt(&mut self, token_id: &str, num_decimals: usize) { + println!("Changing SFT to Meta-ESDT..."); self.interactor .tx() .from(&self.wallet_address) @@ -414,6 +434,7 @@ impl SysFuncCallsInteract { } async fn mint_token(&mut self, token_id: &str, amount: RustBigUint) { + println!("Minting tokens..."); self.interactor .tx() .from(&self.wallet_address) @@ -427,6 +448,7 @@ impl SysFuncCallsInteract { } async fn burn_token(&mut self, token_id: &str, amount: RustBigUint) { + println!("Burning tokens..."); self.interactor .tx() .from(&self.wallet_address) @@ -440,6 +462,7 @@ impl SysFuncCallsInteract { } async fn pause_token(&mut self, token_id: &str) { + println!("Pausing token..."); self.interactor .tx() .from(&self.wallet_address) @@ -453,6 +476,7 @@ impl SysFuncCallsInteract { } async fn unpause_token(&mut self, token_id: &str) { + println!("Unpausing token..."); self.interactor .tx() .from(&self.wallet_address) @@ -466,6 +490,7 @@ impl SysFuncCallsInteract { } async fn freeze_token(&mut self, token_id: &str, address: &str) { + println!("Freezing token..."); let address = Bech32Address::from_bech32_string(address.to_string()).to_address(); let managed_address: ManagedAddress = ManagedAddress::from_address(&address); self.interactor @@ -481,6 +506,7 @@ impl SysFuncCallsInteract { } async fn unfreeze_token(&mut self, token_id: &str, address: &str) { + println!("Unfreezing token..."); let address = Bech32Address::from_bech32_string(address.to_string()).to_address(); let managed_address: ManagedAddress = ManagedAddress::from_address(&address); self.interactor @@ -496,6 +522,7 @@ impl SysFuncCallsInteract { } async fn freeze_nft(&mut self, token_id: &str, nonce: u64, address: &str) { + println!("Freezing NFT/SFT/Meta-ESDT..."); let address = Bech32Address::from_bech32_string(address.to_string()).to_address(); let managed_address: ManagedAddress = ManagedAddress::from_address(&address); self.interactor @@ -511,6 +538,7 @@ impl SysFuncCallsInteract { } async fn unfreeze_nft(&mut self, token_id: &str, nonce: u64, address: &str) { + println!("Unfreezing NFT/SFT/Meta-ESDT..."); let address = Bech32Address::from_bech32_string(address.to_string()).to_address(); let managed_address: ManagedAddress = ManagedAddress::from_address(&address); self.interactor @@ -526,6 +554,7 @@ impl SysFuncCallsInteract { } async fn wipe_token(&mut self, token_id: &str, address: &str) { + println!("Wiping token..."); let address = Bech32Address::from_bech32_string(address.to_string()).to_address(); let managed_address: ManagedAddress = ManagedAddress::from_address(&address); self.interactor @@ -541,6 +570,7 @@ impl SysFuncCallsInteract { } async fn wipe_nft(&mut self, token_id: &str, nonce: u64, address: &str) { + println!("Wiping NFT/SFT/Meta-ESDT..."); let address = Bech32Address::from_bech32_string(address.to_string()).to_address(); let managed_address: ManagedAddress = ManagedAddress::from_address(&address); self.interactor @@ -563,6 +593,7 @@ impl SysFuncCallsInteract { royalties: u64, hash: &str, ) { + println!("Minting NFT..."); self.interactor .tx() .from(&self.wallet_address) @@ -590,7 +621,7 @@ impl SysFuncCallsInteract { let converted_roles: Vec = roles.into_iter().map(EsdtLocalRole::from).collect(); - println!("ROLES: {:?}", converted_roles); + println!("Unsetting the following roles: {:?}", converted_roles); let bech32_addr = Bech32Address::from_bech32_string(address.to_string()); let addr = bech32_addr.to_address(); @@ -613,6 +644,7 @@ impl SysFuncCallsInteract { } async fn transfer_ownership(&mut self, token_id: &str, new_owner: &str) { + println!("Transferring token ownership..."); let bech32_addr = Bech32Address::from_bech32_string(new_owner.to_string()); let addr = bech32_addr.to_address(); let managed_addr: ManagedAddress = ManagedAddress::from_address(&addr); @@ -630,6 +662,7 @@ impl SysFuncCallsInteract { } async fn transfer_nft_create_role(&mut self, token_id: &str, old_owner: &str, new_owner: &str) { + println!("Transferring NFT create role..."); let bech32_addr_new_owner = Bech32Address::from_bech32_string(new_owner.to_string()); let addr_new_owner = bech32_addr_new_owner.to_address(); let managed_addr_new_owner: ManagedAddress = @@ -657,6 +690,7 @@ impl SysFuncCallsInteract { } async fn control_changes(&mut self, token_id: &str) { + println!("Control changes"); self.interactor .tx() .from(&self.wallet_address) diff --git a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_cli.rs b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_cli.rs index 3386feffff..5cb356b3d8 100644 --- a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_cli.rs +++ b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_cli.rs @@ -61,8 +61,8 @@ pub enum InteractCliCommand { about = "Issues fungible tokens and sends them to your wallet" )] IssueFungible(IssueFungibleArgs), - #[command(name = "issue-sft", about = "Issues a SFT")] - IssueSft(IssueSftArgs), + #[command(name = "issue-sft-collection", about = "Issues a SFT")] + IssueSftCollection(IssueSftArgs), #[command(name = "mint-sft", about = "Mints a SFT")] MintSft(MintSFTArgs), #[command(name = "register-meta-esdt", about = "Registers a meta ESDT")] @@ -145,7 +145,7 @@ pub struct IssueNftCollectionArgs { pub struct IssueSftArgs { #[arg(short = 'c', long = "cost", default_value = "50000000000000000")] pub cost: RustBigUint, - #[arg(long = "display-name")] + #[arg(short = 'd', long = "display-name")] pub display_name: String, #[arg(long = "token-ticker")] pub ticker: String, @@ -175,7 +175,7 @@ pub struct MintSFTArgs { pub struct RegisterMetaEsdtArgs { #[arg(short = 'c', long = "cost", default_value = "50000000000000000")] pub cost: RustBigUint, - #[arg(long = "display-name")] + #[arg(short = 'd', long = "display-name")] pub display_name: String, #[arg(long = "token-ticker")] pub ticker: String, From b13757be1ab878b6c1320770855476bcc74a0d8e Mon Sep 17 00:00:00 2001 From: BiancaIalangi Date: Wed, 28 Aug 2024 12:37:06 +0300 Subject: [PATCH 57/92] unified - compare expected_uri with serialized merged_token_data uri --- .../tests/token_merge_module_whitebox_test.rs | 176 +++++++++--------- 1 file changed, 88 insertions(+), 88 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 51cd7fa6df..4b40f656c9 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 @@ -124,23 +124,21 @@ fn test_token_merge() { &MERGED_TOKEN_ID_EXPR.to_token_identifier(), 1, ); - let expected_uri = [ - TestEsdtTransfer(NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT), - TestEsdtTransfer(NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT), - ]; + let expected_uri = ArrayVec::from([ + EsdtTokenPayment::new( + NFT_TOKEN_ID_EXPR.to_token_identifier(), + FIRST_NFT_NONCE, + managed_biguint!(NFT_AMOUNT), + ), + EsdtTokenPayment::new( + NFT_TOKEN_ID_EXPR.to_token_identifier(), + SECOND_NFT_NONCE, + managed_biguint!(NFT_AMOUNT), + ), + ]); let actual_uri = MergedTokenInstances::decode_from_first_uri(&merged_token_data.uris); - - for (expected, uri) in expected_uri.iter().zip(actual_uri.into_instances()) { - let token_identifier_string = uri.token_identifier.to_string(); - let actual_transfer = TestEsdtTransfer( - TestTokenIdentifier::new(&token_identifier_string), - uri.token_nonce, - uri.amount.to_u64().unwrap(), - ); - - assert_eq!(expected, &actual_transfer); - } + assert_eq!(expected_uri, *actual_uri.into_instances()); assert_eq!( merged_token_data.royalties, @@ -228,22 +226,21 @@ fn test_token_merge() { &MERGED_TOKEN_ID_EXPR.to_token_identifier(), 2, ); - let expected_uri = [ - TestEsdtTransfer(NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT), - TestEsdtTransfer(FUNGIBLE_TOKEN_ID_EXPR, 0, FUNGIBLE_AMOUNT), - ]; + let expected_uri = ArrayVec::from([ + EsdtTokenPayment::new( + NFT_TOKEN_ID_EXPR.to_token_identifier(), + FIRST_NFT_NONCE, + managed_biguint!(NFT_AMOUNT), + ), + EsdtTokenPayment::new( + FUNGIBLE_TOKEN_ID_EXPR.to_token_identifier(), + 0, + managed_biguint!(FUNGIBLE_AMOUNT), + ), + ]); let actual_uri = MergedTokenInstances::decode_from_first_uri(&merged_token_data.uris); - for (expected, uri) in expected_uri.iter().zip(actual_uri.into_instances()) { - let token_identifier_string = uri.token_identifier.to_string(); - let actual_transfer = TestEsdtTransfer( - TestTokenIdentifier::new(&token_identifier_string), - uri.token_nonce, - uri.amount.to_u64().unwrap(), - ); - - assert_eq!(expected, &actual_transfer); - } + assert_eq!(expected_uri, *actual_uri.into_instances()); assert_eq!( merged_token_data.royalties, @@ -280,23 +277,26 @@ fn test_token_merge() { &MERGED_TOKEN_ID_EXPR.into(), 3, ); - let expected_uri = [ - TestEsdtTransfer(NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT), - TestEsdtTransfer(FUNGIBLE_TOKEN_ID_EXPR, 0, FUNGIBLE_AMOUNT), - TestEsdtTransfer(NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT), - ]; + let expected_uri = ArrayVec::from([ + EsdtTokenPayment::new( + NFT_TOKEN_ID_EXPR.to_token_identifier(), + FIRST_NFT_NONCE, + managed_biguint!(NFT_AMOUNT), + ), + EsdtTokenPayment::new( + FUNGIBLE_TOKEN_ID_EXPR.to_token_identifier(), + 0, + managed_biguint!(FUNGIBLE_AMOUNT), + ), + EsdtTokenPayment::new( + NFT_TOKEN_ID_EXPR.to_token_identifier(), + SECOND_NFT_NONCE, + managed_biguint!(NFT_AMOUNT), + ), + ]); let actual_uri = MergedTokenInstances::decode_from_first_uri(&merged_token_data.uris); - for (expected, uri) in expected_uri.iter().zip(actual_uri.into_instances()) { - let token_identifier_string = uri.token_identifier.to_string(); - let actual_transfer = TestEsdtTransfer( - TestTokenIdentifier::new(&token_identifier_string), - uri.token_nonce, - uri.amount.to_u64().unwrap(), - ); - - assert_eq!(expected, &actual_transfer); - } + assert_eq!(expected_uri, *actual_uri.into_instances()); assert_eq!( merged_token_data.royalties, @@ -436,23 +436,26 @@ fn test_partial_split() { &MERGED_TOKEN_ID_EXPR.to_token_identifier(), 1, ); - let expected_uri = [ - TestEsdtTransfer(NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT), - TestEsdtTransfer(NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT), - TestEsdtTransfer(FUNGIBLE_TOKEN_ID_EXPR, 0, FUNGIBLE_AMOUNT), - ]; + let expected_uri = ArrayVec::from([ + EsdtTokenPayment::new( + NFT_TOKEN_ID_EXPR.to_token_identifier(), + FIRST_NFT_NONCE, + managed_biguint!(NFT_AMOUNT), + ), + EsdtTokenPayment::new( + NFT_TOKEN_ID_EXPR.to_token_identifier(), + SECOND_NFT_NONCE, + managed_biguint!(NFT_AMOUNT), + ), + EsdtTokenPayment::new( + FUNGIBLE_TOKEN_ID_EXPR.to_token_identifier(), + 0, + managed_biguint!(FUNGIBLE_AMOUNT), + ), + ]); let actual_uri = MergedTokenInstances::decode_from_first_uri(&merged_token_data.uris); - for (expected, uri) in expected_uri.iter().zip(actual_uri.into_instances()) { - let token_identifier_string = uri.token_identifier.to_string(); - let actual_transfer = TestEsdtTransfer( - TestTokenIdentifier::new(&token_identifier_string), - uri.token_nonce, - uri.amount.to_u64().unwrap(), - ); - - assert_eq!(expected, &actual_transfer); - } + assert_eq!(expected_uri, *actual_uri.into_instances()); }); // split part of the fungible token @@ -518,22 +521,21 @@ fn test_partial_split() { &MERGED_TOKEN_ID_EXPR.to_token_identifier(), 3, ); - let expected_uri = [ - TestEsdtTransfer(NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT), - TestEsdtTransfer(FUNGIBLE_TOKEN_ID_EXPR, 0, FUNGIBLE_AMOUNT - 40), - ]; + let expected_uri = ArrayVec::from([ + EsdtTokenPayment::new( + NFT_TOKEN_ID_EXPR.to_token_identifier(), + SECOND_NFT_NONCE, + managed_biguint!(NFT_AMOUNT), + ), + EsdtTokenPayment::new( + FUNGIBLE_TOKEN_ID_EXPR.to_token_identifier(), + 0, + managed_biguint!(FUNGIBLE_AMOUNT - 40), + ), + ]); let actual_uri = MergedTokenInstances::decode_from_first_uri(&merged_token_data.uris); - for (expected, uri) in expected_uri.iter().zip(actual_uri.into_instances()) { - let token_identifier_string = uri.token_identifier.to_string(); - let actual_transfer = TestEsdtTransfer( - TestTokenIdentifier::new(&token_identifier_string), - uri.token_nonce, - uri.amount.to_u64().unwrap(), - ); - - assert_eq!(expected, &actual_transfer); - } + assert_eq!(expected_uri, *actual_uri.into_instances()); assert_eq!( merged_token_data.royalties, @@ -636,22 +638,20 @@ fn test_custom_attributes() { &MERGED_TOKEN_ID_EXPR.to_token_identifier(), 1, ); - let expected_uri = [ - TestEsdtTransfer(NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT), - TestEsdtTransfer(NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT), - ]; - + let expected_uri = ArrayVec::from([ + EsdtTokenPayment::new( + NFT_TOKEN_ID_EXPR.to_token_identifier(), + FIRST_NFT_NONCE, + managed_biguint!(NFT_AMOUNT), + ), + EsdtTokenPayment::new( + NFT_TOKEN_ID_EXPR.to_token_identifier(), + SECOND_NFT_NONCE, + managed_biguint!(NFT_AMOUNT), + ), + ]); let actual_uri = MergedTokenInstances::decode_from_first_uri(&merged_token_data.uris); - for (expected, uri) in expected_uri.iter().zip(actual_uri.into_instances()) { - let token_identifier_string = uri.token_identifier.to_string(); - let actual_transfer = TestEsdtTransfer( - TestTokenIdentifier::new(&token_identifier_string), - uri.token_nonce, - uri.amount.to_u64().unwrap(), - ); - - assert_eq!(expected, &actual_transfer); - } + assert_eq!(expected_uri, *actual_uri.into_instances()); let actual_attributes: CustomAttributes = merged_token_data.decode_attributes(); assert_eq!(expected_attributes, actual_attributes); From 3a1ee56d9bb907c4d462d1a83acbc2fd3eaf17ae Mon Sep 17 00:00:00 2001 From: JustEatAnApple Date: Wed, 28 Aug 2024 12:55:34 +0300 Subject: [PATCH 58/92] Modified the adder interactor example to work with keystore-signing Co-authored-by: Andrei Vasilescu --- contracts/examples/adder/interact/alice.json | 23 +++++++++++++++++++ .../adder/interact/src/basic_interact.rs | 4 +++- sdk/core/src/wallet.rs | 11 ++++----- 3 files changed, 31 insertions(+), 7 deletions(-) create mode 100644 contracts/examples/adder/interact/alice.json diff --git a/contracts/examples/adder/interact/alice.json b/contracts/examples/adder/interact/alice.json new file mode 100644 index 0000000000..8f1a81514e --- /dev/null +++ b/contracts/examples/adder/interact/alice.json @@ -0,0 +1,23 @@ +{ + "version": 4, + "kind": "secretKey", + "id": "f2c5e236-9039-46cd-8df5-1efcd9466ead", + "address": "0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", + "bech32": "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th", + "crypto": { + "ciphertext": "45de5198c6c477725abc17d26c6b5fc88b1ff22a67a8c4784b297d426d351cf5c891a4c92d63e04cf23f602f660b7b606ed1c5293c85ff40216d9e53c9a07c23", + "cipherparams": { + "iv": "d6442fb1d4c49106152baeb3c539ed2c" + }, + "cipher": "aes-128-ctr", + "kdf": "scrypt", + "kdfparams": { + "dklen": 32, + "salt": "dd69d88742b9d27a0438a4554d4180b070d9af224ea8ff8225fdf74c8e272adb", + "n": 4096, + "r": 8, + "p": 1 + }, + "mac": "b277984f71d0e9b4a6597911775c0ee6d598002645b29f22021e595c2725d204" + } +} diff --git a/contracts/examples/adder/interact/src/basic_interact.rs b/contracts/examples/adder/interact/src/basic_interact.rs index 262eb13631..4765ec6fbe 100644 --- a/contracts/examples/adder/interact/src/basic_interact.rs +++ b/contracts/examples/adder/interact/src/basic_interact.rs @@ -65,7 +65,9 @@ impl AdderInteract { let adder_owner_address = interactor.register_wallet(Wallet::from_pem_file("adder-owner.pem").unwrap()); - let wallet_address = interactor.register_wallet(test_wallets::mike()); + // PASSWORD: "alice" + let wallet_address = interactor + .register_wallet(Wallet::from_keystore_secret("alice.json", "alice").unwrap()); Self { interactor, diff --git a/sdk/core/src/wallet.rs b/sdk/core/src/wallet.rs index bf1362a314..e197c13c02 100644 --- a/sdk/core/src/wallet.rs +++ b/sdk/core/src/wallet.rs @@ -156,12 +156,11 @@ impl Wallet { (private_key_str, public_key_str) } - pub fn from_keystore_secret(file_path: &str) -> Result { - let decyption_params = - Self::validate_keystore_password(file_path, Self::get_keystore_password()) - .unwrap_or_else(|e| { - panic!("Error: {:?}", e); - }); + pub fn from_keystore_secret(file_path: &str, password: &str) -> Result { + let decyption_params = Self::validate_keystore_password(file_path, password.to_string()) + .unwrap_or_else(|e| { + panic!("Error: {:?}", e); + }); let priv_key = PrivateKey::from_hex_str( hex::encode(Self::decrypt_secret_key(decyption_params)).as_str(), )?; From 4928800dfe85e9d65c8aaf06f48edbffa441a931 Mon Sep 17 00:00:00 2001 From: JustEatAnApple Date: Wed, 28 Aug 2024 14:32:43 +0300 Subject: [PATCH 59/92] Password can now be passed either in terminal or as a string parameter Co-authored-by: Andrei Vasilescu --- contracts/examples/adder/interact/.gitignore | 1 + .../adder/interact/src/basic_interact.rs | 16 +++++++++---- sdk/core/src/data/keystore.rs | 7 ++++++ sdk/core/src/wallet.rs | 23 ++++++++++++++----- 4 files changed, 36 insertions(+), 11 deletions(-) diff --git a/contracts/examples/adder/interact/.gitignore b/contracts/examples/adder/interact/.gitignore index b2630809de..336fa10df0 100644 --- a/contracts/examples/adder/interact/.gitignore +++ b/contracts/examples/adder/interact/.gitignore @@ -1,5 +1,6 @@ # Pem files are used for interactions, but shouldn't be committed *.pem +*.json !adder-owner.pem # Temporary storage of deployed contract address, so we can preserve the context between executions. diff --git a/contracts/examples/adder/interact/src/basic_interact.rs b/contracts/examples/adder/interact/src/basic_interact.rs index 4765ec6fbe..abcaec4c00 100644 --- a/contracts/examples/adder/interact/src/basic_interact.rs +++ b/contracts/examples/adder/interact/src/basic_interact.rs @@ -7,7 +7,7 @@ use basic_interact_config::Config; use basic_interact_state::State; use clap::Parser; -use multiversx_sc_snippets::imports::*; +use multiversx_sc_snippets::{imports::*, sdk::data::keystore::InsertPassword}; const INTERACTOR_SCENARIO_TRACE_PATH: &str = "interactor_trace.scen.json"; @@ -66,8 +66,14 @@ impl AdderInteract { let adder_owner_address = interactor.register_wallet(Wallet::from_pem_file("adder-owner.pem").unwrap()); // PASSWORD: "alice" - let wallet_address = interactor - .register_wallet(Wallet::from_keystore_secret("alice.json", "alice").unwrap()); + // InsertPassword::Plaintext("alice".to_string()) || InsertPassword::StandardInput + let wallet_address = interactor.register_wallet( + Wallet::from_keystore_secret( + "alice.json", + InsertPassword::Plaintext("alice".to_string()), + ) + .unwrap(), + ); Self { interactor, @@ -243,5 +249,5 @@ async fn test() { basic_interact.deploy().await; basic_interact.add(1u32).await; - basic_interact.upgrade(7u32).await; -} + // basic_interact.upgrade(7u32).await; +} \ No newline at end of file diff --git a/sdk/core/src/data/keystore.rs b/sdk/core/src/data/keystore.rs index 1b3c656ef1..31e6b6538a 100644 --- a/sdk/core/src/data/keystore.rs +++ b/sdk/core/src/data/keystore.rs @@ -12,6 +12,13 @@ pub enum WalletError { InvalidKdf, InvalidCipher, } + +#[derive(Debug)] +pub enum InsertPassword { + Plaintext(String), + StandardInput, +} + #[derive(Debug, Serialize, Deserialize)] pub struct CryptoParams { pub iv: String, diff --git a/sdk/core/src/wallet.rs b/sdk/core/src/wallet.rs index e197c13c02..df9b9dc43a 100644 --- a/sdk/core/src/wallet.rs +++ b/sdk/core/src/wallet.rs @@ -156,13 +156,24 @@ impl Wallet { (private_key_str, public_key_str) } - pub fn from_keystore_secret(file_path: &str, password: &str) -> Result { - let decyption_params = Self::validate_keystore_password(file_path, password.to_string()) - .unwrap_or_else(|e| { - panic!("Error: {:?}", e); - }); + pub fn from_keystore_secret(file_path: &str, insert_password: InsertPassword) -> Result { + let decryption_params = match insert_password { + InsertPassword::Plaintext(password) => { + Self::validate_keystore_password(file_path, password.to_string()).unwrap_or_else( + |e| { + panic!("Error: {:?}", e); + }, + ) + }, + InsertPassword::StandardInput => { + Self::validate_keystore_password(file_path, Self::get_keystore_password()) + .unwrap_or_else(|e| { + panic!("Error: {:?}", e); + }) + }, + }; let priv_key = PrivateKey::from_hex_str( - hex::encode(Self::decrypt_secret_key(decyption_params)).as_str(), + hex::encode(Self::decrypt_secret_key(decryption_params)).as_str(), )?; Ok(Self { priv_key }) } From ca748ff88fc951a40d5a992f7e591d04750e43f6 Mon Sep 17 00:00:00 2001 From: JustEatAnApple Date: Wed, 28 Aug 2024 15:49:18 +0300 Subject: [PATCH 60/92] Decommented a line to showcase the upgrade failure Co-authored-by: Andrei Vasilescu --- contracts/examples/adder/interact/src/basic_interact.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/examples/adder/interact/src/basic_interact.rs b/contracts/examples/adder/interact/src/basic_interact.rs index abcaec4c00..0061b2a888 100644 --- a/contracts/examples/adder/interact/src/basic_interact.rs +++ b/contracts/examples/adder/interact/src/basic_interact.rs @@ -249,5 +249,5 @@ async fn test() { basic_interact.deploy().await; basic_interact.add(1u32).await; - // basic_interact.upgrade(7u32).await; + basic_interact.upgrade(7u32).await; } \ No newline at end of file From 6f41c77a4fb8f6796b86a5e28d46fe17e5a43e21 Mon Sep 17 00:00:00 2001 From: JustEatAnApple Date: Wed, 28 Aug 2024 16:55:32 +0300 Subject: [PATCH 61/92] Made the upgrade failure more clear Co-authored-by: Andrei Vasilescu --- .../adder/interact/src/basic_interact.rs | 49 +++++++++++++++++-- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/contracts/examples/adder/interact/src/basic_interact.rs b/contracts/examples/adder/interact/src/basic_interact.rs index 0061b2a888..a5e5fb4942 100644 --- a/contracts/examples/adder/interact/src/basic_interact.rs +++ b/contracts/examples/adder/interact/src/basic_interact.rs @@ -209,13 +209,43 @@ impl AdderInteract { println!("sum: {sum}"); } + async fn fail_upgrade(&mut self, new_value: u32) { + self.interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_adder_address()) + .gas(6_000_000) + .typed(adder_proxy::AdderProxy) + .upgrade(BigUint::from(new_value)) + .code_metadata(CodeMetadata::UPGRADEABLE) + .code(ADDER_CODE_PATH) + .with_result(ExpectError(4, "upgrade is allowed only for owner")) + .prepare_async() + .run() + .await; + + let sum = self + .interactor + .query() + .to(self.state.current_adder_address()) + .typed(adder_proxy::AdderProxy) + .sum() + .returns(ReturnsResultUnmanaged) + .prepare_async() + .run() + .await; + assert_ne!(sum, RustBigUint::from(new_value)); + + println!("Upgrade failed: upgrade is allowed only for owner"); + } + async fn upgrade(&mut self, new_value: u32) { let response = self .interactor .tx() - .from(&self.wallet_address) + .from(&self.adder_owner_address) .to(self.state.current_adder_address()) - .gas(3_000_000) + .gas(6_000_000) .typed(adder_proxy::AdderProxy) .upgrade(BigUint::from(new_value)) .code_metadata(CodeMetadata::UPGRADEABLE) @@ -243,11 +273,22 @@ impl AdderInteract { #[tokio::test] #[ignore = "run on demand"] -async fn test() { +async fn fail_upgrade_test() { + let mut basic_interact = AdderInteract::init().await; + + basic_interact.deploy().await; + basic_interact.add(1u32).await; + + basic_interact.fail_upgrade(7u32).await; +} + +#[tokio::test] +#[ignore = "run on demand"] +async fn upgrade_test() { let mut basic_interact = AdderInteract::init().await; basic_interact.deploy().await; basic_interact.add(1u32).await; basic_interact.upgrade(7u32).await; -} \ No newline at end of file +} From 5933f501839958bf3ab083a7313adca5e737044f Mon Sep 17 00:00:00 2001 From: JustEatAnApple Date: Wed, 28 Aug 2024 16:57:57 +0300 Subject: [PATCH 62/92] Updated gas prices Co-authored-by: Andrei Vasilescu --- contracts/examples/adder/interact/src/basic_interact.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/contracts/examples/adder/interact/src/basic_interact.rs b/contracts/examples/adder/interact/src/basic_interact.rs index a5e5fb4942..e1dc1b3dec 100644 --- a/contracts/examples/adder/interact/src/basic_interact.rs +++ b/contracts/examples/adder/interact/src/basic_interact.rs @@ -101,7 +101,7 @@ impl AdderInteract { .interactor .tx() .from(&self.adder_owner_address) - .gas(3_000_000) + .gas(6_000_000) .typed(adder_proxy::AdderProxy) .init(0u32) .code(ADDER_CODE_PATH) @@ -131,7 +131,7 @@ impl AdderInteract { .typed(adder_proxy::AdderProxy) .init(0u32) .code(ADDER_CODE_PATH) - .gas(3_000_000) + .gas(6_000_000) .returns(ReturnsNewBech32Address) }); } @@ -159,7 +159,7 @@ impl AdderInteract { .to(self.state.current_adder_address()) .typed(adder_proxy::AdderProxy) .add(value) - .gas(3_000_000) + .gas(6_000_000) }); } @@ -184,7 +184,7 @@ impl AdderInteract { .tx() .from(&self.wallet_address) .to(self.state.current_adder_address()) - .gas(3_000_000) + .gas(6_000_000) .typed(adder_proxy::AdderProxy) .add(value) .prepare_async() From 804bf49ca0cc72c7053d7f21aa353d9209da2dbd Mon Sep 17 00:00:00 2001 From: Andrei Vasilescu Date: Wed, 28 Aug 2024 19:45:16 +0300 Subject: [PATCH 63/92] added README + small changes in interactor --- tools/interactor-system-func-calls/README.md | 75 +++++++++ .../interact/src/basic_interact.rs | 158 +++++++++++------- .../interact/src/basic_interact_cli.rs | 6 +- 3 files changed, 182 insertions(+), 57 deletions(-) create mode 100644 tools/interactor-system-func-calls/README.md diff --git a/tools/interactor-system-func-calls/README.md b/tools/interactor-system-func-calls/README.md new file mode 100644 index 0000000000..18d1501cf7 --- /dev/null +++ b/tools/interactor-system-func-calls/README.md @@ -0,0 +1,75 @@ +# System SC function calls interactor + +Fungible Tokens docs: https://docs.multiversx.com/tokens/fungible-tokens/ +NFT/SFT/Meta-ESDT docs: https://docs.multiversx.com/tokens/nft-tokens/ + +### Functions: + +- `issue_fungible_token`: Issues a fungible token, it registers the token and sends the initial supply to your wallet +- `issue_non_fungible_collection`: Issues an NFT Collection +- `issue_semi_fungible_collection`: Issues an SFT Collection +- `issue_token`: Registers any kind of token (Fungible/NFT/SFT/Meta-ESDT) and sets all the roles for it. This function doesn't transfer any tokens to your wallet +- `set_roles`: Sets the roles for your address over a specified token ID +- `mint_sft`: Mints an SFT/Meta-ESDT corresponding to a collection +- `register_meta_esdt`: Registers a Meta-ESDT token +- `change_sft_meta_esdt`: Changes an SFT to a Meta-ESDT +- `mint_token`: Mints a fungible token +- `burn_token`: Burns a token +- `pause_token`: Pauses all the transfers for a token +- `unpause_token`: Reverse function of `pause_token` +- `freeze_token`: Freezes a token for an address +- `unfreeze_token`: Reverse function of `freeze_token` +- `freeze_nft`: Freezes an NFT/SFT/Meta-ESDT token for an address +- `unfreeze_nft`: Reverse function of `freeze_nft` +- `wipe_token`: Wipes a token from an address +- `wipe_nft`: Wipes an NFT/SFT/Meta-ESDT token from an address +- `mint_nft`: Mints an NFT corresponding to a collection +- `unset roles`: Unsets the roles for an address over a specified tokenID +- `transfer_ownership`: Transfers the ownership of your token to another address +- `transfer_nft_create_role`: Transfers the NFT Create role to a new address +- `control_changes`: Sets/Unsets properties of a specified tokenID + +### How to use tips + +#### Token types for `issue_token` function + +For CLI use, insert one of the numbers below for the `token-type` parameter + +- 0 => `Fungible` +- 1 => `NonFungible` +- 2 => `SemiFungible` +- 3 => `Meta` +- any other number => `Invalid` + +#### Set/Unset roles + +Before trying to make any kind of interaction with a token (e.g. Mint, Burn, Transfer) you should set the neccessary roles, even if you are the owner of the token. For CLI use, insert one or more numbers from below for the `roles` parameter, each corresponding to a role, each separated by one comma `e.g. --roles 1,2,8` + +- 1 => `Mint` +- 2 => `Burn` +- 3 => `NftCreate` +- 4 => `NftAddQuantity` +- 5 => `NftBurn` +- 6 => `NftAddUri` +- 7 => `NftUpdateAttributes` +- 8 => `Transfer` +- any other number => `None` + +#### Issue fungible token + +- Method 1: `issue_fungible_token` (set the token properties inside the function) +- Method 2: `issue_token`-> `set_roles` (**Mint** role needed for minting the tokens) -> `mint_token` to receive the tokens in your wallet + +#### Issue NFT Collection + Mint an NFT + +- `issue_non_fungible_collection`/`issue_token` -> `set_roles` (**NFTCreate** role needed for minting) -> Mint an NFT by calling `mint_nft` + +#### Issue SFT Collection + +- Issue Collection: `issue_semi_fungible_collection`/`issue_token` -> `set_roles` (**NFTCreate** role needed for minting) -> Mint the amount of SFTs wantes by calling `mint_sft` + +### Register a Meta-ESDT + +- `register_meta_esdt` -> `set_roles`(**NFTCreate**) -> `mint_sft` to mint the Meta-ESDT + +By using `set_roles`(**NFTAddQuantity**) -> `mint_token` you can add quantity to a Meta-ESDT/SFT with a specified nonce diff --git a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs index b7cbb4ee3e..fb08fd587b 100644 --- a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs +++ b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs @@ -30,17 +30,24 @@ async fn main() { }, Some(basic_interact_cli::InteractCliCommand::Mint(args)) => { basic_interact - .mint_token(&args.token_id, args.amount.clone()) + .mint_token(&args.token_id, args.nonce, args.amount.clone()) .await; }, Some(basic_interact_cli::InteractCliCommand::SetRoles(args)) => { basic_interact - .set_roles(&args.token_id, args.roles.clone()) + .set_roles( + &args.token_id, + args.roles + .clone() + .into_iter() + .map(EsdtLocalRole::from) + .collect(), + ) .await; }, Some(basic_interact_cli::InteractCliCommand::Burn(args)) => { basic_interact - .burn_token(&args.token_id, args.amount.clone()) + .burn_token(&args.token_id, args.nonce, args.amount.clone()) .await; }, Some(basic_interact_cli::InteractCliCommand::PauseToken(args)) => { @@ -51,32 +58,53 @@ async fn main() { }, Some(basic_interact_cli::InteractCliCommand::FreezeToken(args)) => { basic_interact - .freeze_token(&args.token_id, &args.address) + .freeze_token( + &args.token_id, + Bech32Address::from_bech32_string(args.address.clone()), + ) .await; }, Some(basic_interact_cli::InteractCliCommand::UnfreezeToken(args)) => { basic_interact - .unfreeze_token(&args.token_id, &args.address) + .unfreeze_token( + &args.token_id, + Bech32Address::from_bech32_string(args.address.clone()), + ) .await; }, Some(basic_interact_cli::InteractCliCommand::FreezeNFT(args)) => { basic_interact - .freeze_nft(&args.token_id, args.nft_nonce, &args.address) + .freeze_nft( + &args.token_id, + args.nft_nonce, + Bech32Address::from_bech32_string(args.address.clone()), + ) .await; }, Some(basic_interact_cli::InteractCliCommand::UnfreezeNFT(args)) => { basic_interact - .unfreeze_nft(&args.token_id, args.nft_nonce, &args.address) + .unfreeze_nft( + &args.token_id, + args.nft_nonce, + Bech32Address::from_bech32_string(args.address.clone()), + ) .await; }, Some(basic_interact_cli::InteractCliCommand::WipeToken(args)) => { basic_interact - .wipe_token(&args.token_id, &args.address) + .wipe_token( + &args.token_id, + Bech32Address::from_bech32_string(args.address.clone()), + ) .await; }, Some(basic_interact_cli::InteractCliCommand::WipeNFT(args)) => { basic_interact - .wipe_nft(&args.token_id, args.nft_nonce, &args.address) + .wipe_nft( + &args.token_id, + args.nft_nonce, + Bech32Address::from_bech32_string(args.address.clone()), + ) .await; }, Some(basic_interact_cli::InteractCliCommand::IssueNFTCollection(args)) => { @@ -86,7 +114,7 @@ async fn main() { }, Some(basic_interact_cli::InteractCliCommand::CreateNFT(args)) => { basic_interact - .create_nft( + .mint_nft( &args.token_id, args.amount.clone(), &args.name, @@ -117,7 +145,7 @@ async fn main() { &args.token_id, args.amount.clone(), &args.name, - args.royalties.clone(), + args.royalties, &args.hash, ) .await; @@ -139,7 +167,15 @@ async fn main() { }, Some(basic_interact_cli::InteractCliCommand::UnsetRoles(args)) => { basic_interact - .unset_roles(&args.address, &args.token_id, args.roles.clone()) + .unset_roles( + Bech32Address::from_bech32_string(args.address.clone()), + &args.token_id, + args.roles + .clone() + .into_iter() + .map(EsdtLocalRole::from) + .collect(), + ) .await; }, Some(basic_interact_cli::InteractCliCommand::TransferOwnership(args)) => { @@ -172,7 +208,8 @@ impl SysFuncCallsInteract { let config = Config::load_config(); let mut interactor = Interactor::new(config.gateway()).await; - let wallet_address = interactor.register_wallet(test_wallets::alice()); + let wallet_address = + interactor.register_wallet(Wallet::from_pem_file("wallet.pem").unwrap()); Self { interactor, @@ -302,9 +339,7 @@ impl SysFuncCallsInteract { num_decimals: usize, token_type: EsdtTokenType, ) { - println!( - "Registering token... Don't forget to mint afterwards in order to receive the tokens!" - ); + println!("Registering token..."); let token_id = self .interactor .tx() @@ -327,12 +362,12 @@ impl SysFuncCallsInteract { println!("TOKEN ID: {:?}", token_id); } - async fn set_roles(&mut self, token_id: &str, roles: Vec) { + async fn set_roles(&mut self, token_id: &str, roles: Vec) { let wallet_address = &self.wallet_address.clone().into_address(); - let converted_roles: Vec = - roles.into_iter().map(EsdtLocalRole::from).collect(); + // let converted_roles: Vec = + // roles.into_iter().map(EsdtLocalRole::from).collect(); - println!("Setting the following roles: {:?}", converted_roles); + println!("Setting the following roles: {:?}", roles); self.interactor .tx() @@ -340,10 +375,10 @@ impl SysFuncCallsInteract { .to(ESDTSystemSCAddress.to_managed_address()) .gas(100_000_000u64) .typed(ESDTSystemSCProxy) - .set_special_roles::>( + .set_special_roles( &ManagedAddress::from_address(wallet_address), &TokenIdentifier::from(token_id), - converted_roles.into_iter(), + roles.into_iter(), ) .prepare_async() .run() @@ -355,9 +390,11 @@ impl SysFuncCallsInteract { token_id: &str, amount: RustBigUint, name: &str, - royalties: RustBigUint, + royalties: u64, hash: &str, ) { + println!("Minting SFT..."); + self.interactor .tx() .from(&self.wallet_address) @@ -388,7 +425,7 @@ impl SysFuncCallsInteract { token_ticker: &str, num_decimals: usize, ) { - println!("Registering meta ESDT... Don't forget to mint afterwards in order to receive the tokens!"); + println!("Registering meta ESDT..."); let meta_esdt = self .interactor .tx() @@ -433,7 +470,7 @@ impl SysFuncCallsInteract { .await; } - async fn mint_token(&mut self, token_id: &str, amount: RustBigUint) { + async fn mint_token(&mut self, token_id: &str, nonce: u64, amount: RustBigUint) { println!("Minting tokens..."); self.interactor .tx() @@ -441,13 +478,17 @@ impl SysFuncCallsInteract { .to(&self.wallet_address) .gas(100_000_000u64) .typed(UserBuiltinProxy) - .esdt_local_mint(&TokenIdentifier::from(token_id), 0, &BigUint::from(amount)) + .esdt_local_mint( + &TokenIdentifier::from(token_id), + nonce, + &BigUint::from(amount), + ) .prepare_async() .run() .await; } - async fn burn_token(&mut self, token_id: &str, amount: RustBigUint) { + async fn burn_token(&mut self, token_id: &str, nonce: u64, amount: RustBigUint) { println!("Burning tokens..."); self.interactor .tx() @@ -455,7 +496,11 @@ impl SysFuncCallsInteract { .to(&self.wallet_address) .gas(100_000_000u64) .typed(UserBuiltinProxy) - .esdt_local_burn(&TokenIdentifier::from(token_id), 0, &BigUint::from(amount)) + .esdt_local_burn( + &TokenIdentifier::from(token_id), + nonce, + &BigUint::from(amount), + ) .prepare_async() .run() .await; @@ -489,10 +534,10 @@ impl SysFuncCallsInteract { .await; } - async fn freeze_token(&mut self, token_id: &str, address: &str) { + async fn freeze_token(&mut self, token_id: &str, address: Bech32Address) { println!("Freezing token..."); - let address = Bech32Address::from_bech32_string(address.to_string()).to_address(); - let managed_address: ManagedAddress = ManagedAddress::from_address(&address); + let managed_address: ManagedAddress = + ManagedAddress::from_address(&address.to_address()); self.interactor .tx() .from(&self.wallet_address) @@ -505,10 +550,10 @@ impl SysFuncCallsInteract { .await; } - async fn unfreeze_token(&mut self, token_id: &str, address: &str) { + async fn unfreeze_token(&mut self, token_id: &str, address: Bech32Address) { println!("Unfreezing token..."); - let address = Bech32Address::from_bech32_string(address.to_string()).to_address(); - let managed_address: ManagedAddress = ManagedAddress::from_address(&address); + let managed_address: ManagedAddress = + ManagedAddress::from_address(&address.to_address()); self.interactor .tx() .from(&self.wallet_address) @@ -521,10 +566,10 @@ impl SysFuncCallsInteract { .await; } - async fn freeze_nft(&mut self, token_id: &str, nonce: u64, address: &str) { + async fn freeze_nft(&mut self, token_id: &str, nonce: u64, address: Bech32Address) { println!("Freezing NFT/SFT/Meta-ESDT..."); - let address = Bech32Address::from_bech32_string(address.to_string()).to_address(); - let managed_address: ManagedAddress = ManagedAddress::from_address(&address); + let managed_address: ManagedAddress = + ManagedAddress::from_address(&address.to_address()); self.interactor .tx() .from(&self.wallet_address) @@ -537,10 +582,10 @@ impl SysFuncCallsInteract { .await; } - async fn unfreeze_nft(&mut self, token_id: &str, nonce: u64, address: &str) { + async fn unfreeze_nft(&mut self, token_id: &str, nonce: u64, address: Bech32Address) { println!("Unfreezing NFT/SFT/Meta-ESDT..."); - let address = Bech32Address::from_bech32_string(address.to_string()).to_address(); - let managed_address: ManagedAddress = ManagedAddress::from_address(&address); + let managed_address: ManagedAddress = + ManagedAddress::from_address(&address.to_address()); self.interactor .tx() .from(&self.wallet_address) @@ -553,10 +598,10 @@ impl SysFuncCallsInteract { .await; } - async fn wipe_token(&mut self, token_id: &str, address: &str) { + async fn wipe_token(&mut self, token_id: &str, address: Bech32Address) { println!("Wiping token..."); - let address = Bech32Address::from_bech32_string(address.to_string()).to_address(); - let managed_address: ManagedAddress = ManagedAddress::from_address(&address); + let managed_address: ManagedAddress = + ManagedAddress::from_address(&address.to_address()); self.interactor .tx() .from(&self.wallet_address) @@ -569,10 +614,10 @@ impl SysFuncCallsInteract { .await; } - async fn wipe_nft(&mut self, token_id: &str, nonce: u64, address: &str) { + async fn wipe_nft(&mut self, token_id: &str, nonce: u64, address: Bech32Address) { println!("Wiping NFT/SFT/Meta-ESDT..."); - let address = Bech32Address::from_bech32_string(address.to_string()).to_address(); - let managed_address: ManagedAddress = ManagedAddress::from_address(&address); + let managed_address: ManagedAddress = + ManagedAddress::from_address(&address.to_address()); self.interactor .tx() .from(&self.wallet_address) @@ -585,7 +630,7 @@ impl SysFuncCallsInteract { .await; } - async fn create_nft( + async fn mint_nft( &mut self, token_id: &str, amount: RustBigUint, @@ -617,15 +662,16 @@ impl SysFuncCallsInteract { .await; } - async fn unset_roles(&mut self, address: &str, token_id: &str, roles: Vec) { - let converted_roles: Vec = - roles.into_iter().map(EsdtLocalRole::from).collect(); - - println!("Unsetting the following roles: {:?}", converted_roles); + async fn unset_roles( + &mut self, + address: Bech32Address, + token_id: &str, + roles: Vec, + ) { + println!("Unsetting the following roles: {:?}", roles); - let bech32_addr = Bech32Address::from_bech32_string(address.to_string()); - let addr = bech32_addr.to_address(); - let managed_addr: ManagedAddress = ManagedAddress::from_address(&addr); + let managed_addr: ManagedAddress = + ManagedAddress::from_address(&address.to_address()); self.interactor .tx() @@ -636,7 +682,7 @@ impl SysFuncCallsInteract { .unset_special_roles( &managed_addr, &TokenIdentifier::from(token_id), - converted_roles.into_iter(), + roles.into_iter(), ) .prepare_async() .run() diff --git a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_cli.rs b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_cli.rs index 5cb356b3d8..d498e11675 100644 --- a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_cli.rs +++ b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_cli.rs @@ -97,6 +97,8 @@ pub struct IssueTokenArgs { pub struct MintArgs { #[arg(long = "token-id")] pub token_id: String, + #[arg(short = 'n', long = "nonce")] + pub nonce: u64, #[arg(long = "amount")] pub amount: RustBigUint, } @@ -113,6 +115,8 @@ pub struct SetRolesArgs { pub struct BurnArgs { #[arg(long = "token-id")] pub token_id: String, + #[arg(short = 'n', long = "nonce")] + pub nonce: u64, #[arg(long = "amount")] pub amount: RustBigUint, } @@ -166,7 +170,7 @@ pub struct MintSFTArgs { #[arg(short = 'n', long = "name")] pub name: String, #[arg(short = 'r', long = "royalties")] - pub royalties: RustBigUint, + pub royalties: u64, #[arg(long = "hash")] pub hash: String, } From 1f6f64449e3eba2c0014cd4b0a8d3f0fa73ad6b8 Mon Sep 17 00:00:00 2001 From: JustEatAnApple Date: Thu, 29 Aug 2024 09:47:45 +0300 Subject: [PATCH 64/92] Finished updating the adder example Co-authored-by: Andrei Vasilescu --- .../adder/interact/src/basic_interact.rs | 71 ++++--------------- 1 file changed, 15 insertions(+), 56 deletions(-) diff --git a/contracts/examples/adder/interact/src/basic_interact.rs b/contracts/examples/adder/interact/src/basic_interact.rs index e1dc1b3dec..37e511b823 100644 --- a/contracts/examples/adder/interact/src/basic_interact.rs +++ b/contracts/examples/adder/interact/src/basic_interact.rs @@ -41,7 +41,8 @@ async fn main() { basic_interact.print_sum().await; }, Some(basic_interact_cli::InteractCliCommand::Upgrade(args)) => { - basic_interact.upgrade(args.value).await + let owner_address = basic_interact.adder_owner_address.clone(); + basic_interact.upgrade(args.value, owner_address, ExpectError(0, "")).await }, None => {}, } @@ -209,63 +210,21 @@ impl AdderInteract { println!("sum: {sum}"); } - async fn fail_upgrade(&mut self, new_value: u32) { - self.interactor - .tx() - .from(&self.wallet_address) - .to(self.state.current_adder_address()) - .gas(6_000_000) - .typed(adder_proxy::AdderProxy) - .upgrade(BigUint::from(new_value)) - .code_metadata(CodeMetadata::UPGRADEABLE) - .code(ADDER_CODE_PATH) - .with_result(ExpectError(4, "upgrade is allowed only for owner")) - .prepare_async() - .run() - .await; - - let sum = self - .interactor - .query() - .to(self.state.current_adder_address()) - .typed(adder_proxy::AdderProxy) - .sum() - .returns(ReturnsResultUnmanaged) - .prepare_async() - .run() - .await; - assert_ne!(sum, RustBigUint::from(new_value)); - - println!("Upgrade failed: upgrade is allowed only for owner"); - } - - async fn upgrade(&mut self, new_value: u32) { + async fn upgrade(&mut self, new_value: u32, sender: Bech32Address, expected_result: ExpectError<'_>) { let response = self .interactor .tx() - .from(&self.adder_owner_address) + .from(sender) .to(self.state.current_adder_address()) .gas(6_000_000) .typed(adder_proxy::AdderProxy) .upgrade(BigUint::from(new_value)) .code_metadata(CodeMetadata::UPGRADEABLE) .code(ADDER_CODE_PATH) - .returns(ReturnsResultUnmanaged) - .prepare_async() - .run() - .await; - - let sum = self - .interactor - .query() - .to(self.state.current_adder_address()) - .typed(adder_proxy::AdderProxy) - .sum() - .returns(ReturnsResultUnmanaged) + .returns(expected_result) .prepare_async() .run() .await; - assert_eq!(sum, RustBigUint::from(new_value)); println!("response: {response:?}"); } @@ -273,22 +232,22 @@ impl AdderInteract { #[tokio::test] #[ignore = "run on demand"] -async fn fail_upgrade_test() { +async fn upgrade_test() { let mut basic_interact = AdderInteract::init().await; basic_interact.deploy().await; basic_interact.add(1u32).await; - basic_interact.fail_upgrade(7u32).await; -} + // Sum will be 1 + basic_interact.print_sum().await; -#[tokio::test] -#[ignore = "run on demand"] -async fn upgrade_test() { - let mut basic_interact = AdderInteract::init().await; + basic_interact.upgrade(7u32, basic_interact.adder_owner_address.clone(), ExpectError(0, "")).await; - basic_interact.deploy().await; - basic_interact.add(1u32).await; + // Sum will be the updated value of 7 + basic_interact.print_sum().await; + + basic_interact.upgrade(10u32, basic_interact.wallet_address.clone(), ExpectError(4, "upgrade is allowed only for owner")).await; - basic_interact.upgrade(7u32).await; + // Sum will remain 7 + basic_interact.print_sum().await; } From 6e6c9e1ffc76b39204e2aeb89b4769b3cad7eca6 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Thu, 29 Aug 2024 10:40:17 +0300 Subject: [PATCH 65/92] ESDTSystemSCAddress in interactor --- .../markers/esdt_system_sc_address.rs | 16 ++++---- .../interact/src/basic_interact.rs | 38 +++++++++---------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/framework/base/src/types/interaction/markers/esdt_system_sc_address.rs b/framework/base/src/types/interaction/markers/esdt_system_sc_address.rs index b7b646ae16..e422553ca4 100644 --- a/framework/base/src/types/interaction/markers/esdt_system_sc_address.rs +++ b/framework/base/src/types/interaction/markers/esdt_system_sc_address.rs @@ -3,8 +3,8 @@ use multiversx_sc_codec::{EncodeErrorHandler, TopEncode, TopEncodeOutput}; use crate::{ abi::TypeAbiFrom, - api::{CallTypeApi, ManagedTypeApi}, - types::{AnnotatedValue, ManagedAddress, ManagedBuffer, TxScEnv, TxTo, TxToSpecified}, + api::ManagedTypeApi, + types::{AnnotatedValue, ManagedAddress, ManagedBuffer, TxEnv, TxTo, TxToSpecified}, }; /// Address of the system smart contract that manages ESDT. @@ -35,21 +35,21 @@ impl ESDTSystemSCAddress { } } -impl AnnotatedValue, ManagedAddress> for ESDTSystemSCAddress +impl AnnotatedValue> for ESDTSystemSCAddress where - Api: CallTypeApi, + Env: TxEnv, { - fn annotation(&self, _env: &TxScEnv) -> ManagedBuffer { + fn annotation(&self, _env: &Env) -> ManagedBuffer { ManagedBuffer::from(SYSTEM_SC_ADDRESS_ANNOTATION) } - fn to_value(&self, _env: &TxScEnv) -> ManagedAddress { + fn to_value(&self, _env: &Env) -> ManagedAddress { ESDTSystemSCAddress.to_managed_address() } } -impl TxTo> for ESDTSystemSCAddress where Api: CallTypeApi {} -impl TxToSpecified> for ESDTSystemSCAddress where Api: CallTypeApi {} +impl TxTo for ESDTSystemSCAddress where Env: TxEnv {} +impl TxToSpecified for ESDTSystemSCAddress where Env: TxEnv {} impl TopEncode for ESDTSystemSCAddress { fn top_encode_or_handle_err(&self, output: O, h: H) -> Result<(), H::HandledErr> diff --git a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs index fb08fd587b..33edf61b4b 100644 --- a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs +++ b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs @@ -231,7 +231,7 @@ impl SysFuncCallsInteract { .interactor .tx() .from(&self.wallet_address) - .to(ESDTSystemSCAddress.to_managed_address()) + .to(ESDTSystemSCAddress) .gas(100_000_000u64) .typed(ESDTSystemSCProxy) .issue_fungible( @@ -270,7 +270,7 @@ impl SysFuncCallsInteract { .interactor .tx() .from(&self.wallet_address) - .to(ESDTSystemSCAddress.to_managed_address()) + .to(ESDTSystemSCAddress) .gas(100_000_000u64) .typed(ESDTSystemSCProxy) .issue_non_fungible( @@ -306,7 +306,7 @@ impl SysFuncCallsInteract { .interactor .tx() .from(&self.wallet_address) - .to(ESDTSystemSCAddress.to_managed_address()) + .to(ESDTSystemSCAddress) .gas(100_000_000u64) .typed(ESDTSystemSCProxy) .issue_semi_fungible( @@ -344,7 +344,7 @@ impl SysFuncCallsInteract { .interactor .tx() .from(&self.wallet_address) - .to(ESDTSystemSCAddress.to_managed_address()) + .to(ESDTSystemSCAddress) .gas(100_000_000u64) .typed(ESDTSystemSCProxy) .issue_and_set_all_roles( @@ -372,7 +372,7 @@ impl SysFuncCallsInteract { self.interactor .tx() .from(&self.wallet_address) - .to(ESDTSystemSCAddress.to_managed_address()) + .to(ESDTSystemSCAddress) .gas(100_000_000u64) .typed(ESDTSystemSCProxy) .set_special_roles( @@ -430,7 +430,7 @@ impl SysFuncCallsInteract { .interactor .tx() .from(&self.wallet_address) - .to(ESDTSystemSCAddress.to_managed_address()) + .to(ESDTSystemSCAddress) .gas(100_000_000u64) .typed(ESDTSystemSCProxy) .register_meta_esdt( @@ -461,7 +461,7 @@ impl SysFuncCallsInteract { self.interactor .tx() .from(&self.wallet_address) - .to(ESDTSystemSCAddress.to_managed_address()) + .to(ESDTSystemSCAddress) .gas(100_000_000u64) .typed(ESDTSystemSCProxy) .change_sft_to_meta_esdt(&TokenIdentifier::from(token_id), num_decimals) @@ -511,7 +511,7 @@ impl SysFuncCallsInteract { self.interactor .tx() .from(&self.wallet_address) - .to(ESDTSystemSCAddress.to_managed_address()) + .to(ESDTSystemSCAddress) .gas(100_000_000u64) .typed(ESDTSystemSCProxy) .pause(&TokenIdentifier::from(token_id)) @@ -525,7 +525,7 @@ impl SysFuncCallsInteract { self.interactor .tx() .from(&self.wallet_address) - .to(ESDTSystemSCAddress.to_managed_address()) + .to(ESDTSystemSCAddress) .gas(100_000_000u64) .typed(ESDTSystemSCProxy) .unpause(&TokenIdentifier::from(token_id)) @@ -541,7 +541,7 @@ impl SysFuncCallsInteract { self.interactor .tx() .from(&self.wallet_address) - .to(ESDTSystemSCAddress.to_managed_address()) + .to(ESDTSystemSCAddress) .gas(100_000_000u64) .typed(ESDTSystemSCProxy) .freeze(&TokenIdentifier::from(token_id), &managed_address) @@ -557,7 +557,7 @@ impl SysFuncCallsInteract { self.interactor .tx() .from(&self.wallet_address) - .to(ESDTSystemSCAddress.to_managed_address()) + .to(ESDTSystemSCAddress) .gas(100_000_000u64) .typed(ESDTSystemSCProxy) .unfreeze(&TokenIdentifier::from(token_id), &managed_address) @@ -573,7 +573,7 @@ impl SysFuncCallsInteract { self.interactor .tx() .from(&self.wallet_address) - .to(ESDTSystemSCAddress.to_managed_address()) + .to(ESDTSystemSCAddress) .gas(100_000_000u64) .typed(ESDTSystemSCProxy) .freeze_nft(&TokenIdentifier::from(token_id), nonce, &managed_address) @@ -589,7 +589,7 @@ impl SysFuncCallsInteract { self.interactor .tx() .from(&self.wallet_address) - .to(ESDTSystemSCAddress.to_managed_address()) + .to(ESDTSystemSCAddress) .gas(100_000_000u64) .typed(ESDTSystemSCProxy) .unfreeze_nft(&TokenIdentifier::from(token_id), nonce, &managed_address) @@ -605,7 +605,7 @@ impl SysFuncCallsInteract { self.interactor .tx() .from(&self.wallet_address) - .to(&ESDTSystemSCAddress.to_managed_address()) + .to(ESDTSystemSCAddress) .gas(100_000_000u64) .typed(ESDTSystemSCProxy) .wipe(&TokenIdentifier::from(token_id), &managed_address) @@ -621,7 +621,7 @@ impl SysFuncCallsInteract { self.interactor .tx() .from(&self.wallet_address) - .to(ESDTSystemSCAddress.to_managed_address()) + .to(ESDTSystemSCAddress) .gas(100_000_000u64) .typed(ESDTSystemSCProxy) .wipe_nft(&TokenIdentifier::from(token_id), nonce, &managed_address) @@ -676,7 +676,7 @@ impl SysFuncCallsInteract { self.interactor .tx() .from(&self.wallet_address) - .to(ESDTSystemSCAddress.to_managed_address()) + .to(ESDTSystemSCAddress) .gas(100_000_000u64) .typed(ESDTSystemSCProxy) .unset_special_roles( @@ -698,7 +698,7 @@ impl SysFuncCallsInteract { self.interactor .tx() .from(&self.wallet_address) - .to(ESDTSystemSCAddress.to_managed_address()) + .to(ESDTSystemSCAddress) .gas(100_000_000u64) .typed(ESDTSystemSCProxy) .transfer_ownership(&TokenIdentifier::from(token_id), &managed_addr) @@ -722,7 +722,7 @@ impl SysFuncCallsInteract { self.interactor .tx() .from(&self.wallet_address) - .to(ESDTSystemSCAddress.to_managed_address()) + .to(ESDTSystemSCAddress) .gas(100_000_000u64) .typed(ESDTSystemSCProxy) .transfer_nft_create_role( @@ -740,7 +740,7 @@ impl SysFuncCallsInteract { self.interactor .tx() .from(&self.wallet_address) - .to(ESDTSystemSCAddress.to_managed_address()) + .to(ESDTSystemSCAddress) .gas(100_000_000u64) .typed(ESDTSystemSCProxy) .control_changes( From 1bf4b456acc1ce7727f6e82eece678fdf5e2620d Mon Sep 17 00:00:00 2001 From: Andrei Vasilescu Date: Thu, 29 Aug 2024 10:43:58 +0300 Subject: [PATCH 66/92] changed test wallet --- .../sys-func-calls/interact/src/basic_interact.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs index 33edf61b4b..57b1ebe1aa 100644 --- a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs +++ b/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs @@ -208,8 +208,7 @@ impl SysFuncCallsInteract { let config = Config::load_config(); let mut interactor = Interactor::new(config.gateway()).await; - let wallet_address = - interactor.register_wallet(Wallet::from_pem_file("wallet.pem").unwrap()); + let wallet_address = interactor.register_wallet(test_wallets::alice()); Self { interactor, From 6dc98686a3dbca8979ec8b34ac87f2cc0fb0a5de Mon Sep 17 00:00:00 2001 From: Andrei Vasilescu Date: Thu, 29 Aug 2024 12:10:58 +0300 Subject: [PATCH 67/92] refactored upgrade code --- .../adder/interact/src/basic_interact.rs | 83 ++++++++++++++----- 1 file changed, 64 insertions(+), 19 deletions(-) diff --git a/contracts/examples/adder/interact/src/basic_interact.rs b/contracts/examples/adder/interact/src/basic_interact.rs index 37e511b823..93a00d4079 100644 --- a/contracts/examples/adder/interact/src/basic_interact.rs +++ b/contracts/examples/adder/interact/src/basic_interact.rs @@ -42,7 +42,9 @@ async fn main() { }, Some(basic_interact_cli::InteractCliCommand::Upgrade(args)) => { let owner_address = basic_interact.adder_owner_address.clone(); - basic_interact.upgrade(args.value, owner_address, ExpectError(0, "")).await + basic_interact + .upgrade(args.value, &owner_address, None) + .await }, None => {}, } @@ -210,23 +212,59 @@ impl AdderInteract { println!("sum: {sum}"); } - async fn upgrade(&mut self, new_value: u32, sender: Bech32Address, expected_result: ExpectError<'_>) { - let response = self - .interactor - .tx() - .from(sender) - .to(self.state.current_adder_address()) - .gas(6_000_000) - .typed(adder_proxy::AdderProxy) - .upgrade(BigUint::from(new_value)) - .code_metadata(CodeMetadata::UPGRADEABLE) - .code(ADDER_CODE_PATH) - .returns(expected_result) - .prepare_async() - .run() - .await; + async fn upgrade( + &mut self, + new_value: u32, + sender: &Bech32Address, + expected_result: Option<(u64, &str)>, + ) { + match expected_result { + Some((code, msg)) => { + let response = self + .interactor + .tx() + .from(sender) + .to(self.state.current_adder_address()) + .gas(6_000_000) + .typed(adder_proxy::AdderProxy) + .upgrade(BigUint::from(new_value)) + .code_metadata(CodeMetadata::UPGRADEABLE) + .code(ADDER_CODE_PATH) + .returns(ExpectError(code, msg)) + .prepare_async() + .run() + .await; + + println!("response: {response:?}"); + }, + None => { + self.interactor + .tx() + .from(sender) + .to(self.state.current_adder_address()) + .gas(6_000_000) + .typed(adder_proxy::AdderProxy) + .upgrade(BigUint::from(new_value)) + .code_metadata(CodeMetadata::UPGRADEABLE) + .code(ADDER_CODE_PATH) + .prepare_async() + .run() + .await; - println!("response: {response:?}"); + let sum = self + .interactor + .query() + .to(self.state.current_adder_address()) + .typed(adder_proxy::AdderProxy) + .sum() + .returns(ReturnsResultUnmanaged) + .prepare_async() + .run() + .await; + + assert_eq!(sum, RustBigUint::from(new_value)); + }, + } } } @@ -234,6 +272,9 @@ impl AdderInteract { #[ignore = "run on demand"] async fn upgrade_test() { let mut basic_interact = AdderInteract::init().await; + let wallet_address = basic_interact.wallet_address.clone(); + let adder_owner_address = basic_interact.adder_owner_address.clone(); + let error_not_owner = (4, "upgrade is allowed only for owner"); basic_interact.deploy().await; basic_interact.add(1u32).await; @@ -241,12 +282,16 @@ async fn upgrade_test() { // Sum will be 1 basic_interact.print_sum().await; - basic_interact.upgrade(7u32, basic_interact.adder_owner_address.clone(), ExpectError(0, "")).await; + basic_interact + .upgrade(7u32, &adder_owner_address, None) + .await; // Sum will be the updated value of 7 basic_interact.print_sum().await; - basic_interact.upgrade(10u32, basic_interact.wallet_address.clone(), ExpectError(4, "upgrade is allowed only for owner")).await; + basic_interact + .upgrade(10u32, &wallet_address, Some(error_not_owner)) + .await; // Sum will remain 7 basic_interact.print_sum().await; From 3e35a4539a5a40e381769e5be34eb466ac7b4b98 Mon Sep 17 00:00:00 2001 From: Andrei Vasilescu Date: Thu, 29 Aug 2024 12:45:35 +0300 Subject: [PATCH 68/92] refactored file system Co-authored-by: Mihai Blacioti --- Cargo.lock | 20 +++---- Cargo.toml | 2 +- .../{sys-func-calls/interact => }/.gitignore | 2 +- .../{sys-func-calls/interact => }/Cargo.toml | 8 +-- .../{sys-func-calls/interact => }/config.toml | 0 .../system_sc_interact.rs} | 60 +++++++++---------- .../system_sc_interact_cli.rs} | 0 .../system_sc_interact_config.rs} | 2 +- .../system_sc_interact_state.rs} | 0 9 files changed, 47 insertions(+), 47 deletions(-) rename tools/interactor-system-func-calls/{sys-func-calls/interact => }/.gitignore (89%) rename tools/interactor-system-func-calls/{sys-func-calls/interact => }/Cargo.toml (68%) rename tools/interactor-system-func-calls/{sys-func-calls/interact => }/config.toml (100%) rename tools/interactor-system-func-calls/{sys-func-calls/interact/src/basic_interact.rs => src/system_sc_interact.rs} (91%) rename tools/interactor-system-func-calls/{sys-func-calls/interact/src/basic_interact_cli.rs => src/system_sc_interact_cli.rs} (100%) rename tools/interactor-system-func-calls/{sys-func-calls/interact/src/basic_interact_config.rs => src/system_sc_interact_config.rs} (92%) rename tools/interactor-system-func-calls/{sys-func-calls/interact/src/basic_interact_state.rs => src/system_sc_interact_state.rs} (100%) diff --git a/Cargo.lock b/Cargo.lock index 126235e69e..07022466f3 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -264,16 +264,6 @@ dependencies = [ "toml", ] -[[package]] -name = "basic-interact-sys-calls" -version = "0.0.0" -dependencies = [ - "clap", - "multiversx-sc-snippets", - "serde", - "toml", -] - [[package]] name = "bech32" version = "0.9.1" @@ -3435,6 +3425,16 @@ dependencies = [ "libc", ] +[[package]] +name = "system-sc-interact" +version = "0.0.0" +dependencies = [ + "clap", + "multiversx-sc-snippets", + "serde", + "toml", +] + [[package]] name = "tempfile" version = "3.12.0" diff --git a/Cargo.toml b/Cargo.toml index ba889c374d..651456eebd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ members = [ "tools/mxpy-snippet-generator", "tools/payload-macro-generator", # "tools/plotter", - "tools/interactor-system-func-calls/sys-func-calls/interact/", + "tools/interactor-system-func-calls/", "vm", diff --git a/tools/interactor-system-func-calls/sys-func-calls/interact/.gitignore b/tools/interactor-system-func-calls/.gitignore similarity index 89% rename from tools/interactor-system-func-calls/sys-func-calls/interact/.gitignore rename to tools/interactor-system-func-calls/.gitignore index b2630809de..ae87d15dcd 100644 --- a/tools/interactor-system-func-calls/sys-func-calls/interact/.gitignore +++ b/tools/interactor-system-func-calls/.gitignore @@ -6,4 +6,4 @@ state.toml # Trace file of interactor tooling -interactor_trace.scen.json +interactor_trace.scen.json \ No newline at end of file diff --git a/tools/interactor-system-func-calls/sys-func-calls/interact/Cargo.toml b/tools/interactor-system-func-calls/Cargo.toml similarity index 68% rename from tools/interactor-system-func-calls/sys-func-calls/interact/Cargo.toml rename to tools/interactor-system-func-calls/Cargo.toml index 837ff49d1c..1cfd20f282 100644 --- a/tools/interactor-system-func-calls/sys-func-calls/interact/Cargo.toml +++ b/tools/interactor-system-func-calls/Cargo.toml @@ -1,9 +1,9 @@ [[bin]] -name = "basic-interact-sys-calls" -path = "src/basic_interact.rs" +name = "system-sc-interact" +path = "src/system_sc_interact.rs" [package] -name = "basic-interact-sys-calls" +name = "system-sc-interact" version = "0.0.0" publish = false edition = "2021" @@ -22,4 +22,4 @@ features = ["derive"] [dependencies.multiversx-sc-snippets] version = "=0.52.3" -path = "../../../../framework/snippets" +path = "../../framework/snippets" diff --git a/tools/interactor-system-func-calls/sys-func-calls/interact/config.toml b/tools/interactor-system-func-calls/config.toml similarity index 100% rename from tools/interactor-system-func-calls/sys-func-calls/interact/config.toml rename to tools/interactor-system-func-calls/config.toml diff --git a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs b/tools/interactor-system-func-calls/src/system_sc_interact.rs similarity index 91% rename from tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs rename to tools/interactor-system-func-calls/src/system_sc_interact.rs index 57b1ebe1aa..c522384290 100644 --- a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact.rs +++ b/tools/interactor-system-func-calls/src/system_sc_interact.rs @@ -1,11 +1,11 @@ -mod basic_interact_cli; -mod basic_interact_config; -mod basic_interact_state; +mod system_sc_interact_cli; +mod system_sc_interact_config; +mod system_sc_interact_state; -use basic_interact_cli::NftDummyAttributes; -use basic_interact_config::Config; -use basic_interact_state::State; use clap::Parser; +use system_sc_interact_cli::NftDummyAttributes; +use system_sc_interact_config::Config; +use system_sc_interact_state::State; use multiversx_sc_snippets::imports::*; @@ -15,9 +15,9 @@ async fn main() { let mut basic_interact = SysFuncCallsInteract::init().await; - let cli = basic_interact_cli::InteractCli::parse(); + let cli = system_sc_interact_cli::InteractCli::parse(); match &cli.command { - Some(basic_interact_cli::InteractCliCommand::IssueToken(args)) => { + Some(system_sc_interact_cli::InteractCliCommand::IssueToken(args)) => { basic_interact .issue_token( args.cost.clone(), @@ -28,12 +28,12 @@ async fn main() { ) .await; }, - Some(basic_interact_cli::InteractCliCommand::Mint(args)) => { + Some(system_sc_interact_cli::InteractCliCommand::Mint(args)) => { basic_interact .mint_token(&args.token_id, args.nonce, args.amount.clone()) .await; }, - Some(basic_interact_cli::InteractCliCommand::SetRoles(args)) => { + Some(system_sc_interact_cli::InteractCliCommand::SetRoles(args)) => { basic_interact .set_roles( &args.token_id, @@ -45,18 +45,18 @@ async fn main() { ) .await; }, - Some(basic_interact_cli::InteractCliCommand::Burn(args)) => { + Some(system_sc_interact_cli::InteractCliCommand::Burn(args)) => { basic_interact .burn_token(&args.token_id, args.nonce, args.amount.clone()) .await; }, - Some(basic_interact_cli::InteractCliCommand::PauseToken(args)) => { + Some(system_sc_interact_cli::InteractCliCommand::PauseToken(args)) => { basic_interact.pause_token(&args.token_id).await; }, - Some(basic_interact_cli::InteractCliCommand::UnpauseToken(args)) => { + Some(system_sc_interact_cli::InteractCliCommand::UnpauseToken(args)) => { basic_interact.unpause_token(&args.token_id).await; }, - Some(basic_interact_cli::InteractCliCommand::FreezeToken(args)) => { + Some(system_sc_interact_cli::InteractCliCommand::FreezeToken(args)) => { basic_interact .freeze_token( &args.token_id, @@ -64,7 +64,7 @@ async fn main() { ) .await; }, - Some(basic_interact_cli::InteractCliCommand::UnfreezeToken(args)) => { + Some(system_sc_interact_cli::InteractCliCommand::UnfreezeToken(args)) => { basic_interact .unfreeze_token( &args.token_id, @@ -72,7 +72,7 @@ async fn main() { ) .await; }, - Some(basic_interact_cli::InteractCliCommand::FreezeNFT(args)) => { + Some(system_sc_interact_cli::InteractCliCommand::FreezeNFT(args)) => { basic_interact .freeze_nft( &args.token_id, @@ -81,7 +81,7 @@ async fn main() { ) .await; }, - Some(basic_interact_cli::InteractCliCommand::UnfreezeNFT(args)) => { + Some(system_sc_interact_cli::InteractCliCommand::UnfreezeNFT(args)) => { basic_interact .unfreeze_nft( &args.token_id, @@ -90,7 +90,7 @@ async fn main() { ) .await; }, - Some(basic_interact_cli::InteractCliCommand::WipeToken(args)) => { + Some(system_sc_interact_cli::InteractCliCommand::WipeToken(args)) => { basic_interact .wipe_token( &args.token_id, @@ -98,7 +98,7 @@ async fn main() { ) .await; }, - Some(basic_interact_cli::InteractCliCommand::WipeNFT(args)) => { + Some(system_sc_interact_cli::InteractCliCommand::WipeNFT(args)) => { basic_interact .wipe_nft( &args.token_id, @@ -107,12 +107,12 @@ async fn main() { ) .await; }, - Some(basic_interact_cli::InteractCliCommand::IssueNFTCollection(args)) => { + Some(system_sc_interact_cli::InteractCliCommand::IssueNFTCollection(args)) => { basic_interact .issue_non_fungible_collection(args.cost.clone(), &args.display_name, &args.ticker) .await; }, - Some(basic_interact_cli::InteractCliCommand::CreateNFT(args)) => { + Some(system_sc_interact_cli::InteractCliCommand::CreateNFT(args)) => { basic_interact .mint_nft( &args.token_id, @@ -123,7 +123,7 @@ async fn main() { ) .await; }, - Some(basic_interact_cli::InteractCliCommand::IssueFungible(args)) => { + Some(system_sc_interact_cli::InteractCliCommand::IssueFungible(args)) => { basic_interact .issue_fungible_token( args.cost.clone(), @@ -134,12 +134,12 @@ async fn main() { ) .await; }, - Some(basic_interact_cli::InteractCliCommand::IssueSftCollection(args)) => { + Some(system_sc_interact_cli::InteractCliCommand::IssueSftCollection(args)) => { basic_interact .issue_semi_fungible_collection(args.cost.clone(), &args.display_name, &args.ticker) .await; }, - Some(basic_interact_cli::InteractCliCommand::MintSft(args)) => { + Some(system_sc_interact_cli::InteractCliCommand::MintSft(args)) => { basic_interact .mint_sft( &args.token_id, @@ -150,7 +150,7 @@ async fn main() { ) .await; }, - Some(basic_interact_cli::InteractCliCommand::RegisterMetaEsdt(args)) => { + Some(system_sc_interact_cli::InteractCliCommand::RegisterMetaEsdt(args)) => { basic_interact .register_meta_esdt( args.cost.clone(), @@ -160,12 +160,12 @@ async fn main() { ) .await; }, - Some(basic_interact_cli::InteractCliCommand::ChangeSftMetaEsdt(args)) => { + Some(system_sc_interact_cli::InteractCliCommand::ChangeSftMetaEsdt(args)) => { basic_interact .change_sft_meta_esdt(&args.token_id, args.num_decimals) .await; }, - Some(basic_interact_cli::InteractCliCommand::UnsetRoles(args)) => { + Some(system_sc_interact_cli::InteractCliCommand::UnsetRoles(args)) => { basic_interact .unset_roles( Bech32Address::from_bech32_string(args.address.clone()), @@ -178,17 +178,17 @@ async fn main() { ) .await; }, - Some(basic_interact_cli::InteractCliCommand::TransferOwnership(args)) => { + Some(system_sc_interact_cli::InteractCliCommand::TransferOwnership(args)) => { basic_interact .transfer_ownership(&args.token_id, &args.new_owner) .await; }, - Some(basic_interact_cli::InteractCliCommand::TransferNftCreateRole(args)) => { + Some(system_sc_interact_cli::InteractCliCommand::TransferNftCreateRole(args)) => { basic_interact .transfer_nft_create_role(&args.token_id, &args.old_owner, &args.new_owner) .await; }, - Some(basic_interact_cli::InteractCliCommand::ControlChanges(args)) => { + Some(system_sc_interact_cli::InteractCliCommand::ControlChanges(args)) => { basic_interact.control_changes(&args.token_id).await; }, diff --git a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_cli.rs b/tools/interactor-system-func-calls/src/system_sc_interact_cli.rs similarity index 100% rename from tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_cli.rs rename to tools/interactor-system-func-calls/src/system_sc_interact_cli.rs diff --git a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_config.rs b/tools/interactor-system-func-calls/src/system_sc_interact_config.rs similarity index 92% rename from tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_config.rs rename to tools/interactor-system-func-calls/src/system_sc_interact_config.rs index f25b91a884..4495f069b8 100644 --- a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_config.rs +++ b/tools/interactor-system-func-calls/src/system_sc_interact_config.rs @@ -2,7 +2,7 @@ use serde::Deserialize; use std::io::Read; /// Config file -const CONFIG_FILE: &str = "config.toml"; +const CONFIG_FILE: &str = "../config.toml"; /// SysFuncCalls Interact configuration #[derive(Debug, Deserialize)] diff --git a/tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_state.rs b/tools/interactor-system-func-calls/src/system_sc_interact_state.rs similarity index 100% rename from tools/interactor-system-func-calls/sys-func-calls/interact/src/basic_interact_state.rs rename to tools/interactor-system-func-calls/src/system_sc_interact_state.rs From 1d7f49587f3066df32ba4218b8261591305f9080 Mon Sep 17 00:00:00 2001 From: Andrei Vasilescu Date: Thu, 29 Aug 2024 16:03:58 +0300 Subject: [PATCH 69/92] fixed returnsNewTokenIdentifier interactor --- framework/snippets/src/network_response.rs | 23 +++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/framework/snippets/src/network_response.rs b/framework/snippets/src/network_response.rs index d505e7a525..4d828e12c7 100644 --- a/framework/snippets/src/network_response.rs +++ b/framework/snippets/src/network_response.rs @@ -103,25 +103,31 @@ fn process_new_deployed_address(tx: &TransactionOnNetwork) -> Option
{ } fn process_new_issued_token_identifier(tx: &TransactionOnNetwork) -> Option { + let original_tx_data = String::from_utf8(base64_decode(tx.data.as_ref().unwrap())).unwrap(); + for scr in tx.smart_contract_results.iter() { if scr.sender.to_bech32_string().unwrap() != ESDTSystemSCAddress.to_bech32_string() { continue; } - let Some(prev_tx) = tx + let prev_tx_data: &str = if let Some(prev_tx) = tx .smart_contract_results .iter() .find(|e| e.hash == scr.prev_tx_hash) - else { + { + prev_tx.data.as_ref() + } else if &scr.prev_tx_hash == tx.hash.as_ref().unwrap() { + &original_tx_data + } else { continue; }; - let is_issue_fungible = prev_tx.data.starts_with("issue@"); - let is_issue_semi_fungible = prev_tx.data.starts_with("issueSemiFungible@"); - let is_issue_non_fungible = prev_tx.data.starts_with("issueNonFungible@"); - let is_register_meta_esdt = prev_tx.data.starts_with("registerMetaESDT@"); + let is_issue_fungible = prev_tx_data.starts_with("issue@"); + let is_issue_semi_fungible = prev_tx_data.starts_with("issueSemiFungible@"); + let is_issue_non_fungible = prev_tx_data.starts_with("issueNonFungible@"); + let is_register_meta_esdt = prev_tx_data.starts_with("registerMetaESDT@"); let is_register_and_set_all_roles_esdt = - prev_tx.data.starts_with("registerAndSetAllRoles@"); + prev_tx_data.starts_with("registerAndSetAllRoles@"); if !is_issue_fungible && !is_issue_semi_fungible @@ -135,12 +141,11 @@ fn process_new_issued_token_identifier(tx: &TransactionOnNetwork) -> Option Date: Thu, 29 Aug 2024 17:05:05 +0300 Subject: [PATCH 70/92] added fix for sc calls creating systemSC issues --- sdk/core/src/gateway/gateway_tx_retrieve.rs | 23 +++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/sdk/core/src/gateway/gateway_tx_retrieve.rs b/sdk/core/src/gateway/gateway_tx_retrieve.rs index 821713f972..c5bbda6adf 100644 --- a/sdk/core/src/gateway/gateway_tx_retrieve.rs +++ b/sdk/core/src/gateway/gateway_tx_retrieve.rs @@ -14,6 +14,7 @@ impl GatewayProxy { let mut retries = 0; let mut backoff_delay = Duration::from_secs_f32(INITIAL_BACKOFF_DELAY); let start_time = Instant::now(); + let mut issue_found = false; loop { match self.get_transaction_status(&tx_hash).await { @@ -26,6 +27,20 @@ impl GatewayProxy { .get_transaction_info_with_results(&tx_hash) .await .unwrap(); + + if transaction_info_with_results.smart_contract_results.len() > 0 + && issue_found == false + { + let first_scr = + &transaction_info_with_results.smart_contract_results[0]; + + if GatewayProxy::is_issue_tx(&first_scr.data) { + issue_found = true; + tokio::time::sleep(Duration::from_secs(30)).await; + continue; + } + } + info!( "Transaction retrieved successfully, with status {}: {:#?}", status, transaction_info_with_results @@ -60,4 +75,12 @@ impl GatewayProxy { ); TransactionOnNetwork::default() } + + fn is_issue_tx(data: &str) -> bool { + data.starts_with("issue@") + || data.starts_with("issueSemiFungible@") + || data.starts_with("issueNonFungible@") + || data.starts_with("registerMetaESDT@") + || data.starts_with("registerAndSetAllRoles@") + } } From 044153613ea4dbedd53822b4ff0681e341b99ec0 Mon Sep 17 00:00:00 2001 From: Andrei Vasilescu Date: Thu, 29 Aug 2024 17:07:39 +0300 Subject: [PATCH 71/92] fixed clippy warnings --- sdk/core/src/gateway/gateway_tx_retrieve.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sdk/core/src/gateway/gateway_tx_retrieve.rs b/sdk/core/src/gateway/gateway_tx_retrieve.rs index c5bbda6adf..452d37b3e0 100644 --- a/sdk/core/src/gateway/gateway_tx_retrieve.rs +++ b/sdk/core/src/gateway/gateway_tx_retrieve.rs @@ -28,8 +28,10 @@ impl GatewayProxy { .await .unwrap(); - if transaction_info_with_results.smart_contract_results.len() > 0 - && issue_found == false + if !transaction_info_with_results + .smart_contract_results + .is_empty() + && !issue_found { let first_scr = &transaction_info_with_results.smart_contract_results[0]; From 3e4654143905787a3e9989804b233bf2ad72c8d1 Mon Sep 17 00:00:00 2001 From: JustEatAnApple Date: Thu, 29 Aug 2024 17:08:59 +0300 Subject: [PATCH 72/92] Added requested changes for clarity Co-authored-by: Andrei Vasilescu --- contracts/examples/adder/interact/src/basic_interact.rs | 6 +++--- framework/snippets/src/imports.rs | 5 ++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/contracts/examples/adder/interact/src/basic_interact.rs b/contracts/examples/adder/interact/src/basic_interact.rs index 93a00d4079..454060eb0d 100644 --- a/contracts/examples/adder/interact/src/basic_interact.rs +++ b/contracts/examples/adder/interact/src/basic_interact.rs @@ -7,7 +7,7 @@ use basic_interact_config::Config; use basic_interact_state::State; use clap::Parser; -use multiversx_sc_snippets::{imports::*, sdk::data::keystore::InsertPassword}; +use multiversx_sc_snippets::imports::*; const INTERACTOR_SCENARIO_TRACE_PATH: &str = "interactor_trace.scen.json"; @@ -227,7 +227,7 @@ impl AdderInteract { .to(self.state.current_adder_address()) .gas(6_000_000) .typed(adder_proxy::AdderProxy) - .upgrade(BigUint::from(new_value)) + .upgrade(new_value) .code_metadata(CodeMetadata::UPGRADEABLE) .code(ADDER_CODE_PATH) .returns(ExpectError(code, msg)) @@ -244,7 +244,7 @@ impl AdderInteract { .to(self.state.current_adder_address()) .gas(6_000_000) .typed(adder_proxy::AdderProxy) - .upgrade(BigUint::from(new_value)) + .upgrade(new_value) .code_metadata(CodeMetadata::UPGRADEABLE) .code(ADDER_CODE_PATH) .prepare_async() diff --git a/framework/snippets/src/imports.rs b/framework/snippets/src/imports.rs index d416955e4c..a35e880c78 100644 --- a/framework/snippets/src/imports.rs +++ b/framework/snippets/src/imports.rs @@ -4,7 +4,10 @@ pub use crate::{ dns_address_for_name, test_wallets, Interactor, InteractorPrepareAsync, StepBuffer, }; -pub use multiversx_sdk::wallet::Wallet; +pub use multiversx_sdk::{ + wallet::Wallet, + data::keystore::InsertPassword, +}; pub use env_logger; pub use tokio; From bbaae29c6a18619ad58c3025438ea055043e4ed2 Mon Sep 17 00:00:00 2001 From: JustEatAnApple Date: Thu, 29 Aug 2024 18:01:49 +0300 Subject: [PATCH 73/92] Resolved changes requested Co-authored-by: Andrei Vasilescu --- .../src/system_sc_interact.rs | 112 +++++++++++------- .../src/system_sc_interact_cli.rs | 4 +- 2 files changed, 68 insertions(+), 48 deletions(-) diff --git a/tools/interactor-system-func-calls/src/system_sc_interact.rs b/tools/interactor-system-func-calls/src/system_sc_interact.rs index c522384290..bda87cd491 100644 --- a/tools/interactor-system-func-calls/src/system_sc_interact.rs +++ b/tools/interactor-system-func-calls/src/system_sc_interact.rs @@ -60,7 +60,7 @@ async fn main() { basic_interact .freeze_token( &args.token_id, - Bech32Address::from_bech32_string(args.address.clone()), + &Bech32Address::from_bech32_string(args.address.clone()), ) .await; }, @@ -68,7 +68,7 @@ async fn main() { basic_interact .unfreeze_token( &args.token_id, - Bech32Address::from_bech32_string(args.address.clone()), + &Bech32Address::from_bech32_string(args.address.clone()), ) .await; }, @@ -77,7 +77,7 @@ async fn main() { .freeze_nft( &args.token_id, args.nft_nonce, - Bech32Address::from_bech32_string(args.address.clone()), + &Bech32Address::from_bech32_string(args.address.clone()), ) .await; }, @@ -86,7 +86,7 @@ async fn main() { .unfreeze_nft( &args.token_id, args.nft_nonce, - Bech32Address::from_bech32_string(args.address.clone()), + &Bech32Address::from_bech32_string(args.address.clone()), ) .await; }, @@ -94,7 +94,7 @@ async fn main() { basic_interact .wipe_token( &args.token_id, - Bech32Address::from_bech32_string(args.address.clone()), + &Bech32Address::from_bech32_string(args.address.clone()), ) .await; }, @@ -103,7 +103,7 @@ async fn main() { .wipe_nft( &args.token_id, args.nft_nonce, - Bech32Address::from_bech32_string(args.address.clone()), + &Bech32Address::from_bech32_string(args.address.clone()), ) .await; }, @@ -168,7 +168,7 @@ async fn main() { Some(system_sc_interact_cli::InteractCliCommand::UnsetRoles(args)) => { basic_interact .unset_roles( - Bech32Address::from_bech32_string(args.address.clone()), + &Bech32Address::from_bech32_string(args.address.clone()), &args.token_id, args.roles .clone() @@ -180,12 +180,19 @@ async fn main() { }, Some(system_sc_interact_cli::InteractCliCommand::TransferOwnership(args)) => { basic_interact - .transfer_ownership(&args.token_id, &args.new_owner) + .transfer_ownership( + &args.token_id, + &Bech32Address::from_bech32_string(args.new_owner.clone()), + ) .await; }, Some(system_sc_interact_cli::InteractCliCommand::TransferNftCreateRole(args)) => { basic_interact - .transfer_nft_create_role(&args.token_id, &args.old_owner, &args.new_owner) + .transfer_nft_create_role( + &args.token_id, + &Bech32Address::from_bech32_string(args.old_owner.clone()), + &Bech32Address::from_bech32_string(args.new_owner.clone()), + ) .await; }, Some(system_sc_interact_cli::InteractCliCommand::ControlChanges(args)) => { @@ -226,6 +233,7 @@ impl SysFuncCallsInteract { num_decimals: usize, ) { println!("Issuing fungible token..."); + let res = self .interactor .tx() @@ -265,6 +273,7 @@ impl SysFuncCallsInteract { token_ticker: &str, ) { println!("Issuing NFT Collection..."); + let nft_collection_id = self .interactor .tx() @@ -301,6 +310,7 @@ impl SysFuncCallsInteract { token_ticker: &str, ) { println!("Issuing SFT Collection..."); + let sft_collection_id = self .interactor .tx() @@ -339,6 +349,7 @@ impl SysFuncCallsInteract { token_type: EsdtTokenType, ) { println!("Registering token..."); + let token_id = self .interactor .tx() @@ -363,9 +374,6 @@ impl SysFuncCallsInteract { async fn set_roles(&mut self, token_id: &str, roles: Vec) { let wallet_address = &self.wallet_address.clone().into_address(); - // let converted_roles: Vec = - // roles.into_iter().map(EsdtLocalRole::from).collect(); - println!("Setting the following roles: {:?}", roles); self.interactor @@ -425,6 +433,7 @@ impl SysFuncCallsInteract { num_decimals: usize, ) { println!("Registering meta ESDT..."); + let meta_esdt = self .interactor .tx() @@ -457,6 +466,7 @@ impl SysFuncCallsInteract { async fn change_sft_meta_esdt(&mut self, token_id: &str, num_decimals: usize) { println!("Changing SFT to Meta-ESDT..."); + self.interactor .tx() .from(&self.wallet_address) @@ -471,6 +481,7 @@ impl SysFuncCallsInteract { async fn mint_token(&mut self, token_id: &str, nonce: u64, amount: RustBigUint) { println!("Minting tokens..."); + self.interactor .tx() .from(&self.wallet_address) @@ -489,6 +500,7 @@ impl SysFuncCallsInteract { async fn burn_token(&mut self, token_id: &str, nonce: u64, amount: RustBigUint) { println!("Burning tokens..."); + self.interactor .tx() .from(&self.wallet_address) @@ -507,6 +519,7 @@ impl SysFuncCallsInteract { async fn pause_token(&mut self, token_id: &str) { println!("Pausing token..."); + self.interactor .tx() .from(&self.wallet_address) @@ -521,6 +534,7 @@ impl SysFuncCallsInteract { async fn unpause_token(&mut self, token_id: &str) { println!("Unpausing token..."); + self.interactor .tx() .from(&self.wallet_address) @@ -533,10 +547,11 @@ impl SysFuncCallsInteract { .await; } - async fn freeze_token(&mut self, token_id: &str, address: Bech32Address) { - println!("Freezing token..."); + async fn freeze_token(&mut self, token_id: &str, address: &Bech32Address) { let managed_address: ManagedAddress = ManagedAddress::from_address(&address.to_address()); + println!("Freezing token..."); + self.interactor .tx() .from(&self.wallet_address) @@ -549,10 +564,11 @@ impl SysFuncCallsInteract { .await; } - async fn unfreeze_token(&mut self, token_id: &str, address: Bech32Address) { - println!("Unfreezing token..."); + async fn unfreeze_token(&mut self, token_id: &str, address: &Bech32Address) { let managed_address: ManagedAddress = ManagedAddress::from_address(&address.to_address()); + println!("Unfreezing token..."); + self.interactor .tx() .from(&self.wallet_address) @@ -565,10 +581,11 @@ impl SysFuncCallsInteract { .await; } - async fn freeze_nft(&mut self, token_id: &str, nonce: u64, address: Bech32Address) { - println!("Freezing NFT/SFT/Meta-ESDT..."); + async fn freeze_nft(&mut self, token_id: &str, nonce: u64, address: &Bech32Address) { let managed_address: ManagedAddress = ManagedAddress::from_address(&address.to_address()); + println!("Freezing NFT/SFT/Meta-ESDT..."); + self.interactor .tx() .from(&self.wallet_address) @@ -581,10 +598,11 @@ impl SysFuncCallsInteract { .await; } - async fn unfreeze_nft(&mut self, token_id: &str, nonce: u64, address: Bech32Address) { - println!("Unfreezing NFT/SFT/Meta-ESDT..."); + async fn unfreeze_nft(&mut self, token_id: &str, nonce: u64, address: &Bech32Address) { let managed_address: ManagedAddress = ManagedAddress::from_address(&address.to_address()); + println!("Unfreezing NFT/SFT/Meta-ESDT..."); + self.interactor .tx() .from(&self.wallet_address) @@ -597,10 +615,11 @@ impl SysFuncCallsInteract { .await; } - async fn wipe_token(&mut self, token_id: &str, address: Bech32Address) { - println!("Wiping token..."); + async fn wipe_token(&mut self, token_id: &str, address: &Bech32Address) { let managed_address: ManagedAddress = ManagedAddress::from_address(&address.to_address()); + println!("Wiping token..."); + self.interactor .tx() .from(&self.wallet_address) @@ -613,10 +632,11 @@ impl SysFuncCallsInteract { .await; } - async fn wipe_nft(&mut self, token_id: &str, nonce: u64, address: Bech32Address) { - println!("Wiping NFT/SFT/Meta-ESDT..."); + async fn wipe_nft(&mut self, token_id: &str, nonce: u64, address: &Bech32Address) { let managed_address: ManagedAddress = ManagedAddress::from_address(&address.to_address()); + println!("Wiping NFT/SFT/Meta-ESDT..."); + self.interactor .tx() .from(&self.wallet_address) @@ -638,6 +658,7 @@ impl SysFuncCallsInteract { hash: &str, ) { println!("Minting NFT..."); + self.interactor .tx() .from(&self.wallet_address) @@ -663,14 +684,13 @@ impl SysFuncCallsInteract { async fn unset_roles( &mut self, - address: Bech32Address, + address: &Bech32Address, token_id: &str, roles: Vec, ) { - println!("Unsetting the following roles: {:?}", roles); - - let managed_addr: ManagedAddress = + let managed_address: ManagedAddress = ManagedAddress::from_address(&address.to_address()); + println!("Unsetting the following roles: {:?}", roles); self.interactor .tx() @@ -679,7 +699,7 @@ impl SysFuncCallsInteract { .gas(100_000_000u64) .typed(ESDTSystemSCProxy) .unset_special_roles( - &managed_addr, + &managed_address, &TokenIdentifier::from(token_id), roles.into_iter(), ) @@ -688,11 +708,10 @@ impl SysFuncCallsInteract { .await; } - async fn transfer_ownership(&mut self, token_id: &str, new_owner: &str) { + async fn transfer_ownership(&mut self, token_id: &str, new_owner: &Bech32Address) { + let managed_new_owner: ManagedAddress = + ManagedAddress::from_address(&new_owner.to_address()); println!("Transferring token ownership..."); - let bech32_addr = Bech32Address::from_bech32_string(new_owner.to_string()); - let addr = bech32_addr.to_address(); - let managed_addr: ManagedAddress = ManagedAddress::from_address(&addr); self.interactor .tx() @@ -700,23 +719,23 @@ impl SysFuncCallsInteract { .to(ESDTSystemSCAddress) .gas(100_000_000u64) .typed(ESDTSystemSCProxy) - .transfer_ownership(&TokenIdentifier::from(token_id), &managed_addr) + .transfer_ownership(&TokenIdentifier::from(token_id), &managed_new_owner) .prepare_async() .run() .await; } - async fn transfer_nft_create_role(&mut self, token_id: &str, old_owner: &str, new_owner: &str) { + async fn transfer_nft_create_role( + &mut self, + token_id: &str, + old_owner: &Bech32Address, + new_owner: &Bech32Address, + ) { + let managed_old_owner: ManagedAddress = + ManagedAddress::from_address(&old_owner.to_address()); + let managed_new_owner: ManagedAddress = + ManagedAddress::from_address(&new_owner.to_address()); println!("Transferring NFT create role..."); - let bech32_addr_new_owner = Bech32Address::from_bech32_string(new_owner.to_string()); - let addr_new_owner = bech32_addr_new_owner.to_address(); - let managed_addr_new_owner: ManagedAddress = - ManagedAddress::from_address(&addr_new_owner); - - let bech32_addr_old_owner = Bech32Address::from_bech32_string(old_owner.to_string()); - let addr_old_owner = bech32_addr_old_owner.to_address(); - let managed_addr_old_owner: ManagedAddress = - ManagedAddress::from_address(&addr_old_owner); self.interactor .tx() @@ -726,8 +745,8 @@ impl SysFuncCallsInteract { .typed(ESDTSystemSCProxy) .transfer_nft_create_role( &TokenIdentifier::from(token_id), - &managed_addr_old_owner, - &managed_addr_new_owner, + &managed_old_owner, + &managed_new_owner, ) .prepare_async() .run() @@ -736,6 +755,7 @@ impl SysFuncCallsInteract { async fn control_changes(&mut self, token_id: &str) { println!("Control changes"); + self.interactor .tx() .from(&self.wallet_address) diff --git a/tools/interactor-system-func-calls/src/system_sc_interact_cli.rs b/tools/interactor-system-func-calls/src/system_sc_interact_cli.rs index d498e11675..6e958fbdb3 100644 --- a/tools/interactor-system-func-calls/src/system_sc_interact_cli.rs +++ b/tools/interactor-system-func-calls/src/system_sc_interact_cli.rs @@ -1,5 +1,5 @@ use clap::{Args, Parser, Subcommand}; -use multiversx_sc_snippets::{imports::RustBigUint, multiversx_sc::proxy_imports::*}; +use multiversx_sc_snippets::{imports::*, multiversx_sc::proxy_imports::*}; /// SysFuncCalls Interact CLI #[derive(Default, PartialEq, Eq, Debug, Parser)] @@ -155,7 +155,7 @@ pub struct IssueSftArgs { pub ticker: String, } -#[derive(TopEncode, TopDecode, Clone, Debug, PartialEq, Eq)] +#[derive(TopEncode, Clone, Debug, PartialEq, Eq)] pub struct NftDummyAttributes { pub creation_epoch: u64, pub cool_factor: u8, From d31ffa7ecf04343ed6e913391dfabf8354f0572f Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Fri, 30 Aug 2024 11:37:13 +0300 Subject: [PATCH 74/92] crypto EI 1.4 tests ignored --- .../basic-features/tests/basic_features_scenario_go_test.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/contracts/feature-tests/basic-features/tests/basic_features_scenario_go_test.rs b/contracts/feature-tests/basic-features/tests/basic_features_scenario_go_test.rs index 3a7a5dc515..58bee7c1da 100644 --- a/contracts/feature-tests/basic-features/tests/basic_features_scenario_go_test.rs +++ b/contracts/feature-tests/basic-features/tests/basic_features_scenario_go_test.rs @@ -85,11 +85,13 @@ fn crypto_verify_bls_go() { } #[test] +#[ignore = "requires EI 1.4 in mx-scenario-go"] fn crypto_verify_bls_share_go() { world().run("scenarios/crypto_verify_bls_share.scen.json"); } #[test] +#[ignore = "requires EI 1.4 in mx-scenario-go"] fn crypto_verify_bls_aggregated_go() { world().run("scenarios/crypto_verify_bls_aggregated_signature.scen.json"); } @@ -105,6 +107,7 @@ fn crypto_verify_secp_256_k_1_go() { } #[test] +#[ignore = "requires EI 1.4 in mx-scenario-go"] fn crypto_verify_secp_256_r_1_go() { world().run("scenarios/crypto_verify_secp256r1.scen.json"); } From 4517c25151fd0c0c69ea1a49be7052d449d4e7f0 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Fri, 30 Aug 2024 17:38:57 +0300 Subject: [PATCH 75/92] crypto_verify_secp256r1 test fix --- .../crypto_verify_secp256r1.scen.json | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/contracts/feature-tests/basic-features/scenarios/crypto_verify_secp256r1.scen.json b/contracts/feature-tests/basic-features/scenarios/crypto_verify_secp256r1.scen.json index 0de6016ef6..c1287b32d9 100644 --- a/contracts/feature-tests/basic-features/scenarios/crypto_verify_secp256r1.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/crypto_verify_secp256r1.scen.json @@ -19,22 +19,22 @@ }, { "step": "scCall", - "id": "1", + "id": "secp256r1 - ok", "tx": { "from": "address:an_account", "to": "sc:basic-features-crypto", "function": "verify_secp256r1_signature", "arguments": [ - "0x03e4d20902182b89cd5ed7984ebcf063f2fd2508d9f034e4109be487be9e2cf54d", - "0xa607fab72e13d6b625942bd5c56cc32792c2c7c7f16053b2fb6d62dd9cf36fdacf9d5a8af3537eaf5eb93335b36cf8f1d6e5bb2dfffce9055a2608d5e1a5b839eacf36dd5dec6d2fa156133acf064cc26487d543873f3b3837a3c09b5f4cb509bbc6585d", - "0xd5065c32582bf0bc8f96b34177cbf47f61d4705d64daaebff884693b6dd94afd50d3ac647aeb14d325c28bb00ab68b23280c1c480cac0e72b5a58176ac8cd1b9" + "0x02bc52274edebbef8878eacc4d1e0ed4fb213e5b0737389701ae8d59c403325720", + "0xbf9facf48b2219db73b50c7ff59ceef2ada56632c71afc555d6bb4072d7634d1d9353acd53517ffb9a06935a89a6454fcaa40c69becf9f8029a271fd252ea55307d00d6e97a30719d48d6b7f993af24e9c54381cba02a113238eaee9d741cababeb21aaf", + "0xc7877497444274267a4ea6f42deefde23a12e44f1ec1b437018e5c0e2834ce376dec1b81ebeacf5fbc6882e69af7cafad47bbb96cfb09e8d77d12afff7543052" ], "gasLimit": "50,000,000", "gasPrice": "0" }, "expect": { "out": [ - "0x01" + "true" ], "status": "", "logs": "*", @@ -44,24 +44,23 @@ }, { "step": "scCall", - "id": "2", + "id": "secp256r1 - fail", "tx": { "from": "address:an_account", "to": "sc:basic-features-crypto", "function": "verify_secp256r1_signature", "arguments": [ - "0x04a673638cb9587cb68ea08dbef685c6f2d2a751a8b3c6f2a7e9a4999e6e4bfaf5ca1d22fe57c6103dbaac10cf15d15c0791cab8bb9a04f800e4d215276cb3e008", - "0x00", - "0x3045022100fab29dbcb623e7e96f44665f312b89ffdb9e4d2e2f53353236fbbcf57b2f49bf02203d6f9c63df8be43121042970a549a2d3baeca093fd37b726ddcc0924638409f5" + "0x02bc52274edebbef8878eacc4d1e0ed4fb213e5b0737389701ae8d59c403325720", + "0xbf9facf48b2219db73b50c7ff59ceef2ada56632c71afc555d6bb4072d7634d1d9353acd53517ffb9a06935a89a6454fcaa40c69becf9f8029a271fd252ea55307d00d6e97a30719d48d6b7f993af24e9c54381cba02a113238eaee9d741cababeb21aaf", + "0x00877497444274267a4ea6f42deefde23a12e44f1ec1b437018e5c0e2834ce376dec1b81ebeacf5fbc6882e69af7cafad47bbb96cfb09e8d77d12afff7543052" ], "gasLimit": "50,000,000", "gasPrice": "0" }, "expect": { - "out": [ - "0x00" - ], - "status": "", + "out": [], + "status": "10", + "message": "str:signature verification failed", "logs": "*", "gas": "*", "refund": "*" From f58b4f3fbcb8f87950a9be593a0f885e32f9de2b Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Sun, 1 Sep 2024 01:55:33 +0300 Subject: [PATCH 76/92] crypto_verify_bls_share test fix --- .../crypto_verify_bls_share.scen.json | 44 ++++--------------- 1 file changed, 9 insertions(+), 35 deletions(-) diff --git a/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_share.scen.json b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_share.scen.json index 046b015d86..6aa653a9cd 100644 --- a/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_share.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_share.scen.json @@ -1,6 +1,6 @@ { "name": "crypto", - "comment": "does not currently work with scenarios-rs, because verify_bls function is not yet mocked", + "comment": "does not currently work with scenarios-rs, because function is not yet mocked", "gasSchedule": "v3", "steps": [ { @@ -19,7 +19,7 @@ }, { "step": "scCall", - "id": "1", + "id": "verify_bls_signature_share - Ok", "tx": { "from": "address:an_account", "to": "sc:basic-features-crypto", @@ -44,49 +44,23 @@ }, { "step": "scCall", - "id": "2", + "id": "verify_bls_signature_share - Fail", "tx": { "from": "address:an_account", "to": "sc:basic-features-crypto", "function": "verify_bls_signature_share", "arguments": [ - "0x2c9a358953f61d34401d7ee4175eec105c476b18baacab371e2f47270035b539d84ad79ba587552b7e38802be00ff7148fc2a9c7a7034ff1e63ee24602ee952235ad14ca7d36e2be617fb2c99ed22a7a2729d86ae9fbb4df06f957ba07fec50e", - "0x1e46d9cbb995e30b82485525c29f80ac78aca295a6e88a11c3df8f9a445494bb", - "0xbe8c460db180d6254c712ead3aa81935bc9be15b919dd45cb152b3dece04762569778c5e70e7af03fa1c66409d4f4711" - ], - "gasLimit": "50,000,000", - "gasPrice": "0" - }, - "expect": { - "out": [ - "0x00" - ], - "status": "", - "logs": "*", - "gas": "*", - "refund": "*" - } - }, - { - "step": "scCall", - "id": "2", - "tx": { - "from": "address:an_account", - "to": "sc:basic-features", - "function": "verify_bls_aggregated_signature", - "arguments": [ - "0xb5823f6e564251cc03ce7bad3da83e72576e92795d3500bba1acb30ec9a94dce87bb8aa794d67b2d61d15c33f28f6c0c23ba1dfcbf21e8f8b46286ff871afabac925303ddcaddce6254fcff6d3155797db40b3d3b5865e8fc0bd770b3d79b381", - "0x6d65737361676520746f206265207369676e6564", - "0xaf32a2ddf341c08d1eb7232f05dc34e4454155e676b58c40fddf9a036562ac2c01533d2d557cb49d73aa9d7a89744696" + "0x3e886a4c6e109a151f4105aee65a5192d150ef1fa68d3cd76964a0b086006dbe4324c989deb0e4416c6d6706db1b1910eb2732f08842fb4886067b9ed191109ac2188d76002d2e11da80a3f0ea89fee6b59c834cc478a6bd49cb8a193b1abb16", + "0xe96bd0f36b70c5ccc0c4396343bd7d8255b8a526c55fa1e218511fafe6539b8e", + "0xff725db195e37aa237cdbbda76270d4a229b6e7a3651104dc58c4349c0388e8546976fe54a04240530b99064e434c90f" ], "gasLimit": "50,000,000", "gasPrice": "0" }, "expect": { - "out": [ - "0x01" - ], - "status": "", + "out": [], + "status": "10", + "message": "str:err blsSignatureDeserialize ff725db195e37aa237cdbbda76270d4a229b6e7a3651104dc58c4349c0388e8546976fe54a04240530b99064e434c90f", "logs": "*", "gas": "*", "refund": "*" From d31643cc848e6e4671031da9283841e9d79fde70 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Sun, 1 Sep 2024 02:33:54 +0300 Subject: [PATCH 77/92] crypto functions that fail directly no longer return bool --- .../scenarios/crypto_verify_bls.scen.json | 32 ++++++++++++++++--- ..._verify_bls_aggregated_signature.scen.json | 6 ++-- .../crypto_verify_bls_share.scen.json | 6 ++-- .../crypto_verify_secp256r1.scen.json | 7 ++-- .../managed_decimal_logarithm.scen.json | 2 +- .../basic-features/src/crypto_features.rs | 8 ++--- framework/base/src/api/crypto_api.rs | 8 ++--- .../api/uncallable/crypto_api_uncallable.rs | 8 ++--- .../contract_base/wrappers/crypto_wrapper.rs | 25 +++++++++++---- .../src/api/core_api_vh/crypto_api_vh.rs | 8 ++--- .../wasm-adapter/src/api/crypto_api_node.rs | 24 +++++++++----- 11 files changed, 84 insertions(+), 50 deletions(-) diff --git a/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls.scen.json b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls.scen.json index f5c6ef194c..fc67a3745b 100644 --- a/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls.scen.json @@ -19,7 +19,7 @@ }, { "step": "scCall", - "id": "3", + "id": "verify_bls_signature - Ok", "tx": { "from": "address:an_account", "to": "sc:basic-features", @@ -33,14 +33,36 @@ "gasPrice": "0" }, "expect": { - "out": [ - "0x01" - ], + "out": [], "status": "", "logs": "*", "gas": "*", "refund": "*" } + }, + { + "step": "scCall", + "id": "verify_bls_signature - Fail", + "tx": { + "from": "address:an_account", + "to": "sc:basic-features", + "function": "verify_bls_signature", + "arguments": [ + "0xb5823f6e564251cc03ce7bad3da83e72576e92795d3500bba1acb30ec9a94dce87bb8aa794d67b2d61d15c33f28f6c0c23ba1dfcbf21e8f8b46286ff871afabac925303ddcaddce6254fcff6d3155797db40b3d3b5865e8fc0bd770b3d79b381", + "0x6d65737361676520746f206265207369676e6564", + "0x0032a2ddf341c08d1eb7232f05dc34e4454155e676b58c40fddf9a036562ac2c01533d2d557cb49d73aa9d7a89744696" + ], + "gasLimit": "50,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [], + "status": "10", + "message": "str:err blsSignatureDeserialize 0032a2ddf341c08d1eb7232f05dc34e4454155e676b58c40fddf9a036562ac2c01533d2d557cb49d73aa9d7a89744696", + "logs": "*", + "gas": "*", + "refund": "*" + } } ] -} \ No newline at end of file +} diff --git a/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_aggregated_signature.scen.json b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_aggregated_signature.scen.json index d8e46f2389..546c0d4c9f 100644 --- a/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_aggregated_signature.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_aggregated_signature.scen.json @@ -39,9 +39,7 @@ "gasPrice": "0" }, "expect": { - "out": [ - "true" - ], + "out": [], "status": "", "logs": "*", "gas": "*", @@ -79,4 +77,4 @@ } } ] -} \ No newline at end of file +} diff --git a/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_share.scen.json b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_share.scen.json index 6aa653a9cd..fa7c21611b 100644 --- a/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_share.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_share.scen.json @@ -33,9 +33,7 @@ "gasPrice": "0" }, "expect": { - "out": [ - "0x01" - ], + "out": [], "status": "", "logs": "*", "gas": "*", @@ -67,4 +65,4 @@ } } ] -} \ No newline at end of file +} diff --git a/contracts/feature-tests/basic-features/scenarios/crypto_verify_secp256r1.scen.json b/contracts/feature-tests/basic-features/scenarios/crypto_verify_secp256r1.scen.json index c1287b32d9..1c35b46271 100644 --- a/contracts/feature-tests/basic-features/scenarios/crypto_verify_secp256r1.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/crypto_verify_secp256r1.scen.json @@ -1,6 +1,5 @@ { "name": "crypto", - "comment": "", "gasSchedule": "v3", "steps": [ { @@ -33,9 +32,7 @@ "gasPrice": "0" }, "expect": { - "out": [ - "true" - ], + "out": [], "status": "", "logs": "*", "gas": "*", @@ -67,4 +64,4 @@ } } ] -} \ No newline at end of file +} diff --git a/contracts/feature-tests/basic-features/scenarios/managed_decimal_logarithm.scen.json b/contracts/feature-tests/basic-features/scenarios/managed_decimal_logarithm.scen.json index da54f8ccec..065e92988c 100644 --- a/contracts/feature-tests/basic-features/scenarios/managed_decimal_logarithm.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/managed_decimal_logarithm.scen.json @@ -24,7 +24,7 @@ "arguments": [ "23,000000000" ], - "gasLimit": "9,000,000", + "gasLimit": "25,000,000", "gasPrice": "0" }, "expect": { diff --git a/contracts/feature-tests/basic-features/src/crypto_features.rs b/contracts/feature-tests/basic-features/src/crypto_features.rs index 8da0c83984..0588146780 100644 --- a/contracts/feature-tests/basic-features/src/crypto_features.rs +++ b/contracts/feature-tests/basic-features/src/crypto_features.rs @@ -24,7 +24,7 @@ pub trait CryptoFeatures { key: ManagedBuffer, message: ManagedBuffer, signature: ManagedBuffer, - ) -> bool { + ) { self.crypto().verify_bls(&key, &message, &signature) } @@ -72,7 +72,7 @@ pub trait CryptoFeatures { key: ManagedBuffer, message: ManagedBuffer, signature: ManagedBuffer, - ) -> bool { + ) { self.crypto().verify_secp256r1(&key, &message, &signature) } @@ -83,7 +83,7 @@ pub trait CryptoFeatures { key: ManagedBuffer, message: ManagedBuffer, signature: ManagedBuffer, - ) -> bool { + ) { self.crypto() .verify_bls_signature_share(&key, &message, &signature) } @@ -95,7 +95,7 @@ pub trait CryptoFeatures { key: ManagedVec, message: ManagedBuffer, signature: ManagedBuffer, - ) -> bool { + ) { self.crypto() .verify_bls_aggregated_signature(&key, &message, &signature) } diff --git a/framework/base/src/api/crypto_api.rs b/framework/base/src/api/crypto_api.rs index 235e44919a..f6eaf80fe4 100644 --- a/framework/base/src/api/crypto_api.rs +++ b/framework/base/src/api/crypto_api.rs @@ -44,7 +44,7 @@ pub trait CryptoApiImpl: ManagedTypeApiImpl { key: Self::ManagedBufferHandle, message: Self::ManagedBufferHandle, signature: Self::ManagedBufferHandle, - ) -> bool; + ); fn verify_ed25519_managed( &self, @@ -82,19 +82,19 @@ pub trait CryptoApiImpl: ManagedTypeApiImpl { key: Self::ManagedBufferHandle, message: Self::ManagedBufferHandle, signature: Self::ManagedBufferHandle, - ) -> bool; + ); fn verify_bls_signature_share_managed( &self, key: Self::ManagedBufferHandle, message: Self::ManagedBufferHandle, signature: Self::ManagedBufferHandle, - ) -> bool; + ); fn verify_bls_aggregated_signature_managed( &self, key: Self::ManagedBufferHandle, message: Self::ManagedBufferHandle, signature: Self::ManagedBufferHandle, - ) -> bool; + ); } diff --git a/framework/base/src/api/uncallable/crypto_api_uncallable.rs b/framework/base/src/api/uncallable/crypto_api_uncallable.rs index bb42aa04bb..fe0547c5d7 100644 --- a/framework/base/src/api/uncallable/crypto_api_uncallable.rs +++ b/framework/base/src/api/uncallable/crypto_api_uncallable.rs @@ -42,7 +42,7 @@ impl CryptoApiImpl for UncallableApi { _key: Self::ManagedBufferHandle, _message: Self::ManagedBufferHandle, _signature: Self::ManagedBufferHandle, - ) -> bool { + ) { unreachable!() } @@ -88,7 +88,7 @@ impl CryptoApiImpl for UncallableApi { _key: Self::ManagedBufferHandle, _message: Self::ManagedBufferHandle, _signature: Self::ManagedBufferHandle, - ) -> bool { + ) { unreachable!() } @@ -97,7 +97,7 @@ impl CryptoApiImpl for UncallableApi { _key: Self::ManagedBufferHandle, _message: Self::ManagedBufferHandle, _signature: Self::ManagedBufferHandle, - ) -> bool { + ) { unreachable!() } @@ -106,7 +106,7 @@ impl CryptoApiImpl for UncallableApi { _key: Self::ManagedBufferHandle, _message: Self::ManagedBufferHandle, _signature: Self::ManagedBufferHandle, - ) -> bool { + ) { unreachable!() } } diff --git a/framework/base/src/contract_base/wrappers/crypto_wrapper.rs b/framework/base/src/contract_base/wrappers/crypto_wrapper.rs index eb98f93a56..369cca1a63 100644 --- a/framework/base/src/contract_base/wrappers/crypto_wrapper.rs +++ b/framework/base/src/contract_base/wrappers/crypto_wrapper.rs @@ -61,7 +61,7 @@ where key: &ManagedBuffer, message: &ManagedBuffer, signature: &ManagedBuffer, - ) -> bool { + ) { A::crypto_api_impl().verify_bls_managed( key.get_handle(), message.get_handle(), @@ -69,7 +69,9 @@ where ) } - /// Will crash if the verification fails. + /// Calls the Vm to verify ed25519 signature. + /// + /// Does not return result, will fail tx directly! /// /// The error comes straight form the VM, the message is "invalid signature". pub fn verify_ed25519( @@ -130,12 +132,15 @@ where ManagedBuffer::from_handle(new_handle) } + /// Calls the Vm to verify secp256r1 signature. + /// + /// Does not return result, will fail tx directly! pub fn verify_secp256r1( &self, key: &ManagedBuffer, message: &ManagedBuffer, signature: &ManagedBuffer, - ) -> bool { + ) { A::crypto_api_impl().verify_secp256r1_managed( key.get_handle(), message.get_handle(), @@ -143,12 +148,15 @@ where ) } + /// Calls the Vm to verify BLS signature share. + /// + /// Does not return result, will fail tx directly! pub fn verify_bls_signature_share( &self, key: &ManagedBuffer, message: &ManagedBuffer, signature: &ManagedBuffer, - ) -> bool { + ) { A::crypto_api_impl().verify_bls_signature_share_managed( key.get_handle(), message.get_handle(), @@ -156,14 +164,17 @@ where ) } + /// Calls the Vm to verify BLS aggregated signature. + /// + /// Does not return result, will fail tx directly! pub fn verify_bls_aggregated_signature( &self, - key: &ManagedVec>, + keys: &ManagedVec>, message: &ManagedBuffer, signature: &ManagedBuffer, - ) -> bool { + ) { A::crypto_api_impl().verify_bls_aggregated_signature_managed( - key.get_handle(), + keys.get_handle(), message.get_handle(), signature.get_handle(), ) diff --git a/framework/scenario/src/api/core_api_vh/crypto_api_vh.rs b/framework/scenario/src/api/core_api_vh/crypto_api_vh.rs index aa4c2dab94..305b3d6be9 100644 --- a/framework/scenario/src/api/core_api_vh/crypto_api_vh.rs +++ b/framework/scenario/src/api/core_api_vh/crypto_api_vh.rs @@ -53,7 +53,7 @@ impl CryptoApiImpl for VMHooksApi { _key: Self::ManagedBufferHandle, _message: Self::ManagedBufferHandle, _signature: Self::ManagedBufferHandle, - ) -> bool { + ) { panic!("verify_bls not implemented yet!") } @@ -105,7 +105,7 @@ impl CryptoApiImpl for VMHooksApi { _key: Self::ManagedBufferHandle, _message: Self::ManagedBufferHandle, _signature: Self::ManagedBufferHandle, - ) -> bool { + ) { panic!("verify_secp256r1 not implemented yet!") } @@ -114,7 +114,7 @@ impl CryptoApiImpl for VMHooksApi { _key: Self::ManagedBufferHandle, _message: Self::ManagedBufferHandle, _signature: Self::ManagedBufferHandle, - ) -> bool { + ) { panic!("verify_bls_signature_share not implemented yet!") } @@ -123,7 +123,7 @@ impl CryptoApiImpl for VMHooksApi { _key: Self::ManagedBufferHandle, _message: Self::ManagedBufferHandle, _signature: Self::ManagedBufferHandle, - ) -> bool { + ) { panic!("verify_bls_aggregated_signature not implemented yet!") } } diff --git a/framework/wasm-adapter/src/api/crypto_api_node.rs b/framework/wasm-adapter/src/api/crypto_api_node.rs index 0cbe24fad5..df62b30df9 100644 --- a/framework/wasm-adapter/src/api/crypto_api_node.rs +++ b/framework/wasm-adapter/src/api/crypto_api_node.rs @@ -84,8 +84,10 @@ impl CryptoApiImpl for VmApiImpl { key: Self::ManagedBufferHandle, message: Self::ManagedBufferHandle, signature: Self::ManagedBufferHandle, - ) -> bool { - unsafe { managedVerifyBLS(key, message, signature) == 0 } + ) { + unsafe { + let _ = managedVerifyBLS(key, message, signature); + } } #[inline] @@ -139,8 +141,10 @@ impl CryptoApiImpl for VmApiImpl { key: Self::ManagedBufferHandle, message: Self::ManagedBufferHandle, signature: Self::ManagedBufferHandle, - ) -> bool { - unsafe { managedVerifySecp256r1(key, message, signature) == 0 } + ) { + unsafe { + let _ = managedVerifySecp256r1(key, message, signature); + } } fn verify_bls_signature_share_managed( @@ -148,8 +152,10 @@ impl CryptoApiImpl for VmApiImpl { key: Self::ManagedBufferHandle, message: Self::ManagedBufferHandle, signature: Self::ManagedBufferHandle, - ) -> bool { - unsafe { managedVerifyBLSSignatureShare(key, message, signature) == 0 } + ) { + unsafe { + let _ = managedVerifyBLSSignatureShare(key, message, signature); + } } fn verify_bls_aggregated_signature_managed( @@ -157,7 +163,9 @@ impl CryptoApiImpl for VmApiImpl { key: Self::ManagedBufferHandle, message: Self::ManagedBufferHandle, signature: Self::ManagedBufferHandle, - ) -> bool { - unsafe { managedVerifyBLSAggregatedSignature(key, message, signature) == 0 } + ) { + unsafe { + let _ = managedVerifyBLSAggregatedSignature(key, message, signature); + } } } From 0b43a3bafeb1e8dc3447e576291a66e23e77707b Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Sun, 1 Sep 2024 02:34:06 +0300 Subject: [PATCH 78/92] scenario fmt --- .../basic-features/scenarios/managed_decimal.scen.json | 2 +- .../scenarios/managed_decimal_logarithm.scen.json | 2 +- .../scenarios/storage_mapper_get_at_address.scen.json | 2 +- .../scenarios/storage_mapper_get_at_address_extra_key.scen.json | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/contracts/feature-tests/basic-features/scenarios/managed_decimal.scen.json b/contracts/feature-tests/basic-features/scenarios/managed_decimal.scen.json index e19612ae29..b723c07b6d 100644 --- a/contracts/feature-tests/basic-features/scenarios/managed_decimal.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/managed_decimal.scen.json @@ -143,4 +143,4 @@ } } ] -} \ No newline at end of file +} diff --git a/contracts/feature-tests/basic-features/scenarios/managed_decimal_logarithm.scen.json b/contracts/feature-tests/basic-features/scenarios/managed_decimal_logarithm.scen.json index 065e92988c..193517275c 100644 --- a/contracts/feature-tests/basic-features/scenarios/managed_decimal_logarithm.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/managed_decimal_logarithm.scen.json @@ -107,4 +107,4 @@ } } ] -} \ No newline at end of file +} diff --git a/contracts/feature-tests/basic-features/scenarios/storage_mapper_get_at_address.scen.json b/contracts/feature-tests/basic-features/scenarios/storage_mapper_get_at_address.scen.json index 77ffdda1ee..2a0ff501a8 100644 --- a/contracts/feature-tests/basic-features/scenarios/storage_mapper_get_at_address.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/storage_mapper_get_at_address.scen.json @@ -372,4 +372,4 @@ } } ] -} \ No newline at end of file +} diff --git a/contracts/feature-tests/basic-features/scenarios/storage_mapper_get_at_address_extra_key.scen.json b/contracts/feature-tests/basic-features/scenarios/storage_mapper_get_at_address_extra_key.scen.json index e124fd7e1a..d2802f41d2 100644 --- a/contracts/feature-tests/basic-features/scenarios/storage_mapper_get_at_address_extra_key.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/storage_mapper_get_at_address_extra_key.scen.json @@ -87,4 +87,4 @@ } } ] -} \ No newline at end of file +} From e711f65f5f9a3e307cb1f614820d242c72842ba7 Mon Sep 17 00:00:00 2001 From: Andrei Vasilescu Date: Mon, 2 Sep 2024 12:40:58 +0300 Subject: [PATCH 79/92] Refactored system SC proxies Co-authored-by: Mihai Blacioti --- .../system_proxy/builtin_func_proxy.rs | 45 ++-- .../system_proxy/esdt_system_sc_proxy.rs | 196 +++++++++----- .../src/system_sc_interact.rs | 246 ++++++++---------- 3 files changed, 265 insertions(+), 222 deletions(-) diff --git a/framework/base/src/types/interaction/system_proxy/builtin_func_proxy.rs b/framework/base/src/types/interaction/system_proxy/builtin_func_proxy.rs index 7b5e2fefb2..6e4978980a 100644 --- a/framework/base/src/types/interaction/system_proxy/builtin_func_proxy.rs +++ b/framework/base/src/types/interaction/system_proxy/builtin_func_proxy.rs @@ -82,11 +82,14 @@ where .original_result() } - pub fn esdt_local_burn( + pub fn esdt_local_burn< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + >( self, - token: &TokenIdentifier, + token: &Arg0, nonce: u64, - amount: &BigUint, + amount: &Arg1, ) -> TxTypedCall { if nonce == 0 { return self @@ -107,11 +110,14 @@ where .original_result() } - pub fn esdt_local_mint( + pub fn esdt_local_mint< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + >( self, - token: &TokenIdentifier, + token: &Arg0, nonce: u64, - amount: &BigUint, + amount: &Arg1, ) -> TxTypedCall { if nonce == 0 { return self @@ -131,9 +137,9 @@ where .original_result() } - pub fn nft_add_multiple_uri( + pub fn nft_add_multiple_uri>>( self, - token_id: &TokenIdentifier, + token_id: &Arg0, nft_nonce: u64, new_uris: &ManagedVec>, ) -> TxTypedCall { @@ -151,9 +157,9 @@ where tx.original_result() } - pub fn nft_update_attributes( + pub fn nft_update_attributes>>( self, - token_id: &TokenIdentifier, + token_id: &Arg0, nft_nonce: u64, new_attributes: &T, ) -> TxTypedCall { @@ -167,13 +173,20 @@ where } #[allow(clippy::too_many_arguments)] - pub fn esdt_nft_create( + pub fn esdt_nft_create< + T: TopEncode, + Arg0: ProxyArg>, + Arg1: ProxyArg>, + Arg2: ProxyArg>, + Arg3: ProxyArg>, + Arg4: ProxyArg>, + >( self, - token: &TokenIdentifier, - amount: &BigUint, - name: &ManagedBuffer, - royalties: &BigUint, - hash: &ManagedBuffer, + token: &Arg0, + amount: &Arg1, + name: &Arg2, + royalties: &Arg3, + hash: &Arg4, attributes: &T, uris: &ManagedVec>, ) -> TxTypedCall { diff --git a/framework/base/src/types/interaction/system_proxy/esdt_system_sc_proxy.rs b/framework/base/src/types/interaction/system_proxy/esdt_system_sc_proxy.rs index 50325ed78d..10730ff0fc 100644 --- a/framework/base/src/types/interaction/system_proxy/esdt_system_sc_proxy.rs +++ b/framework/base/src/types/interaction/system_proxy/esdt_system_sc_proxy.rs @@ -4,8 +4,8 @@ use crate::{ api::CallTypeApi, types::{ BigUint, EgldPayment, EsdtLocalRole, EsdtTokenType, FunctionCall, ManagedAddress, - ManagedBuffer, NotPayable, OriginalResultMarker, TokenIdentifier, Tx, TxEnv, TxFrom, TxGas, - TxProxyTrait, TxTo, TxTypedCall, + ManagedBuffer, NotPayable, OriginalResultMarker, ProxyArg, TokenIdentifier, Tx, TxEnv, + TxFrom, TxGas, TxProxyTrait, TxTo, TxTypedCall, }, }; @@ -63,12 +63,16 @@ where { /// Produces a contract call to the ESDT system SC, /// which causes it to issue a new fungible ESDT token. - pub fn issue_fungible( + pub fn issue_fungible< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + Arg2: ProxyArg>, + >( self, issue_cost: BigUint, - token_display_name: &ManagedBuffer, - token_ticker: &ManagedBuffer, - initial_supply: &BigUint, + token_display_name: &Arg0, + token_ticker: &Arg1, + initial_supply: &Arg2, properties: FungibleTokenProperties, ) -> IssueCall { self.issue( @@ -94,20 +98,23 @@ where /// Produces a contract call to the ESDT system SC, /// which causes it to issue a new non-fungible ESDT token. - pub fn issue_non_fungible( + pub fn issue_non_fungible< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + >( self, issue_cost: BigUint, - token_display_name: &ManagedBuffer, - token_ticker: &ManagedBuffer, + token_display_name: &Arg0, + token_ticker: &Arg1, properties: NonFungibleTokenProperties, ) -> IssueCall { - let zero = BigUint::zero_ref(); + let zero = &BigUint::zero(); self.issue( issue_cost, EsdtTokenType::NonFungible, token_display_name, token_ticker, - &zero, + zero, TokenProperties { num_decimals: 0, can_freeze: properties.can_freeze, @@ -125,11 +132,14 @@ where /// Produces a contract call to the ESDT system SC, /// which causes it to issue a new semi-fungible ESDT token. - pub fn issue_semi_fungible( + pub fn issue_semi_fungible< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + >( self, issue_cost: BigUint, - token_display_name: &ManagedBuffer, - token_ticker: &ManagedBuffer, + token_display_name: &Arg0, + token_ticker: &Arg1, properties: SemiFungibleTokenProperties, ) -> IssueCall { let zero = BigUint::zero(); @@ -156,20 +166,23 @@ where /// Produces a contract call to the ESDT system SC, /// which causes it to register a new Meta ESDT token. - pub fn register_meta_esdt( + pub fn register_meta_esdt< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + >( self, issue_cost: BigUint, - token_display_name: &ManagedBuffer, - token_ticker: &ManagedBuffer, + token_display_name: &Arg0, + token_ticker: &Arg1, properties: MetaTokenProperties, ) -> IssueCall { - let zero = BigUint::zero(); + let zero = &BigUint::zero(); self.issue( issue_cost, EsdtTokenType::Meta, token_display_name, token_ticker, - &zero, + zero, TokenProperties { num_decimals: properties.num_decimals, can_freeze: properties.can_freeze, @@ -185,11 +198,14 @@ where ) } - pub fn issue_and_set_all_roles( + pub fn issue_and_set_all_roles< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + >( self, issue_cost: BigUint, - token_display_name: ManagedBuffer, - token_ticker: ManagedBuffer, + token_display_name: Arg0, + token_ticker: Arg1, token_type: EsdtTokenType, num_decimals: usize, ) -> IssueCall { @@ -212,13 +228,17 @@ where } /// Deduplicates code from all the possible issue functions - fn issue( + fn issue< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + Arg2: ProxyArg>, + >( self, issue_cost: BigUint, token_type: EsdtTokenType, - token_display_name: &ManagedBuffer, - token_ticker: &ManagedBuffer, - initial_supply: &BigUint, + token_display_name: &Arg0, + token_ticker: &Arg1, + initial_supply: &Arg2, properties: TokenProperties, ) -> IssueCall { let endpoint_name = match token_type { @@ -268,10 +288,10 @@ where /// Produces a contract call to the ESDT system SC, /// which causes it to mint more fungible ESDT tokens. /// It will fail if the SC is not the owner of the token. - pub fn mint( + pub fn mint>, Arg1: ProxyArg>>( self, - token_identifier: &TokenIdentifier, - amount: &BigUint, + token_identifier: &Arg0, + amount: &Arg1, ) -> TxTypedCall { self.wrapped_tx .payment(NotPayable) @@ -283,10 +303,10 @@ where /// Produces a contract call to the ESDT system SC, /// which causes it to burn fungible ESDT tokens owned by the SC. - pub fn burn( + pub fn burn>, Arg1: ProxyArg>>( self, - token_identifier: &TokenIdentifier, - amount: &BigUint, + token_identifier: &Arg0, + amount: &Arg1, ) -> TxTypedCall { self.wrapped_tx .payment(NotPayable) @@ -298,9 +318,9 @@ where /// The manager of an ESDT token may choose to suspend all transactions of the token, /// except minting, freezing/unfreezing and wiping. - pub fn pause( + pub fn pause>>( self, - token_identifier: &TokenIdentifier, + token_identifier: &Arg0, ) -> TxTypedCall { self.wrapped_tx .payment(NotPayable) @@ -310,9 +330,9 @@ where } /// The reverse operation of `pause`. - pub fn unpause( + pub fn unpause>>( self, - token_identifier: &TokenIdentifier, + token_identifier: &Arg0, ) -> TxTypedCall { self.wrapped_tx .payment(NotPayable) @@ -324,10 +344,13 @@ where /// The manager of an ESDT token may freeze the tokens held by a specific account. /// As a consequence, no tokens may be transferred to or from the frozen account. /// Freezing and unfreezing the tokens of an account are operations designed to help token managers to comply with regulations. - pub fn freeze( + pub fn freeze< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + >( self, - token_identifier: &TokenIdentifier, - address: &ManagedAddress, + token_identifier: &Arg0, + address: &Arg1, ) -> TxTypedCall { self.wrapped_tx .payment(NotPayable) @@ -338,10 +361,13 @@ where } /// The reverse operation of `freeze`, unfreezing, will allow further transfers to and from the account. - pub fn unfreeze( + pub fn unfreeze< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + >( self, - token_identifier: &TokenIdentifier, - address: &ManagedAddress, + token_identifier: &Arg0, + address: &Arg1, ) -> TxTypedCall { self.wrapped_tx .payment(NotPayable) @@ -355,10 +381,13 @@ where /// This operation is similar to burning the tokens, but the account must have been frozen beforehand, /// and it must be done by the token manager. /// Wiping the tokens of an account is an operation designed to help token managers to comply with regulations. - pub fn wipe( + pub fn wipe< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + >( self, - token_identifier: &TokenIdentifier, - address: &ManagedAddress, + token_identifier: &Arg0, + address: &Arg1, ) -> TxTypedCall { self.wrapped_tx .payment(NotPayable) @@ -371,11 +400,14 @@ where /// The manager of an ESDT token may freeze the NFT held by a specific Account. /// As a consequence, no NFT can be transferred to or from the frozen Account. /// Freezing and unfreezing a single NFT of an Account are operations designed to help token managers to comply with regulations. - pub fn freeze_nft( + pub fn freeze_nft< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + >( self, - token_identifier: &TokenIdentifier, + token_identifier: &Arg0, nft_nonce: u64, - address: &ManagedAddress, + address: &Arg1, ) -> TxTypedCall { self.wrapped_tx .payment(NotPayable) @@ -387,11 +419,14 @@ where } /// The reverse operation of `freeze`, unfreezing, will allow further transfers to and from the account. - pub fn unfreeze_nft( + pub fn unfreeze_nft< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + >( self, - token_identifier: &TokenIdentifier, + token_identifier: &Arg0, nft_nonce: u64, - address: &ManagedAddress, + address: &Arg1, ) -> TxTypedCall { self.wrapped_tx .payment(NotPayable) @@ -406,11 +441,14 @@ where /// This operation is similar to burning the quantity, but the Account must have been frozen beforehand, /// and it must be done by the token manager. /// Wiping the tokens of an Account is an operation designed to help token managers to comply with regulations. - pub fn wipe_nft( + pub fn wipe_nft< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + >( self, - token_identifier: &TokenIdentifier, + token_identifier: &Arg0, nft_nonce: u64, - address: &ManagedAddress, + address: &Arg1, ) -> TxTypedCall { self.wrapped_tx .payment(NotPayable) @@ -423,15 +461,15 @@ where /// This function converts an SFT to a metaESDT by adding decimals to its structure in the metachain ESDT System SC. /// This function as almost all in case of ESDT can be called only by the owner. - pub fn change_sft_to_meta_esdt( + pub fn change_sft_to_meta_esdt>>( self, - token_identifier: &TokenIdentifier, + token_identifier: &Arg0, num_decimals: usize, ) -> TxTypedCall { self.wrapped_tx .payment(NotPayable) .raw_call("changeSFTToMetaESDT") - .argument(&token_identifier) + .argument(token_identifier) .argument(&num_decimals) .original_result() } @@ -440,10 +478,14 @@ where /// The metachain system SC will evaluate the arguments and call “ESDTSetRole@tokenId@listOfRoles” for the given address. /// This will be actually a cross shard call. /// This function as almost all in case of ESDT can be called only by the owner. - pub fn set_special_roles>( + pub fn set_special_roles< + RoleIter: Iterator, + Arg0: ProxyArg>, + Arg1: ProxyArg>, + >( self, - address: &ManagedAddress, - token_identifier: &TokenIdentifier, + address: &Arg0, + token_identifier: &Arg1, roles_iter: RoleIter, ) -> TxTypedCall { let mut tx = self @@ -465,10 +507,14 @@ where /// The metachain system SC will evaluate the arguments and call “ESDTUnsetRole@tokenId@listOfRoles” for the given address. /// This will be actually a cross shard call. /// This function as almost all in case of ESDT can be called only by the owner. - pub fn unset_special_roles>( + pub fn unset_special_roles< + RoleIter: Iterator, + Arg0: ProxyArg>, + Arg1: ProxyArg>, + >( self, - address: &ManagedAddress, - token_identifier: &TokenIdentifier, + address: &Arg0, + token_identifier: &Arg1, roles_iter: RoleIter, ) -> TxTypedCall { let mut tx = self @@ -486,10 +532,13 @@ where tx.original_result() } - pub fn transfer_ownership( + pub fn transfer_ownership< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + >( self, - token_identifier: &TokenIdentifier, - new_owner: &ManagedAddress, + token_identifier: &Arg0, + new_owner: &Arg1, ) -> TxTypedCall { self.wrapped_tx .payment(NotPayable) @@ -499,11 +548,14 @@ where .original_result() } - pub fn transfer_nft_create_role( + pub fn transfer_nft_create_role< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + >( self, - token_identifier: &TokenIdentifier, - old_creator: &ManagedAddress, - new_creator: &ManagedAddress, + token_identifier: &Arg0, + old_creator: &Arg1, + new_creator: &Arg1, ) -> TxTypedCall { self.wrapped_tx .payment(NotPayable) @@ -514,9 +566,9 @@ where .original_result() } - pub fn control_changes( + pub fn control_changes>>( self, - token_identifier: &TokenIdentifier, + token_identifier: &Arg0, property_arguments: &TokenPropertyArguments, ) -> TxTypedCall { let mut tx = self diff --git a/tools/interactor-system-func-calls/src/system_sc_interact.rs b/tools/interactor-system-func-calls/src/system_sc_interact.rs index bda87cd491..0558eba3c1 100644 --- a/tools/interactor-system-func-calls/src/system_sc_interact.rs +++ b/tools/interactor-system-func-calls/src/system_sc_interact.rs @@ -21,8 +21,8 @@ async fn main() { basic_interact .issue_token( args.cost.clone(), - &args.display_name, - &args.ticker, + args.display_name.as_bytes(), + args.ticker.as_bytes(), args.num_decimals, args.token_type.into(), ) @@ -30,13 +30,17 @@ async fn main() { }, Some(system_sc_interact_cli::InteractCliCommand::Mint(args)) => { basic_interact - .mint_token(&args.token_id, args.nonce, args.amount.clone()) + .mint_token( + args.token_id.clone().as_bytes(), + args.nonce, + args.amount.clone(), + ) .await; }, Some(system_sc_interact_cli::InteractCliCommand::SetRoles(args)) => { basic_interact .set_roles( - &args.token_id, + args.token_id.as_bytes(), args.roles .clone() .into_iter() @@ -47,19 +51,19 @@ async fn main() { }, Some(system_sc_interact_cli::InteractCliCommand::Burn(args)) => { basic_interact - .burn_token(&args.token_id, args.nonce, args.amount.clone()) + .burn_token(args.token_id.as_bytes(), args.nonce, args.amount.clone()) .await; }, Some(system_sc_interact_cli::InteractCliCommand::PauseToken(args)) => { - basic_interact.pause_token(&args.token_id).await; + basic_interact.pause_token(args.token_id.as_bytes()).await; }, Some(system_sc_interact_cli::InteractCliCommand::UnpauseToken(args)) => { - basic_interact.unpause_token(&args.token_id).await; + basic_interact.unpause_token(args.token_id.as_bytes()).await; }, Some(system_sc_interact_cli::InteractCliCommand::FreezeToken(args)) => { basic_interact .freeze_token( - &args.token_id, + args.token_id.as_bytes(), &Bech32Address::from_bech32_string(args.address.clone()), ) .await; @@ -67,7 +71,7 @@ async fn main() { Some(system_sc_interact_cli::InteractCliCommand::UnfreezeToken(args)) => { basic_interact .unfreeze_token( - &args.token_id, + args.token_id.as_bytes(), &Bech32Address::from_bech32_string(args.address.clone()), ) .await; @@ -75,7 +79,7 @@ async fn main() { Some(system_sc_interact_cli::InteractCliCommand::FreezeNFT(args)) => { basic_interact .freeze_nft( - &args.token_id, + args.token_id.as_bytes(), args.nft_nonce, &Bech32Address::from_bech32_string(args.address.clone()), ) @@ -84,7 +88,7 @@ async fn main() { Some(system_sc_interact_cli::InteractCliCommand::UnfreezeNFT(args)) => { basic_interact .unfreeze_nft( - &args.token_id, + args.token_id.as_bytes(), args.nft_nonce, &Bech32Address::from_bech32_string(args.address.clone()), ) @@ -93,7 +97,7 @@ async fn main() { Some(system_sc_interact_cli::InteractCliCommand::WipeToken(args)) => { basic_interact .wipe_token( - &args.token_id, + args.token_id.as_bytes(), &Bech32Address::from_bech32_string(args.address.clone()), ) .await; @@ -101,7 +105,7 @@ async fn main() { Some(system_sc_interact_cli::InteractCliCommand::WipeNFT(args)) => { basic_interact .wipe_nft( - &args.token_id, + args.token_id.as_bytes(), args.nft_nonce, &Bech32Address::from_bech32_string(args.address.clone()), ) @@ -109,17 +113,21 @@ async fn main() { }, Some(system_sc_interact_cli::InteractCliCommand::IssueNFTCollection(args)) => { basic_interact - .issue_non_fungible_collection(args.cost.clone(), &args.display_name, &args.ticker) + .issue_non_fungible_collection( + args.cost.clone(), + args.display_name.as_bytes(), + args.ticker.as_bytes(), + ) .await; }, Some(system_sc_interact_cli::InteractCliCommand::CreateNFT(args)) => { basic_interact .mint_nft( - &args.token_id, + args.token_id.as_bytes(), args.amount.clone(), - &args.name, + args.name.as_bytes(), args.royalties, - &args.hash, + args.hash.as_bytes(), ) .await; }, @@ -127,8 +135,8 @@ async fn main() { basic_interact .issue_fungible_token( args.cost.clone(), - &args.display_name, - &args.ticker, + args.display_name.as_bytes(), + args.ticker.as_bytes(), args.supply.clone(), args.num_decimals, ) @@ -136,17 +144,21 @@ async fn main() { }, Some(system_sc_interact_cli::InteractCliCommand::IssueSftCollection(args)) => { basic_interact - .issue_semi_fungible_collection(args.cost.clone(), &args.display_name, &args.ticker) + .issue_semi_fungible_collection( + args.cost.clone(), + args.display_name.as_bytes(), + args.ticker.as_bytes(), + ) .await; }, Some(system_sc_interact_cli::InteractCliCommand::MintSft(args)) => { basic_interact .mint_sft( - &args.token_id, + args.token_id.as_bytes(), args.amount.clone(), - &args.name, + args.name.as_bytes(), args.royalties, - &args.hash, + args.hash.as_bytes(), ) .await; }, @@ -154,22 +166,22 @@ async fn main() { basic_interact .register_meta_esdt( args.cost.clone(), - &args.display_name, - &args.ticker, + args.display_name.as_bytes(), + args.ticker.as_bytes(), args.num_decimals, ) .await; }, Some(system_sc_interact_cli::InteractCliCommand::ChangeSftMetaEsdt(args)) => { basic_interact - .change_sft_meta_esdt(&args.token_id, args.num_decimals) + .change_sft_meta_esdt(args.token_id.as_bytes(), args.num_decimals) .await; }, Some(system_sc_interact_cli::InteractCliCommand::UnsetRoles(args)) => { basic_interact .unset_roles( &Bech32Address::from_bech32_string(args.address.clone()), - &args.token_id, + args.token_id.as_bytes(), args.roles .clone() .into_iter() @@ -181,7 +193,7 @@ async fn main() { Some(system_sc_interact_cli::InteractCliCommand::TransferOwnership(args)) => { basic_interact .transfer_ownership( - &args.token_id, + args.token_id.as_bytes(), &Bech32Address::from_bech32_string(args.new_owner.clone()), ) .await; @@ -189,14 +201,16 @@ async fn main() { Some(system_sc_interact_cli::InteractCliCommand::TransferNftCreateRole(args)) => { basic_interact .transfer_nft_create_role( - &args.token_id, + args.token_id.as_bytes(), &Bech32Address::from_bech32_string(args.old_owner.clone()), &Bech32Address::from_bech32_string(args.new_owner.clone()), ) .await; }, Some(system_sc_interact_cli::InteractCliCommand::ControlChanges(args)) => { - basic_interact.control_changes(&args.token_id).await; + basic_interact + .control_changes(args.token_id.as_bytes()) + .await; }, None => {}, @@ -227,8 +241,8 @@ impl SysFuncCallsInteract { async fn issue_fungible_token( &mut self, issue_cost: RustBigUint, - token_display_name: &str, - token_ticker: &str, + token_display_name: &[u8], + token_ticker: &[u8], initial_supply: RustBigUint, num_decimals: usize, ) { @@ -243,9 +257,9 @@ impl SysFuncCallsInteract { .typed(ESDTSystemSCProxy) .issue_fungible( issue_cost.into(), - &token_display_name.into(), - &token_ticker.into(), - &initial_supply.into(), + &token_display_name, + &token_ticker, + &initial_supply, FungibleTokenProperties { num_decimals, can_freeze: true, @@ -269,8 +283,8 @@ impl SysFuncCallsInteract { async fn issue_non_fungible_collection( &mut self, issue_cost: RustBigUint, - token_display_name: &str, - token_ticker: &str, + token_display_name: &[u8], + token_ticker: &[u8], ) { println!("Issuing NFT Collection..."); @@ -283,8 +297,8 @@ impl SysFuncCallsInteract { .typed(ESDTSystemSCProxy) .issue_non_fungible( issue_cost.into(), - &token_display_name.into(), - &token_ticker.into(), + &token_display_name, + &token_ticker, NonFungibleTokenProperties { can_freeze: true, can_wipe: true, @@ -306,8 +320,8 @@ impl SysFuncCallsInteract { async fn issue_semi_fungible_collection( &mut self, issue_cost: RustBigUint, - token_display_name: &str, - token_ticker: &str, + token_display_name: &[u8], + token_ticker: &[u8], ) { println!("Issuing SFT Collection..."); @@ -320,8 +334,8 @@ impl SysFuncCallsInteract { .typed(ESDTSystemSCProxy) .issue_semi_fungible( issue_cost.into(), - &token_display_name.into(), - &token_ticker.into(), + &token_display_name, + &token_ticker, SemiFungibleTokenProperties { can_freeze: true, can_wipe: true, @@ -343,8 +357,8 @@ impl SysFuncCallsInteract { async fn issue_token( &mut self, issue_cost: RustBigUint, - token_display_name: &str, - token_ticker: &str, + token_display_name: &[u8], + token_ticker: &[u8], num_decimals: usize, token_type: EsdtTokenType, ) { @@ -359,8 +373,8 @@ impl SysFuncCallsInteract { .typed(ESDTSystemSCProxy) .issue_and_set_all_roles( issue_cost.into(), - token_display_name.into(), - token_ticker.into(), + token_display_name, + token_ticker, token_type, num_decimals, ) @@ -372,7 +386,7 @@ impl SysFuncCallsInteract { println!("TOKEN ID: {:?}", token_id); } - async fn set_roles(&mut self, token_id: &str, roles: Vec) { + async fn set_roles(&mut self, token_id: &[u8], roles: Vec) { let wallet_address = &self.wallet_address.clone().into_address(); println!("Setting the following roles: {:?}", roles); @@ -394,11 +408,11 @@ impl SysFuncCallsInteract { async fn mint_sft( &mut self, - token_id: &str, + token_id: &[u8], amount: RustBigUint, - name: &str, + name: &[u8], royalties: u64, - hash: &str, + hash: &[u8], ) { println!("Minting SFT..."); @@ -409,11 +423,11 @@ impl SysFuncCallsInteract { .gas(100_000_000u64) .typed(UserBuiltinProxy) .esdt_nft_create( - &TokenIdentifier::from(token_id), - &BigUint::from(amount), - &ManagedBuffer::from(name), - &royalties.into(), - &ManagedBuffer::from(hash), + &token_id, + &amount, + &name, + &royalties, + &hash, &NftDummyAttributes { creation_epoch: 2104, cool_factor: 5, @@ -428,8 +442,8 @@ impl SysFuncCallsInteract { async fn register_meta_esdt( &mut self, issue_cost: RustBigUint, - token_display_name: &str, - token_ticker: &str, + token_display_name: &[u8], + token_ticker: &[u8], num_decimals: usize, ) { println!("Registering meta ESDT..."); @@ -443,8 +457,8 @@ impl SysFuncCallsInteract { .typed(ESDTSystemSCProxy) .register_meta_esdt( issue_cost.into(), - &token_display_name.into(), - &token_ticker.into(), + &token_display_name, + &token_ticker, MetaTokenProperties { num_decimals, can_freeze: true, @@ -464,7 +478,7 @@ impl SysFuncCallsInteract { println!("Meta-ESDT ID: {:?}", meta_esdt); } - async fn change_sft_meta_esdt(&mut self, token_id: &str, num_decimals: usize) { + async fn change_sft_meta_esdt(&mut self, token_id: &[u8], num_decimals: usize) { println!("Changing SFT to Meta-ESDT..."); self.interactor @@ -473,13 +487,13 @@ impl SysFuncCallsInteract { .to(ESDTSystemSCAddress) .gas(100_000_000u64) .typed(ESDTSystemSCProxy) - .change_sft_to_meta_esdt(&TokenIdentifier::from(token_id), num_decimals) + .change_sft_to_meta_esdt(&token_id, num_decimals) .prepare_async() .run() .await; } - async fn mint_token(&mut self, token_id: &str, nonce: u64, amount: RustBigUint) { + async fn mint_token(&mut self, token_id: &[u8], nonce: u64, amount: RustBigUint) { println!("Minting tokens..."); self.interactor @@ -488,17 +502,13 @@ impl SysFuncCallsInteract { .to(&self.wallet_address) .gas(100_000_000u64) .typed(UserBuiltinProxy) - .esdt_local_mint( - &TokenIdentifier::from(token_id), - nonce, - &BigUint::from(amount), - ) + .esdt_local_mint(&token_id, nonce, &amount) .prepare_async() .run() .await; } - async fn burn_token(&mut self, token_id: &str, nonce: u64, amount: RustBigUint) { + async fn burn_token(&mut self, token_id: &[u8], nonce: u64, amount: RustBigUint) { println!("Burning tokens..."); self.interactor @@ -507,17 +517,13 @@ impl SysFuncCallsInteract { .to(&self.wallet_address) .gas(100_000_000u64) .typed(UserBuiltinProxy) - .esdt_local_burn( - &TokenIdentifier::from(token_id), - nonce, - &BigUint::from(amount), - ) + .esdt_local_burn(&token_id, nonce, &amount) .prepare_async() .run() .await; } - async fn pause_token(&mut self, token_id: &str) { + async fn pause_token(&mut self, token_id: &[u8]) { println!("Pausing token..."); self.interactor @@ -526,13 +532,13 @@ impl SysFuncCallsInteract { .to(ESDTSystemSCAddress) .gas(100_000_000u64) .typed(ESDTSystemSCProxy) - .pause(&TokenIdentifier::from(token_id)) + .pause(&token_id) .prepare_async() .run() .await; } - async fn unpause_token(&mut self, token_id: &str) { + async fn unpause_token(&mut self, token_id: &[u8]) { println!("Unpausing token..."); self.interactor @@ -541,15 +547,13 @@ impl SysFuncCallsInteract { .to(ESDTSystemSCAddress) .gas(100_000_000u64) .typed(ESDTSystemSCProxy) - .unpause(&TokenIdentifier::from(token_id)) + .unpause(&token_id) .prepare_async() .run() .await; } - async fn freeze_token(&mut self, token_id: &str, address: &Bech32Address) { - let managed_address: ManagedAddress = - ManagedAddress::from_address(&address.to_address()); + async fn freeze_token(&mut self, token_id: &[u8], address: &Bech32Address) { println!("Freezing token..."); self.interactor @@ -558,15 +562,13 @@ impl SysFuncCallsInteract { .to(ESDTSystemSCAddress) .gas(100_000_000u64) .typed(ESDTSystemSCProxy) - .freeze(&TokenIdentifier::from(token_id), &managed_address) + .freeze(&token_id, &address) .prepare_async() .run() .await; } - async fn unfreeze_token(&mut self, token_id: &str, address: &Bech32Address) { - let managed_address: ManagedAddress = - ManagedAddress::from_address(&address.to_address()); + async fn unfreeze_token(&mut self, token_id: &[u8], address: &Bech32Address) { println!("Unfreezing token..."); self.interactor @@ -575,15 +577,13 @@ impl SysFuncCallsInteract { .to(ESDTSystemSCAddress) .gas(100_000_000u64) .typed(ESDTSystemSCProxy) - .unfreeze(&TokenIdentifier::from(token_id), &managed_address) + .unfreeze(&token_id, &address) .prepare_async() .run() .await; } - async fn freeze_nft(&mut self, token_id: &str, nonce: u64, address: &Bech32Address) { - let managed_address: ManagedAddress = - ManagedAddress::from_address(&address.to_address()); + async fn freeze_nft(&mut self, token_id: &[u8], nonce: u64, address: &Bech32Address) { println!("Freezing NFT/SFT/Meta-ESDT..."); self.interactor @@ -592,15 +592,13 @@ impl SysFuncCallsInteract { .to(ESDTSystemSCAddress) .gas(100_000_000u64) .typed(ESDTSystemSCProxy) - .freeze_nft(&TokenIdentifier::from(token_id), nonce, &managed_address) + .freeze_nft(&token_id, nonce, &address) .prepare_async() .run() .await; } - async fn unfreeze_nft(&mut self, token_id: &str, nonce: u64, address: &Bech32Address) { - let managed_address: ManagedAddress = - ManagedAddress::from_address(&address.to_address()); + async fn unfreeze_nft(&mut self, token_id: &[u8], nonce: u64, address: &Bech32Address) { println!("Unfreezing NFT/SFT/Meta-ESDT..."); self.interactor @@ -609,15 +607,13 @@ impl SysFuncCallsInteract { .to(ESDTSystemSCAddress) .gas(100_000_000u64) .typed(ESDTSystemSCProxy) - .unfreeze_nft(&TokenIdentifier::from(token_id), nonce, &managed_address) + .unfreeze_nft(&token_id, nonce, &address) .prepare_async() .run() .await; } - async fn wipe_token(&mut self, token_id: &str, address: &Bech32Address) { - let managed_address: ManagedAddress = - ManagedAddress::from_address(&address.to_address()); + async fn wipe_token(&mut self, token_id: &[u8], address: &Bech32Address) { println!("Wiping token..."); self.interactor @@ -626,15 +622,13 @@ impl SysFuncCallsInteract { .to(ESDTSystemSCAddress) .gas(100_000_000u64) .typed(ESDTSystemSCProxy) - .wipe(&TokenIdentifier::from(token_id), &managed_address) + .wipe(&token_id, &address) .prepare_async() .run() .await; } - async fn wipe_nft(&mut self, token_id: &str, nonce: u64, address: &Bech32Address) { - let managed_address: ManagedAddress = - ManagedAddress::from_address(&address.to_address()); + async fn wipe_nft(&mut self, token_id: &[u8], nonce: u64, address: &Bech32Address) { println!("Wiping NFT/SFT/Meta-ESDT..."); self.interactor @@ -643,7 +637,7 @@ impl SysFuncCallsInteract { .to(ESDTSystemSCAddress) .gas(100_000_000u64) .typed(ESDTSystemSCProxy) - .wipe_nft(&TokenIdentifier::from(token_id), nonce, &managed_address) + .wipe_nft(&token_id, nonce, &address) .prepare_async() .run() .await; @@ -651,11 +645,11 @@ impl SysFuncCallsInteract { async fn mint_nft( &mut self, - token_id: &str, + token_id: &[u8], amount: RustBigUint, - name: &str, + name: &[u8], royalties: u64, - hash: &str, + hash: &[u8], ) { println!("Minting NFT..."); @@ -666,11 +660,11 @@ impl SysFuncCallsInteract { .gas(100_000_000u64) .typed(UserBuiltinProxy) .esdt_nft_create( - &TokenIdentifier::from(token_id), - &BigUint::from(amount), - &ManagedBuffer::from(name), - &BigUint::from(royalties), - &ManagedBuffer::from(hash), + &token_id, + &amount, + &name, + &royalties, + &hash, &NftDummyAttributes { creation_epoch: 2104, cool_factor: 5, @@ -685,11 +679,9 @@ impl SysFuncCallsInteract { async fn unset_roles( &mut self, address: &Bech32Address, - token_id: &str, + token_id: &[u8], roles: Vec, ) { - let managed_address: ManagedAddress = - ManagedAddress::from_address(&address.to_address()); println!("Unsetting the following roles: {:?}", roles); self.interactor @@ -698,19 +690,13 @@ impl SysFuncCallsInteract { .to(ESDTSystemSCAddress) .gas(100_000_000u64) .typed(ESDTSystemSCProxy) - .unset_special_roles( - &managed_address, - &TokenIdentifier::from(token_id), - roles.into_iter(), - ) + .unset_special_roles(&address, &token_id, roles.into_iter()) .prepare_async() .run() .await; } - async fn transfer_ownership(&mut self, token_id: &str, new_owner: &Bech32Address) { - let managed_new_owner: ManagedAddress = - ManagedAddress::from_address(&new_owner.to_address()); + async fn transfer_ownership(&mut self, token_id: &[u8], new_owner: &Bech32Address) { println!("Transferring token ownership..."); self.interactor @@ -719,7 +705,7 @@ impl SysFuncCallsInteract { .to(ESDTSystemSCAddress) .gas(100_000_000u64) .typed(ESDTSystemSCProxy) - .transfer_ownership(&TokenIdentifier::from(token_id), &managed_new_owner) + .transfer_ownership(&token_id, &new_owner) .prepare_async() .run() .await; @@ -727,14 +713,10 @@ impl SysFuncCallsInteract { async fn transfer_nft_create_role( &mut self, - token_id: &str, + token_id: &[u8], old_owner: &Bech32Address, new_owner: &Bech32Address, ) { - let managed_old_owner: ManagedAddress = - ManagedAddress::from_address(&old_owner.to_address()); - let managed_new_owner: ManagedAddress = - ManagedAddress::from_address(&new_owner.to_address()); println!("Transferring NFT create role..."); self.interactor @@ -743,17 +725,13 @@ impl SysFuncCallsInteract { .to(ESDTSystemSCAddress) .gas(100_000_000u64) .typed(ESDTSystemSCProxy) - .transfer_nft_create_role( - &TokenIdentifier::from(token_id), - &managed_old_owner, - &managed_new_owner, - ) + .transfer_nft_create_role(&token_id, &old_owner, &new_owner) .prepare_async() .run() .await; } - async fn control_changes(&mut self, token_id: &str) { + async fn control_changes(&mut self, token_id: &[u8]) { println!("Control changes"); self.interactor @@ -763,7 +741,7 @@ impl SysFuncCallsInteract { .gas(100_000_000u64) .typed(ESDTSystemSCProxy) .control_changes( - &TokenIdentifier::from(token_id), + &token_id, &TokenPropertyArguments { can_freeze: Some(true), can_wipe: Some(true), From 55f1c40daf6b45cbe58837321e2987ad5ef074d7 Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Mon, 2 Sep 2024 15:47:41 +0200 Subject: [PATCH 80/92] process status fixes, returnsLogs result handler --- .../scenario/src/facade/result_handlers.rs | 2 + .../facade/result_handlers/returns_logs.rs | 24 ++++++++ sdk/core/src/data/transaction.rs | 14 +++++ sdk/core/src/gateway/gateway_tx.rs | 23 +++++++- sdk/core/src/gateway/gateway_tx_retrieve.rs | 58 +++++++++++-------- 5 files changed, 95 insertions(+), 26 deletions(-) create mode 100644 framework/scenario/src/facade/result_handlers/returns_logs.rs diff --git a/framework/scenario/src/facade/result_handlers.rs b/framework/scenario/src/facade/result_handlers.rs index 1893647b45..33b5b1a495 100644 --- a/framework/scenario/src/facade/result_handlers.rs +++ b/framework/scenario/src/facade/result_handlers.rs @@ -2,6 +2,7 @@ mod expect_error; mod expect_message; mod expect_status; mod expect_value; +mod returns_logs; mod returns_message; mod returns_new_bech32_address; mod returns_new_token_identifier; @@ -12,6 +13,7 @@ pub use expect_error::ExpectError; pub use expect_message::ExpectMessage; pub use expect_status::ExpectStatus; pub use expect_value::ExpectValue; +pub use returns_logs::ReturnsLogs; pub use returns_message::ReturnsMessage; pub use returns_new_bech32_address::ReturnsNewBech32Address; pub use returns_new_token_identifier::ReturnsNewTokenIdentifier; diff --git a/framework/scenario/src/facade/result_handlers/returns_logs.rs b/framework/scenario/src/facade/result_handlers/returns_logs.rs new file mode 100644 index 0000000000..7aa4292fa2 --- /dev/null +++ b/framework/scenario/src/facade/result_handlers/returns_logs.rs @@ -0,0 +1,24 @@ +use multiversx_sc::types::RHListItemExec; + +use crate::{ + multiversx_sc::types::{RHListItem, TxEnv}, + scenario_model::{Log, TxResponse}, +}; + +pub struct ReturnsLogs; + +impl RHListItem for ReturnsLogs +where + Env: TxEnv, +{ + type Returns = Vec; +} + +impl RHListItemExec for ReturnsLogs +where + Env: TxEnv, +{ + fn item_process_result(self, raw_result: &TxResponse) -> Self::Returns { + raw_result.logs.clone() + } +} diff --git a/sdk/core/src/data/transaction.rs b/sdk/core/src/data/transaction.rs index 3ee2f25684..561647776d 100644 --- a/sdk/core/src/data/transaction.rs +++ b/sdk/core/src/data/transaction.rs @@ -152,6 +152,20 @@ pub struct TransactionStatus { pub data: Option, } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct TransactionProcessStatusData { + pub reason: String, + pub status: String, +} + +// TransactionProcessStatus holds a transaction's status response from the network obtained through the process-status API +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct TransactionProcessStatus { + pub error: String, + pub code: String, + pub data: Option, +} + // ArgCreateTransaction will hold the transaction fields #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ArgCreateTransaction { diff --git a/sdk/core/src/gateway/gateway_tx.rs b/sdk/core/src/gateway/gateway_tx.rs index 47aa8b5a83..eaf9fed9d5 100644 --- a/sdk/core/src/gateway/gateway_tx.rs +++ b/sdk/core/src/gateway/gateway_tx.rs @@ -3,7 +3,8 @@ use crate::data::{ network_config::NetworkConfig, transaction::{ ArgCreateTransaction, ResponseTxCost, SendTransactionResponse, SendTransactionsResponse, - Transaction, TransactionInfo, TransactionOnNetwork, TransactionStatus, TxCostResponseData, + Transaction, TransactionInfo, TransactionOnNetwork, TransactionProcessStatus, + TransactionStatus, TxCostResponseData, }, vm::{ResponseVmValue, VmValueRequest, VmValuesResponseData}, }; @@ -96,6 +97,26 @@ impl GatewayProxy { } } + // get_transaction_process_status retrieves a transaction's status from the network using process-status API + pub async fn get_transaction_process_status(&self, hash: &str) -> Result<(String, String)> { + println!("transaction process status"); + let endpoint = format!("transaction/{hash}/process-status"); + let endpoint = self.get_endpoint(endpoint.as_str()); + + let resp = self + .client + .get(endpoint) + .send() + .await? + .json::() + .await?; + + match resp.data { + None => Err(anyhow!("{}", resp.error)), + Some(b) => Ok((b.status, b.reason)), + } + } + // get_default_transaction_arguments will prepare the transaction creation argument by querying the account's info pub async fn get_default_transaction_arguments( &self, diff --git a/sdk/core/src/gateway/gateway_tx_retrieve.rs b/sdk/core/src/gateway/gateway_tx_retrieve.rs index 452d37b3e0..18bc9c7136 100644 --- a/sdk/core/src/gateway/gateway_tx_retrieve.rs +++ b/sdk/core/src/gateway/gateway_tx_retrieve.rs @@ -14,41 +14,37 @@ impl GatewayProxy { let mut retries = 0; let mut backoff_delay = Duration::from_secs_f32(INITIAL_BACKOFF_DELAY); let start_time = Instant::now(); - let mut issue_found = false; loop { - match self.get_transaction_status(&tx_hash).await { - Ok(status) => { + match self.get_transaction_process_status(&tx_hash).await { + Ok((status, reason)) => { // checks if transaction status is final match status.as_str() { - "success" | "fail" => { + "success" => { // retrieve transaction info with results let transaction_info_with_results = self .get_transaction_info_with_results(&tx_hash) .await .unwrap(); - if !transaction_info_with_results - .smart_contract_results - .is_empty() - && !issue_found - { - let first_scr = - &transaction_info_with_results.smart_contract_results[0]; - - if GatewayProxy::is_issue_tx(&first_scr.data) { - issue_found = true; - tokio::time::sleep(Duration::from_secs(30)).await; - continue; - } - } - info!( "Transaction retrieved successfully, with status {}: {:#?}", status, transaction_info_with_results ); return transaction_info_with_results; }, + "fail" => { + let result = parse_reason(&reason); + + match result { + Ok((code, err)) => { + panic!("Transaction failed. Code: {code}, message: {err}") + }, + Err(err) => { + panic!("Reason parsing error for failed transaction: {err}") + }, + } + }, _ => { continue; }, @@ -77,12 +73,24 @@ impl GatewayProxy { ); TransactionOnNetwork::default() } +} + +pub fn parse_reason(reason: &str) -> Result<(u64, String), String> { + let parts: Vec<&str> = reason.split('@').collect(); - fn is_issue_tx(data: &str) -> bool { - data.starts_with("issue@") - || data.starts_with("issueSemiFungible@") - || data.starts_with("issueNonFungible@") - || data.starts_with("registerMetaESDT@") - || data.starts_with("registerAndSetAllRoles@") + if parts.len() < 2 { + return Err("Invalid reason format".to_string()); } + + let error_code_hex = parts[1]; + let error_message_hex = parts[2]; + + let error_code = + u64::from_str_radix(error_code_hex, 16).expect("Failed to decode error code as u64"); + + let error_message = + String::from_utf8(hex::decode(error_message_hex).expect("Failed to decode error message")) + .expect("Failed to decode error message as UTF-8"); + + Ok((error_code, error_message)) } From 1866c74b9cc16ba5cbb0e6277887ab68fa6051c7 Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Mon, 2 Sep 2024 16:28:57 +0200 Subject: [PATCH 81/92] removed debug comment --- sdk/core/src/gateway/gateway_tx.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/sdk/core/src/gateway/gateway_tx.rs b/sdk/core/src/gateway/gateway_tx.rs index eaf9fed9d5..88d9cd4ece 100644 --- a/sdk/core/src/gateway/gateway_tx.rs +++ b/sdk/core/src/gateway/gateway_tx.rs @@ -99,7 +99,6 @@ impl GatewayProxy { // get_transaction_process_status retrieves a transaction's status from the network using process-status API pub async fn get_transaction_process_status(&self, hash: &str) -> Result<(String, String)> { - println!("transaction process status"); let endpoint = format!("transaction/{hash}/process-status"); let endpoint = self.get_endpoint(endpoint.as_str()); From f34c9d0ea2036e985e36de5e2c71fcd7636ef711 Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Mon, 2 Sep 2024 17:41:47 +0200 Subject: [PATCH 82/92] invalid transaction case --- sdk/core/src/gateway/gateway_tx_retrieve.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sdk/core/src/gateway/gateway_tx_retrieve.rs b/sdk/core/src/gateway/gateway_tx_retrieve.rs index 18bc9c7136..61ba080430 100644 --- a/sdk/core/src/gateway/gateway_tx_retrieve.rs +++ b/sdk/core/src/gateway/gateway_tx_retrieve.rs @@ -34,13 +34,21 @@ impl GatewayProxy { return transaction_info_with_results; }, "fail" => { + // status failed and no reason means invalid transaction + if reason.is_empty() { + info!("Transaction failed. Invalid transaction: {tx_hash}"); + panic!("Transaction failed. Invalid transaction: {tx_hash}"); + } + let result = parse_reason(&reason); match result { Ok((code, err)) => { + info!("Transaction failed. Code: {code}, message: {err}"); panic!("Transaction failed. Code: {code}, message: {err}") }, Err(err) => { + info!("Reason parsing error for failed transaction: {err}"); panic!("Reason parsing error for failed transaction: {err}") }, } From c4098643397a08db22e3b2ea31e0ecbbd8e1ecf2 Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Tue, 3 Sep 2024 10:54:58 +0200 Subject: [PATCH 83/92] moved returnsLogs to a different PR --- .../scenario/src/facade/result_handlers.rs | 2 -- .../facade/result_handlers/returns_logs.rs | 24 ------------------- 2 files changed, 26 deletions(-) delete mode 100644 framework/scenario/src/facade/result_handlers/returns_logs.rs diff --git a/framework/scenario/src/facade/result_handlers.rs b/framework/scenario/src/facade/result_handlers.rs index 33b5b1a495..1893647b45 100644 --- a/framework/scenario/src/facade/result_handlers.rs +++ b/framework/scenario/src/facade/result_handlers.rs @@ -2,7 +2,6 @@ mod expect_error; mod expect_message; mod expect_status; mod expect_value; -mod returns_logs; mod returns_message; mod returns_new_bech32_address; mod returns_new_token_identifier; @@ -13,7 +12,6 @@ pub use expect_error::ExpectError; pub use expect_message::ExpectMessage; pub use expect_status::ExpectStatus; pub use expect_value::ExpectValue; -pub use returns_logs::ReturnsLogs; pub use returns_message::ReturnsMessage; pub use returns_new_bech32_address::ReturnsNewBech32Address; pub use returns_new_token_identifier::ReturnsNewTokenIdentifier; diff --git a/framework/scenario/src/facade/result_handlers/returns_logs.rs b/framework/scenario/src/facade/result_handlers/returns_logs.rs deleted file mode 100644 index 7aa4292fa2..0000000000 --- a/framework/scenario/src/facade/result_handlers/returns_logs.rs +++ /dev/null @@ -1,24 +0,0 @@ -use multiversx_sc::types::RHListItemExec; - -use crate::{ - multiversx_sc::types::{RHListItem, TxEnv}, - scenario_model::{Log, TxResponse}, -}; - -pub struct ReturnsLogs; - -impl RHListItem for ReturnsLogs -where - Env: TxEnv, -{ - type Returns = Vec; -} - -impl RHListItemExec for ReturnsLogs -where - Env: TxEnv, -{ - fn item_process_result(self, raw_result: &TxResponse) -> Self::Returns { - raw_result.logs.clone() - } -} From 5c5f1592affcf7bb5172ffac24dc171c016dc9d9 Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Tue, 3 Sep 2024 10:59:40 +0200 Subject: [PATCH 84/92] result handler impl --- .../scenario/src/facade/result_handlers.rs | 2 ++ .../facade/result_handlers/returns_logs.rs | 24 +++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 framework/scenario/src/facade/result_handlers/returns_logs.rs diff --git a/framework/scenario/src/facade/result_handlers.rs b/framework/scenario/src/facade/result_handlers.rs index 1893647b45..33b5b1a495 100644 --- a/framework/scenario/src/facade/result_handlers.rs +++ b/framework/scenario/src/facade/result_handlers.rs @@ -2,6 +2,7 @@ mod expect_error; mod expect_message; mod expect_status; mod expect_value; +mod returns_logs; mod returns_message; mod returns_new_bech32_address; mod returns_new_token_identifier; @@ -12,6 +13,7 @@ pub use expect_error::ExpectError; pub use expect_message::ExpectMessage; pub use expect_status::ExpectStatus; pub use expect_value::ExpectValue; +pub use returns_logs::ReturnsLogs; pub use returns_message::ReturnsMessage; pub use returns_new_bech32_address::ReturnsNewBech32Address; pub use returns_new_token_identifier::ReturnsNewTokenIdentifier; diff --git a/framework/scenario/src/facade/result_handlers/returns_logs.rs b/framework/scenario/src/facade/result_handlers/returns_logs.rs new file mode 100644 index 0000000000..7aa4292fa2 --- /dev/null +++ b/framework/scenario/src/facade/result_handlers/returns_logs.rs @@ -0,0 +1,24 @@ +use multiversx_sc::types::RHListItemExec; + +use crate::{ + multiversx_sc::types::{RHListItem, TxEnv}, + scenario_model::{Log, TxResponse}, +}; + +pub struct ReturnsLogs; + +impl RHListItem for ReturnsLogs +where + Env: TxEnv, +{ + type Returns = Vec; +} + +impl RHListItemExec for ReturnsLogs +where + Env: TxEnv, +{ + fn item_process_result(self, raw_result: &TxResponse) -> Self::Returns { + raw_result.logs.clone() + } +} From f634c4c8cafa81ccf6bbae7df3acbc2f422c124b Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Tue, 3 Sep 2024 14:14:02 +0200 Subject: [PATCH 85/92] populate txResult logs with transactionFromNetwork --- .../src/scenario/model/transaction/log.rs | 10 ++++------ framework/snippets/src/network_response.rs | 20 ++++++++++++++++++- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/framework/scenario/src/scenario/model/transaction/log.rs b/framework/scenario/src/scenario/model/transaction/log.rs index 27ebccfd08..4cb0f98be0 100644 --- a/framework/scenario/src/scenario/model/transaction/log.rs +++ b/framework/scenario/src/scenario/model/transaction/log.rs @@ -1,9 +1,7 @@ -use crate::scenario_model::BytesValue; - #[derive(Debug, Clone)] pub struct Log { - pub address: BytesValue, - pub endpoint: BytesValue, - pub topics: Vec, - pub data: BytesValue, + pub address: String, + pub endpoint: String, + pub topics: Vec, + pub data: String, } diff --git a/framework/snippets/src/network_response.rs b/framework/snippets/src/network_response.rs index 4d828e12c7..ed4d5dd8ce 100644 --- a/framework/snippets/src/network_response.rs +++ b/framework/snippets/src/network_response.rs @@ -1,7 +1,7 @@ use multiversx_sc_scenario::{ imports::{Address, ESDTSystemSCAddress}, multiversx_chain_vm::crypto_functions::keccak256, - scenario_model::{TxResponse, TxResponseStatus}, + scenario_model::{Log, TxResponse, TxResponseStatus}, }; use multiversx_sdk::{ data::transaction::{ApiSmartContractResult, Events, TransactionOnNetwork}, @@ -44,6 +44,7 @@ fn process_success(tx: &TransactionOnNetwork) -> TxResponse { out: process_out(tx), new_deployed_address: process_new_deployed_address(tx), new_issued_token_identifier: process_new_issued_token_identifier(tx), + logs: process_logs(tx), ..Default::default() } } @@ -58,6 +59,23 @@ fn process_out(tx: &TransactionOnNetwork) -> Vec> { } } +fn process_logs(tx: &TransactionOnNetwork) -> Vec { + if let Some(api_logs) = &tx.logs { + return api_logs + .events + .iter() + .map(|event| Log { + address: event.address.to_string(), + endpoint: event.identifier.clone(), + topics: event.topics.clone().unwrap_or_default(), + data: event.data.clone().unwrap_or_default(), + }) + .collect::>(); + } + + Vec::new() +} + fn process_out_from_log(tx: &TransactionOnNetwork) -> Option>> { if let Some(logs) = &tx.logs { logs.events.iter().rev().find_map(|event| { From 2659d239976b42ec540d261665bec4fb56f89d09 Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Tue, 3 Sep 2024 16:47:56 +0200 Subject: [PATCH 86/92] added more tests for managed decimal var --- .../scenarios/managed_decimal.scen.json | 88 ++++++++++++++++- .../managed_decimal_logarithm.scen.json | 94 ++++++++++++++++++- .../src/managed_decimal_features.rs | 43 +++++++++ .../basic_features_managed_decimal_test.rs | 5 + .../basic-features/wasm/src/lib.rs | 9 +- framework/snippets/src/imports.rs | 5 +- 6 files changed, 236 insertions(+), 8 deletions(-) diff --git a/contracts/feature-tests/basic-features/scenarios/managed_decimal.scen.json b/contracts/feature-tests/basic-features/scenarios/managed_decimal.scen.json index b723c07b6d..e23747e4fb 100644 --- a/contracts/feature-tests/basic-features/scenarios/managed_decimal.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/managed_decimal.scen.json @@ -141,6 +141,92 @@ "gas": "*", "refund": "*" } + }, + { + "step": "scCall", + "id": "6", + "tx": { + "from": "address:an_account", + "to": "sc:basic-features", + "function": "managed_decimal_addition_var", + "arguments": [ + "0x000000010400000002", + "0x000000010500000002" + ], + "gasLimit": "1,000,000,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [ + "0x000000010900000002" + ] + } + }, + { + "step": "scCall", + "id": "7", + "tx": { + "from": "address:an_account", + "to": "sc:basic-features", + "function": "managed_decimal_subtraction_var", + "arguments": [ + "0x000000010900000002", + "0x000000010400000002" + ], + "gasLimit": "1,000,000,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [ + "0x000000010500000002" + ] + } + }, + { + "step": "scCall", + "id": "8", + "tx": { + "from": "address:an_account", + "to": "sc:basic-features", + "function": "managed_decimal_subtraction_var", + "arguments": [ + "0x000000010200000002", + "0x000000010800000002" + ], + "gasLimit": "1,000,000,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [], + "status": "4", + "message": "str:cannot subtract because result would be negative", + "gas": "*", + "refund": "*" + } + }, + { + "step": "scCall", + "id": "9", + "tx": { + "from": "address:an_account", + "to": "sc:basic-features", + "function": "managed_decimal_eq_var", + "arguments": [ + "0x000000010d00000002", + "0x000000010d00000002" + ], + "gasLimit": "1,000,000,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [ + "0x01" + ], + "status": "", + "message": "*", + "gas": "*", + "refund": "*" + } } ] -} +} \ No newline at end of file diff --git a/contracts/feature-tests/basic-features/scenarios/managed_decimal_logarithm.scen.json b/contracts/feature-tests/basic-features/scenarios/managed_decimal_logarithm.scen.json index 193517275c..6ee41eaa4d 100644 --- a/contracts/feature-tests/basic-features/scenarios/managed_decimal_logarithm.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/managed_decimal_logarithm.scen.json @@ -105,6 +105,98 @@ "gas": "*", "refund": "*" } + }, + { + "step": "scCall", + "id": "managed_decimal_log2_var(23)", + "tx": { + "from": "address:an_account", + "to": "sc:basic-features", + "function": "managed_decimal_log2_var", + "arguments": [ + "0x00000005055ae8260000000009" + ], + "gasLimit": "1,000,000,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [ + "4,523648008" + ], + "status": "", + "message": "*", + "gas": "*", + "refund": "*" + } + }, + { + "step": "scCall", + "id": "managed_decimal_ln_var(23)", + "tx": { + "from": "address:an_account", + "to": "sc:basic-features", + "function": "managed_decimal_ln_var", + "arguments": [ + "0x00000005055ae8260000000009" + ], + "gasLimit": "25,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [ + "+3,135553845" + ], + "status": "", + "message": "*", + "gas": "*", + "refund": "*" + } + }, + { + "step": "scCall", + "id": "managed_decimal_ln_var(378,298)", + "tx": { + "from": "address:an_account", + "to": "sc:basic-features", + "function": "managed_decimal_ln_var", + "arguments": [ + "0x00000005581451628000000009" + ], + "gasLimit": "1,000,000,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [ + "0x0161cc16aa" + ], + "status": "", + "message": "*", + "gas": "*", + "refund": "*" + } + }, + { + "step": "scCall", + "id": "managed_decimal_log2_var(218,345)", + "tx": { + "from": "address:an_account", + "to": "sc:basic-features", + "function": "managed_decimal_log2_var", + "arguments": [ + "0x0000000532d6604c4000000009" + ], + "gasLimit": "1,000,000,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [ + "7,770385327" + ], + "status": "", + "message": "*", + "gas": "*", + "refund": "*" + } } ] -} +} \ No newline at end of file diff --git a/contracts/feature-tests/basic-features/src/managed_decimal_features.rs b/contracts/feature-tests/basic-features/src/managed_decimal_features.rs index 556641cdc9..4bb3233c70 100644 --- a/contracts/feature-tests/basic-features/src/managed_decimal_features.rs +++ b/contracts/feature-tests/basic-features/src/managed_decimal_features.rs @@ -56,4 +56,47 @@ pub trait ManagedDecimalFeatures { ) -> ManagedDecimalSigned> { x.log2().unwrap_or_else(|| sc_panic!("cannot be zero")) } + + #[endpoint] + fn managed_decimal_addition_var( + &self, + first: ManagedDecimal, + second: ManagedDecimal, + ) -> ManagedDecimal { + first + second + } + + #[endpoint] + fn managed_decimal_subtraction_var( + &self, + first: ManagedDecimal, + second: ManagedDecimal, + ) -> ManagedDecimal { + first - second + } + + #[endpoint] + fn managed_decimal_eq_var( + &self, + first: ManagedDecimal, + second: ManagedDecimal, + ) -> bool { + first.eq(&second) + } + + #[endpoint] + fn managed_decimal_ln_var( + &self, + x: ManagedDecimal, + ) -> ManagedDecimalSigned> { + x.ln().unwrap_or_else(|| sc_panic!("cannot be zero")) + } + + #[endpoint] + fn managed_decimal_log2_var( + &self, + x: ManagedDecimal, + ) -> ManagedDecimalSigned> { + x.log2().unwrap_or_else(|| sc_panic!("cannot be zero")) + } } diff --git a/contracts/feature-tests/basic-features/tests/basic_features_managed_decimal_test.rs b/contracts/feature-tests/basic-features/tests/basic_features_managed_decimal_test.rs index d4257fe078..238e4f0f4e 100644 --- a/contracts/feature-tests/basic-features/tests/basic_features_managed_decimal_test.rs +++ b/contracts/feature-tests/basic-features/tests/basic_features_managed_decimal_test.rs @@ -13,3 +13,8 @@ fn world() -> ScenarioWorld { fn managed_decimal_test() { world().run("scenarios/managed_decimal.scen.json"); } + +#[test] +fn managed_decimal_logarithm_test() { + world().run("scenarios/managed_decimal_logarithm.scen.json"); +} diff --git a/contracts/feature-tests/basic-features/wasm/src/lib.rs b/contracts/feature-tests/basic-features/wasm/src/lib.rs index 887b75bcd5..7b988da222 100644 --- a/contracts/feature-tests/basic-features/wasm/src/lib.rs +++ b/contracts/feature-tests/basic-features/wasm/src/lib.rs @@ -5,9 +5,9 @@ //////////////////////////////////////////////////// // Init: 1 -// Endpoints: 403 +// Endpoints: 408 // Async Callback: 1 -// Total number of exported functions: 405 +// Total number of exported functions: 410 #![no_std] @@ -421,6 +421,11 @@ multiversx_sc_wasm_adapter::endpoints! { managed_decimal_into_raw_units => managed_decimal_into_raw_units managed_decimal_ln => managed_decimal_ln managed_decimal_log2 => managed_decimal_log2 + managed_decimal_addition_var => managed_decimal_addition_var + managed_decimal_subtraction_var => managed_decimal_subtraction_var + managed_decimal_eq_var => managed_decimal_eq_var + managed_decimal_ln_var => managed_decimal_ln_var + managed_decimal_log2_var => managed_decimal_log2_var ) } diff --git a/framework/snippets/src/imports.rs b/framework/snippets/src/imports.rs index a35e880c78..a22c969887 100644 --- a/framework/snippets/src/imports.rs +++ b/framework/snippets/src/imports.rs @@ -4,10 +4,7 @@ pub use crate::{ dns_address_for_name, test_wallets, Interactor, InteractorPrepareAsync, StepBuffer, }; -pub use multiversx_sdk::{ - wallet::Wallet, - data::keystore::InsertPassword, -}; +pub use multiversx_sdk::{data::keystore::InsertPassword, wallet::Wallet}; pub use env_logger; pub use tokio; From 6b1f314829d41b56011754e4bb1c636d96f0f7ff Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Tue, 3 Sep 2024 19:08:45 +0200 Subject: [PATCH 87/92] fix after review and tests --- .../tests/promises_feature_blackbox_test.rs | 41 +++++++++++++++++++ .../src/scenario/model/transaction/log.rs | 8 ++-- .../scenario/model/transaction/tx_response.rs | 10 +++++ framework/snippets/src/network_response.rs | 32 +++++++++++---- sdk/core/src/data/transaction.rs | 2 +- 5 files changed, 81 insertions(+), 12 deletions(-) diff --git a/contracts/feature-tests/composability/tests/promises_feature_blackbox_test.rs b/contracts/feature-tests/composability/tests/promises_feature_blackbox_test.rs index 4fd4f4d1cc..2eb20508f8 100644 --- a/contracts/feature-tests/composability/tests/promises_feature_blackbox_test.rs +++ b/contracts/feature-tests/composability/tests/promises_feature_blackbox_test.rs @@ -85,3 +85,44 @@ fn test_multi_call_back_transfers() { .check_account(PROMISES_FEATURE_ADDRESS) .esdt_balance(TOKEN_ID_EXPR, token_amount); } + +#[test] +fn test_back_transfers_logs() { + let mut state = PromisesFeaturesTestState::new(); + let token_amount = BigUint::from(1000u64); + + let logs = state + .world + .tx() + .from(USER_ADDRESS) + .to(PROMISES_FEATURE_ADDRESS) + .typed(promises_feature_proxy::PromisesFeaturesProxy) + .forward_sync_retrieve_funds_bt(VAULT_ADDRESS, TOKEN_ID, 0u64, &token_amount) + .returns(ReturnsLogs) + .run(); + + assert!(!logs.is_empty() && !logs[0].topics.is_empty()); + assert_eq!(logs[0].address, PROMISES_FEATURE_ADDRESS); + assert_eq!(logs[0].endpoint, "transferValueOnly"); +} + +#[test] +fn test_multi_call_back_transfers_logs() { + let mut state = PromisesFeaturesTestState::new(); + let token_amount = BigUint::from(1000u64); + let half_token_amount = token_amount.clone() / 2u64; + + let logs = state + .world + .tx() + .from(USER_ADDRESS) + .to(PROMISES_FEATURE_ADDRESS) + .typed(promises_feature_proxy::PromisesFeaturesProxy) + .forward_sync_retrieve_funds_bt_twice(VAULT_ADDRESS, TOKEN_ID, 0u64, &half_token_amount) + .returns(ReturnsLogs) + .run(); + + assert!(!logs.is_empty() && !logs[0].topics.is_empty()); + assert_eq!(logs[0].address, PROMISES_FEATURE_ADDRESS); + assert_eq!(logs[0].endpoint, "transferValueOnly"); +} diff --git a/framework/scenario/src/scenario/model/transaction/log.rs b/framework/scenario/src/scenario/model/transaction/log.rs index 4cb0f98be0..803c521bbf 100644 --- a/framework/scenario/src/scenario/model/transaction/log.rs +++ b/framework/scenario/src/scenario/model/transaction/log.rs @@ -1,7 +1,9 @@ +use multiversx_sc::types::Address; + #[derive(Debug, Clone)] pub struct Log { - pub address: String, + pub address: Address, pub endpoint: String, - pub topics: Vec, - pub data: String, + pub topics: Vec>, + pub data: Vec>, } diff --git a/framework/scenario/src/scenario/model/transaction/tx_response.rs b/framework/scenario/src/scenario/model/transaction/tx_response.rs index fd9721721f..8a7a5c4bf9 100644 --- a/framework/scenario/src/scenario/model/transaction/tx_response.rs +++ b/framework/scenario/src/scenario/model/transaction/tx_response.rs @@ -31,6 +31,16 @@ impl TxResponse { status: tx_result.result_status, message: tx_result.result_message, }, + logs: tx_result + .result_logs + .iter() + .map(|tx_log| Log { + address: Address::from_slice(tx_log.address.as_bytes()), + endpoint: tx_log.endpoint.to_string(), + topics: tx_log.topics.clone(), + data: tx_log.data.clone(), + }) + .collect(), ..Default::default() } } diff --git a/framework/snippets/src/network_response.rs b/framework/snippets/src/network_response.rs index ed4d5dd8ce..7d4e398396 100644 --- a/framework/snippets/src/network_response.rs +++ b/framework/snippets/src/network_response.rs @@ -65,10 +65,22 @@ fn process_logs(tx: &TransactionOnNetwork) -> Vec { .events .iter() .map(|event| Log { - address: event.address.to_string(), + address: Address::from_slice(&event.address.to_bytes()), endpoint: event.identifier.clone(), - topics: event.topics.clone().unwrap_or_default(), - data: event.data.clone().unwrap_or_default(), + topics: event + .topics + .clone() + .unwrap_or_default() + .into_iter() + .map(|s| s.into_bytes()) + .collect(), + data: event + .data + .clone() + .unwrap_or_default() + .into_iter() + .map(|s| s.into_bytes()) + .collect(), }) .collect::>(); } @@ -81,12 +93,16 @@ fn process_out_from_log(tx: &TransactionOnNetwork) -> Option>> { logs.events.iter().rev().find_map(|event| { if event.identifier == "writeLog" { if let Some(data) = &event.data { - let decoded_data = String::from_utf8(base64_decode(data)).unwrap(); - - if decoded_data.starts_with('@') { - let out = decode_scr_data_or_panic(decoded_data.as_str()); - return Some(out); + let mut out = Vec::new(); + for data_member in data.iter() { + let decoded_data = String::from_utf8(base64_decode(data_member)).unwrap(); + + if decoded_data.starts_with('@') { + let out_content = decode_scr_data_or_panic(decoded_data.as_str()); + out.extend(out_content); + } } + return Some(out); } } diff --git a/sdk/core/src/data/transaction.rs b/sdk/core/src/data/transaction.rs index 561647776d..bd93ff0fd7 100644 --- a/sdk/core/src/data/transaction.rs +++ b/sdk/core/src/data/transaction.rs @@ -92,7 +92,7 @@ pub struct Events { pub address: Address, pub identifier: String, pub topics: Option>, - pub data: Option, + pub data: Option>, } // ApiLogs represents logs with changed fields' types in order to make it friendly for API's json From ca3489a489427125716df3003ca3375e22038aa2 Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Tue, 3 Sep 2024 20:09:33 +0200 Subject: [PATCH 88/92] added support for object or vec as event data --- framework/snippets/src/network_response.rs | 71 ++++++++++++++-------- sdk/core/src/data/transaction.rs | 9 ++- 2 files changed, 55 insertions(+), 25 deletions(-) diff --git a/framework/snippets/src/network_response.rs b/framework/snippets/src/network_response.rs index 7d4e398396..1210a97bdd 100644 --- a/framework/snippets/src/network_response.rs +++ b/framework/snippets/src/network_response.rs @@ -4,7 +4,7 @@ use multiversx_sc_scenario::{ scenario_model::{Log, TxResponse, TxResponseStatus}, }; use multiversx_sdk::{ - data::transaction::{ApiSmartContractResult, Events, TransactionOnNetwork}, + data::transaction::{ApiSmartContractResult, Data, Events, TransactionOnNetwork}, utils::base64_decode, }; @@ -67,20 +67,8 @@ fn process_logs(tx: &TransactionOnNetwork) -> Vec { .map(|event| Log { address: Address::from_slice(&event.address.to_bytes()), endpoint: event.identifier.clone(), - topics: event - .topics - .clone() - .unwrap_or_default() - .into_iter() - .map(|s| s.into_bytes()) - .collect(), - data: event - .data - .clone() - .unwrap_or_default() - .into_iter() - .map(|s| s.into_bytes()) - .collect(), + topics: extract_topics(event), + data: extract_data(event), }) .collect::>(); } @@ -88,21 +76,56 @@ fn process_logs(tx: &TransactionOnNetwork) -> Vec { Vec::new() } +fn extract_data(event: &Events) -> Vec> { + let mut out: Vec> = Vec::new(); + if let Some(data) = event.data.clone() { + match data { + Data::String(string) => out.push(string.into_bytes()), + Data::Vec(vec) => return vec.into_iter().map(|s| s.into_bytes()).collect(), + } + } + + out +} + +fn extract_topics(event: &Events) -> Vec> { + event + .topics + .clone() + .unwrap_or_default() + .into_iter() + .map(|s| s.into_bytes()) + .collect() +} + fn process_out_from_log(tx: &TransactionOnNetwork) -> Option>> { if let Some(logs) = &tx.logs { logs.events.iter().rev().find_map(|event| { if event.identifier == "writeLog" { if let Some(data) = &event.data { - let mut out = Vec::new(); - for data_member in data.iter() { - let decoded_data = String::from_utf8(base64_decode(data_member)).unwrap(); - - if decoded_data.starts_with('@') { - let out_content = decode_scr_data_or_panic(decoded_data.as_str()); - out.extend(out_content); - } + match data { + Data::String(string) => { + let decoded_data = String::from_utf8(base64_decode(string)).unwrap(); + if decoded_data.starts_with('@') { + let out = decode_scr_data_or_panic(&decoded_data); + return Some(out); + } + }, + Data::Vec(vec) => { + let mut out = Vec::new(); + for data_member in vec.iter() { + let decoded_data = + String::from_utf8(base64_decode(data_member)).unwrap(); + + if decoded_data.starts_with('@') { + let out_content = + decode_scr_data_or_panic(decoded_data.as_str()); + out.extend(out_content); + } + } + return Some(out); + }, } - return Some(out); } } diff --git a/sdk/core/src/data/transaction.rs b/sdk/core/src/data/transaction.rs index bd93ff0fd7..5f98eb0438 100644 --- a/sdk/core/src/data/transaction.rs +++ b/sdk/core/src/data/transaction.rs @@ -92,7 +92,14 @@ pub struct Events { pub address: Address, pub identifier: String, pub topics: Option>, - pub data: Option>, + pub data: Option, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +#[serde(untagged)] +pub enum Data { + String(String), + Vec(Vec), } // ApiLogs represents logs with changed fields' types in order to make it friendly for API's json From b9cdef7c2d736d7b876e210cf472bba1f276a3e1 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Wed, 4 Sep 2024 08:22:38 +0300 Subject: [PATCH 89/92] log data refactor --- framework/snippets/src/network_response.rs | 43 +++++++--------------- sdk/core/src/data/transaction.rs | 13 ++++++- 2 files changed, 24 insertions(+), 32 deletions(-) diff --git a/framework/snippets/src/network_response.rs b/framework/snippets/src/network_response.rs index 1210a97bdd..ea10ade8f3 100644 --- a/framework/snippets/src/network_response.rs +++ b/framework/snippets/src/network_response.rs @@ -4,7 +4,7 @@ use multiversx_sc_scenario::{ scenario_model::{Log, TxResponse, TxResponseStatus}, }; use multiversx_sdk::{ - data::transaction::{ApiSmartContractResult, Data, Events, TransactionOnNetwork}, + data::transaction::{ApiSmartContractResult, Events, TransactionOnNetwork}, utils::base64_decode, }; @@ -78,13 +78,9 @@ fn process_logs(tx: &TransactionOnNetwork) -> Vec { fn extract_data(event: &Events) -> Vec> { let mut out: Vec> = Vec::new(); - if let Some(data) = event.data.clone() { - match data { - Data::String(string) => out.push(string.into_bytes()), - Data::Vec(vec) => return vec.into_iter().map(|s| s.into_bytes()).collect(), - } + if let Some(data) = &event.data { + data.for_each(|data_field| out.push(data_field.clone().into_bytes())); } - out } @@ -103,29 +99,16 @@ fn process_out_from_log(tx: &TransactionOnNetwork) -> Option>> { logs.events.iter().rev().find_map(|event| { if event.identifier == "writeLog" { if let Some(data) = &event.data { - match data { - Data::String(string) => { - let decoded_data = String::from_utf8(base64_decode(string)).unwrap(); - if decoded_data.starts_with('@') { - let out = decode_scr_data_or_panic(&decoded_data); - return Some(out); - } - }, - Data::Vec(vec) => { - let mut out = Vec::new(); - for data_member in vec.iter() { - let decoded_data = - String::from_utf8(base64_decode(data_member)).unwrap(); - - if decoded_data.starts_with('@') { - let out_content = - decode_scr_data_or_panic(decoded_data.as_str()); - out.extend(out_content); - } - } - return Some(out); - }, - } + let mut out = Vec::new(); + data.for_each(|data_member| { + let decoded_data = String::from_utf8(base64_decode(data_member)).unwrap(); + + if decoded_data.starts_with('@') { + let out_content = decode_scr_data_or_panic(decoded_data.as_str()); + out.extend(out_content); + } + }); + return Some(out); } } diff --git a/sdk/core/src/data/transaction.rs b/sdk/core/src/data/transaction.rs index 5f98eb0438..774c366dfa 100644 --- a/sdk/core/src/data/transaction.rs +++ b/sdk/core/src/data/transaction.rs @@ -92,16 +92,25 @@ pub struct Events { pub address: Address, pub identifier: String, pub topics: Option>, - pub data: Option, + pub data: Option, } #[derive(Serialize, Deserialize, Debug, Clone)] #[serde(untagged)] -pub enum Data { +pub enum LogData { String(String), Vec(Vec), } +impl LogData { + pub fn for_each(&self, mut f: F) { + match self { + LogData::String(s) => f(s), + LogData::Vec(v) => v.iter().for_each(f), + } + } +} + // ApiLogs represents logs with changed fields' types in order to make it friendly for API's json #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] From 6ce2d1e4b1b64479abdad7fa0a11cc755f9d9dfa Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Wed, 4 Sep 2024 08:36:17 +0300 Subject: [PATCH 90/92] log data refactor --- framework/snippets/src/network_response.rs | 28 +++++---- sdk/core/src/data/transaction.rs | 67 +++++++++++++++++++++- 2 files changed, 78 insertions(+), 17 deletions(-) diff --git a/framework/snippets/src/network_response.rs b/framework/snippets/src/network_response.rs index ea10ade8f3..0140dd839e 100644 --- a/framework/snippets/src/network_response.rs +++ b/framework/snippets/src/network_response.rs @@ -78,9 +78,9 @@ fn process_logs(tx: &TransactionOnNetwork) -> Vec { fn extract_data(event: &Events) -> Vec> { let mut out: Vec> = Vec::new(); - if let Some(data) = &event.data { - data.for_each(|data_field| out.push(data_field.clone().into_bytes())); - } + event + .data + .for_each(|data_field| out.push(data_field.clone().into_bytes())); out } @@ -98,18 +98,16 @@ fn process_out_from_log(tx: &TransactionOnNetwork) -> Option>> { if let Some(logs) = &tx.logs { logs.events.iter().rev().find_map(|event| { if event.identifier == "writeLog" { - if let Some(data) = &event.data { - let mut out = Vec::new(); - data.for_each(|data_member| { - let decoded_data = String::from_utf8(base64_decode(data_member)).unwrap(); - - if decoded_data.starts_with('@') { - let out_content = decode_scr_data_or_panic(decoded_data.as_str()); - out.extend(out_content); - } - }); - return Some(out); - } + let mut out = Vec::new(); + event.data.for_each(|data_member| { + let decoded_data = String::from_utf8(base64_decode(data_member)).unwrap(); + + if decoded_data.starts_with('@') { + let out_content = decode_scr_data_or_panic(decoded_data.as_str()); + out.extend(out_content); + } + }); + return Some(out); } None diff --git a/sdk/core/src/data/transaction.rs b/sdk/core/src/data/transaction.rs index 774c366dfa..664ea3a08e 100644 --- a/sdk/core/src/data/transaction.rs +++ b/sdk/core/src/data/transaction.rs @@ -92,12 +92,15 @@ pub struct Events { pub address: Address, pub identifier: String, pub topics: Option>, - pub data: Option, + #[serde(default)] + pub data: LogData, } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Default, Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] #[serde(untagged)] pub enum LogData { + #[default] + Empty, String(String), Vec(Vec), } @@ -105,6 +108,7 @@ pub enum LogData { impl LogData { pub fn for_each(&self, mut f: F) { match self { + LogData::Empty => {}, LogData::String(s) => f(s), LogData::Vec(v) => v.iter().for_each(f), } @@ -227,3 +231,62 @@ pub struct SendTransactionsResponse { pub code: String, pub data: Option, } + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn parse_event_log_0() { + let data = r#" +{ + "address": "erd1qqqqqqqqqqqqqpgq0628nau8zydgwu96fn8ksqklzhrggkcfq33sm4vmwv", + "identifier": "completedTxEvent", + "topics": [], + "data": null, + "additionalData": null +} + "#; + + let event_log = serde_json::from_str::(data).unwrap(); + assert_eq!(event_log.data, LogData::Empty); + } + + #[test] + fn parse_event_log_1() { + let data = r#" +{ + "address": "erd1qqqqqqqqqqqqqpgq0628nau8zydgwu96fn8ksqklzhrggkcfq33sm4vmwv", + "identifier": "completedTxEvent", + "topics": [], + "data": "data-string", + "additionalData": null +} + "#; + + let event_log = serde_json::from_str::(data).unwrap(); + assert_eq!(event_log.data, LogData::String("data-string".to_owned())); + } + + #[test] + fn parse_event_log_2() { + let data = r#" +{ + "address": "erd1qqqqqqqqqqqqqpgq0628nau8zydgwu96fn8ksqklzhrggkcfq33sm4vmwv", + "identifier": "completedTxEvent", + "topics": [], + "data": [ + "data1", + "data2" + ], + "additionalData": null +} + "#; + + let event_log = serde_json::from_str::(data).unwrap(); + assert_eq!( + event_log.data, + LogData::Vec(vec!["data1".to_owned(), "data2".to_owned()]) + ); + } +} From d2d2d15fa5eacc8f9040ebbeb8e7e95d70804af7 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Wed, 4 Sep 2024 08:52:58 +0300 Subject: [PATCH 91/92] mandos refactor --- .../scenarios/managed_decimal.scen.json | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/contracts/feature-tests/basic-features/scenarios/managed_decimal.scen.json b/contracts/feature-tests/basic-features/scenarios/managed_decimal.scen.json index e23747e4fb..479b8931c3 100644 --- a/contracts/feature-tests/basic-features/scenarios/managed_decimal.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/managed_decimal.scen.json @@ -150,15 +150,15 @@ "to": "sc:basic-features", "function": "managed_decimal_addition_var", "arguments": [ - "0x000000010400000002", - "0x000000010500000002" + "biguint:4|u32:2", + "biguint:5|u32:2" ], "gasLimit": "1,000,000,000,000", "gasPrice": "0" }, "expect": { "out": [ - "0x000000010900000002" + "biguint:9|u32:2" ] } }, @@ -170,15 +170,15 @@ "to": "sc:basic-features", "function": "managed_decimal_subtraction_var", "arguments": [ - "0x000000010900000002", - "0x000000010400000002" + "biguint:9|u32:2", + "biguint:4|u32:2" ], "gasLimit": "1,000,000,000,000", "gasPrice": "0" }, "expect": { "out": [ - "0x000000010500000002" + "biguint:5|u32:2" ] } }, @@ -190,8 +190,8 @@ "to": "sc:basic-features", "function": "managed_decimal_subtraction_var", "arguments": [ - "0x000000010200000002", - "0x000000010800000002" + "biguint:2|u32:2", + "biguint:8|u32:2" ], "gasLimit": "1,000,000,000,000", "gasPrice": "0" @@ -212,15 +212,15 @@ "to": "sc:basic-features", "function": "managed_decimal_eq_var", "arguments": [ - "0x000000010d00000002", - "0x000000010d00000002" + "biguint:11|u32:2", + "biguint:11|u32:2" ], "gasLimit": "1,000,000,000,000", "gasPrice": "0" }, "expect": { "out": [ - "0x01" + "true" ], "status": "", "message": "*", From 1aa35d69293d2109fd655260ab68f69601f5b43a Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Wed, 4 Sep 2024 09:39:56 +0300 Subject: [PATCH 92/92] dependency upgrade --- Cargo.lock | 32 ++++++++++++++++---------------- data/codec-derive/Cargo.toml | 2 +- framework/derive/Cargo.toml | 2 +- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bb45b11227..19a7d86bac 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -392,9 +392,9 @@ checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" [[package]] name = "cc" -version = "1.1.14" +version = "1.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d2eb3cd3d1bf4529e31c215ee6f93ec5a3d536d9f578f93d9d33ee19562932" +checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" dependencies = [ "shlex", ] @@ -1559,9 +1559,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" dependencies = [ "equivalent", "hashbrown", @@ -2309,9 +2309,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.3" +version = "0.36.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9" +checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" dependencies = [ "memchr", ] @@ -2930,18 +2930,18 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] [[package]] name = "rustix" -version = "0.38.34" +version = "0.38.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "a85d50532239da68e9addb745ba38ff4612a242c1c7ceea689c4bc7c2f43c36f" dependencies = [ "bitflags", "errno", @@ -2981,9 +2981,9 @@ checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" [[package]] name = "rustls-webpki" -version = "0.102.6" +version = "0.102.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" +checksum = "84678086bd54edf2b415183ed7a94d0efb049f1b646a33e22a36f3794be6ae56" dependencies = [ "ring", "rustls-pki-types", @@ -3357,9 +3357,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.76" +version = "2.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578e081a14e0cefc3279b0472138c513f37b41a08d5a3cca9b6e4e8ceb6cd525" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" dependencies = [ "proc-macro2", "quote", @@ -3481,9 +3481,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.39.3" +version = "1.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" dependencies = [ "backtrace", "bytes", diff --git a/data/codec-derive/Cargo.toml b/data/codec-derive/Cargo.toml index 707de3c33a..a738579380 100644 --- a/data/codec-derive/Cargo.toml +++ b/data/codec-derive/Cargo.toml @@ -23,5 +23,5 @@ default = ["syn/full", "syn/parsing", "syn/extra-traits"] [dependencies] proc-macro2 = "=1.0.86" quote = "=1.0.37" -syn = "=2.0.76" +syn = "=2.0.77" hex = "=0.4.3" diff --git a/framework/derive/Cargo.toml b/framework/derive/Cargo.toml index d4246c314b..111a7447c7 100644 --- a/framework/derive/Cargo.toml +++ b/framework/derive/Cargo.toml @@ -16,7 +16,7 @@ categories = ["cryptography::cryptocurrencies", "development-tools::procedural-m [dependencies] proc-macro2 = "=1.0.86" quote = "=1.0.37" -syn = "=2.0.76" +syn = "=2.0.77" hex = "=0.4.3" radix_trie = "=0.2.1"