From ee8a82aef97e4401e7f59dcb1feecbe22dd3de88 Mon Sep 17 00:00:00 2001 From: JustEatAnApple Date: Wed, 28 Aug 2024 12:31:12 +0300 Subject: [PATCH 1/3] Suggested fix for ReturnsNewTokenIdentifier Co-authored-by: Andrei Vasilescu --- 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: Wed, 28 Aug 2024 18:31:52 +0300 Subject: [PATCH 2/3] [WIP] Testing branch for ReturnsNewTokenIdentifier Co-authored-by: Andrei Vasilescu --- Cargo.lock | 54 +++ Cargo.toml | 7 + .../proxy-test/Cargo.toml | 17 + .../proxy-test/README.md | 3 + .../proxy-test/interact/.gitignore | 9 + .../proxy-test/interact/Cargo.toml | 29 ++ .../proxy-test/interact/config.toml | 1 + .../proxy-test/interact/src/basic_interact.rs | 324 ++++++++++++++++++ .../interact/src/basic_interact_cli.rs | 56 +++ .../interact/src/basic_interact_config.rs | 26 ++ .../interact/src/basic_interact_state.rs | 50 +++ .../proxy-test/meta/Cargo.toml | 13 + .../proxy-test/meta/src/main.rs | 3 + .../proxy-test/multiversx.json | 3 + .../proxy-test/sc-config.toml | 8 + .../scenarios/interactor_trace.scen.json | 76 ++++ .../proxy-test/scenarios/proxy_test.scen.json | 99 ++++++ .../proxy-test/src/proxy_test.rs | 105 ++++++ .../proxy-test/src/proxy_test_proxy.rs | 166 +++++++++ .../tests/proxy_test_blackbox_test.rs | 80 +++++ .../tests/proxy_test_scenario_go_test.rs | 15 + .../tests/proxy_test_scenario_rs_test.rs | 18 + .../proxy-test/tests/proxy_test_unit_test.rs | 17 + .../tests/proxy_test_whitebox_test.rs | 49 +++ .../proxy-test/wasm/Cargo.lock | 178 ++++++++++ .../proxy-test/wasm/Cargo.toml | 35 ++ .../proxy-test/wasm/src/lib.rs | 32 ++ .../returns-token-identifier-test/Cargo.toml | 17 + .../returns-token-identifier-test/README.md | 3 + .../interact/.gitignore | 9 + .../interact/Cargo.toml | 28 ++ .../interact/config.toml | 1 + .../interact/src/basic_interact.rs | 245 +++++++++++++ .../interact/src/basic_interact_cli.rs | 52 +++ .../interact/src/basic_interact_config.rs | 26 ++ .../interact/src/basic_interact_state.rs | 50 +++ .../meta/Cargo.toml | 14 + .../meta/src/main.rs | 3 + .../multiversx.json | 3 + .../sc-config.toml | 4 + .../scenarios/interactor_trace.scen.json | 76 ++++ .../returns_token_identifier_test.scen.json | 99 ++++++ .../src/returns_token_identifier_test.rs | 31 ++ .../returns_token_identifier_test_proxy.rs | 114 ++++++ ...rns_token_identifier_test_blackbox_test.rs | 80 +++++ ..._token_identifier_test_scenario_go_test.rs | 15 + ..._token_identifier_test_scenario_rs_test.rs | 18 + ...returns_token_identifier_test_unit_test.rs | 17 + ...rns_token_identifier_test_whitebox_test.rs | 49 +++ 49 files changed, 2427 insertions(+) create mode 100644 contracts/examples/token-identifier-test/proxy-test/Cargo.toml create mode 100644 contracts/examples/token-identifier-test/proxy-test/README.md create mode 100644 contracts/examples/token-identifier-test/proxy-test/interact/.gitignore create mode 100644 contracts/examples/token-identifier-test/proxy-test/interact/Cargo.toml create mode 100644 contracts/examples/token-identifier-test/proxy-test/interact/config.toml create mode 100644 contracts/examples/token-identifier-test/proxy-test/interact/src/basic_interact.rs create mode 100644 contracts/examples/token-identifier-test/proxy-test/interact/src/basic_interact_cli.rs create mode 100644 contracts/examples/token-identifier-test/proxy-test/interact/src/basic_interact_config.rs create mode 100644 contracts/examples/token-identifier-test/proxy-test/interact/src/basic_interact_state.rs create mode 100644 contracts/examples/token-identifier-test/proxy-test/meta/Cargo.toml create mode 100644 contracts/examples/token-identifier-test/proxy-test/meta/src/main.rs create mode 100644 contracts/examples/token-identifier-test/proxy-test/multiversx.json create mode 100644 contracts/examples/token-identifier-test/proxy-test/sc-config.toml create mode 100644 contracts/examples/token-identifier-test/proxy-test/scenarios/interactor_trace.scen.json create mode 100644 contracts/examples/token-identifier-test/proxy-test/scenarios/proxy_test.scen.json create mode 100644 contracts/examples/token-identifier-test/proxy-test/src/proxy_test.rs create mode 100644 contracts/examples/token-identifier-test/proxy-test/src/proxy_test_proxy.rs create mode 100644 contracts/examples/token-identifier-test/proxy-test/tests/proxy_test_blackbox_test.rs create mode 100644 contracts/examples/token-identifier-test/proxy-test/tests/proxy_test_scenario_go_test.rs create mode 100644 contracts/examples/token-identifier-test/proxy-test/tests/proxy_test_scenario_rs_test.rs create mode 100644 contracts/examples/token-identifier-test/proxy-test/tests/proxy_test_unit_test.rs create mode 100644 contracts/examples/token-identifier-test/proxy-test/tests/proxy_test_whitebox_test.rs create mode 100644 contracts/examples/token-identifier-test/proxy-test/wasm/Cargo.lock create mode 100644 contracts/examples/token-identifier-test/proxy-test/wasm/Cargo.toml create mode 100644 contracts/examples/token-identifier-test/proxy-test/wasm/src/lib.rs create mode 100644 contracts/examples/token-identifier-test/returns-token-identifier-test/Cargo.toml create mode 100644 contracts/examples/token-identifier-test/returns-token-identifier-test/README.md create mode 100644 contracts/examples/token-identifier-test/returns-token-identifier-test/interact/.gitignore create mode 100644 contracts/examples/token-identifier-test/returns-token-identifier-test/interact/Cargo.toml create mode 100644 contracts/examples/token-identifier-test/returns-token-identifier-test/interact/config.toml create mode 100644 contracts/examples/token-identifier-test/returns-token-identifier-test/interact/src/basic_interact.rs create mode 100644 contracts/examples/token-identifier-test/returns-token-identifier-test/interact/src/basic_interact_cli.rs create mode 100644 contracts/examples/token-identifier-test/returns-token-identifier-test/interact/src/basic_interact_config.rs create mode 100644 contracts/examples/token-identifier-test/returns-token-identifier-test/interact/src/basic_interact_state.rs create mode 100644 contracts/examples/token-identifier-test/returns-token-identifier-test/meta/Cargo.toml create mode 100644 contracts/examples/token-identifier-test/returns-token-identifier-test/meta/src/main.rs create mode 100644 contracts/examples/token-identifier-test/returns-token-identifier-test/multiversx.json create mode 100644 contracts/examples/token-identifier-test/returns-token-identifier-test/sc-config.toml create mode 100644 contracts/examples/token-identifier-test/returns-token-identifier-test/scenarios/interactor_trace.scen.json create mode 100644 contracts/examples/token-identifier-test/returns-token-identifier-test/scenarios/returns_token_identifier_test.scen.json create mode 100644 contracts/examples/token-identifier-test/returns-token-identifier-test/src/returns_token_identifier_test.rs create mode 100644 contracts/examples/token-identifier-test/returns-token-identifier-test/src/returns_token_identifier_test_proxy.rs create mode 100644 contracts/examples/token-identifier-test/returns-token-identifier-test/tests/returns_token_identifier_test_blackbox_test.rs create mode 100644 contracts/examples/token-identifier-test/returns-token-identifier-test/tests/returns_token_identifier_test_scenario_go_test.rs create mode 100644 contracts/examples/token-identifier-test/returns-token-identifier-test/tests/returns_token_identifier_test_scenario_rs_test.rs create mode 100644 contracts/examples/token-identifier-test/returns-token-identifier-test/tests/returns_token_identifier_test_unit_test.rs create mode 100644 contracts/examples/token-identifier-test/returns-token-identifier-test/tests/returns_token_identifier_test_whitebox_test.rs diff --git a/Cargo.lock b/Cargo.lock index fecbf652fe..81916d1c9a 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -258,6 +258,28 @@ dependencies = [ "toml", ] +[[package]] +name = "basic-interact-proxy" +version = "0.0.0" +dependencies = [ + "clap", + "multiversx-sc-snippets", + "proxy-test", + "serde", + "toml", +] + +[[package]] +name = "basic-interact-token" +version = "0.0.0" +dependencies = [ + "clap", + "multiversx-sc-snippets", + "returns-token-identifier-test", + "serde", + "toml", +] + [[package]] name = "bech32" version = "0.9.1" @@ -2600,6 +2622,14 @@ dependencies = [ "proxy-pause", ] +[[package]] +name = "proxy-test" +version = "0.0.0" +dependencies = [ + "multiversx-sc", + "multiversx-sc-scenario", +] + [[package]] name = "proxy-test-first" version = "0.0.0" @@ -2617,6 +2647,14 @@ dependencies = [ "proxy-test-first", ] +[[package]] +name = "proxy-test-meta" +version = "0.0.0" +dependencies = [ + "multiversx-sc-meta-lib", + "proxy-test", +] + [[package]] name = "proxy-test-second" version = "0.0.0" @@ -2855,6 +2893,22 @@ dependencies = [ "winreg", ] +[[package]] +name = "returns-token-identifier-test" +version = "0.0.0" +dependencies = [ + "multiversx-sc", + "multiversx-sc-scenario", +] + +[[package]] +name = "returns-token-identifier-test-meta" +version = "0.0.0" +dependencies = [ + "multiversx-sc-meta-lib", + "returns-token-identifier-test", +] + [[package]] name = "rewards-distribution" version = "0.0.0" diff --git a/Cargo.toml b/Cargo.toml index 2f599c6e03..a563ad80d1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -104,6 +104,13 @@ members = [ "contracts/examples/token-release", "contracts/examples/token-release/meta", + "contracts/examples/token-identifier-test/proxy-test", + "contracts/examples/token-identifier-test/proxy-test/meta", + "contracts/examples/token-identifier-test/proxy-test/interact", + "contracts/examples/token-identifier-test/returns-token-identifier-test", + "contracts/examples/token-identifier-test/returns-token-identifier-test/meta", + "contracts/examples/token-identifier-test/returns-token-identifier-test/interact", + "contracts/feature-tests/abi-tester", "contracts/feature-tests/abi-tester/meta", "contracts/feature-tests/alloc-features", diff --git a/contracts/examples/token-identifier-test/proxy-test/Cargo.toml b/contracts/examples/token-identifier-test/proxy-test/Cargo.toml new file mode 100644 index 0000000000..5d97921b63 --- /dev/null +++ b/contracts/examples/token-identifier-test/proxy-test/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "proxy-test" +version = "0.0.0" +publish = false +edition = "2021" +authors = ["you"] + +[lib] +path = "src/proxy_test.rs" + +[dependencies.multiversx-sc] +version = "0.52.3" +path = "../../../../framework/base" + +[dev-dependencies.multiversx-sc-scenario] +version = "0.52.3" +path = "../../../../framework/scenario" diff --git a/contracts/examples/token-identifier-test/proxy-test/README.md b/contracts/examples/token-identifier-test/proxy-test/README.md new file mode 100644 index 0000000000..4538caeca9 --- /dev/null +++ b/contracts/examples/token-identifier-test/proxy-test/README.md @@ -0,0 +1,3 @@ +# Adder + +`Adder` is a simple Smart Contract. diff --git a/contracts/examples/token-identifier-test/proxy-test/interact/.gitignore b/contracts/examples/token-identifier-test/proxy-test/interact/.gitignore new file mode 100644 index 0000000000..b2630809de --- /dev/null +++ b/contracts/examples/token-identifier-test/proxy-test/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/contracts/examples/token-identifier-test/proxy-test/interact/Cargo.toml b/contracts/examples/token-identifier-test/proxy-test/interact/Cargo.toml new file mode 100644 index 0000000000..8ce0ed6bd7 --- /dev/null +++ b/contracts/examples/token-identifier-test/proxy-test/interact/Cargo.toml @@ -0,0 +1,29 @@ +[[bin]] +name = "basic-interact-proxy" +path = "src/basic_interact.rs" + +[package] +name = "basic-interact-proxy" +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.proxy-test] +path = ".." + +[dependencies.multiversx-sc-snippets] +version = "0.52.3" +path = "../../../../../framework/snippets" + diff --git a/contracts/examples/token-identifier-test/proxy-test/interact/config.toml b/contracts/examples/token-identifier-test/proxy-test/interact/config.toml new file mode 100644 index 0000000000..61ac8dbf87 --- /dev/null +++ b/contracts/examples/token-identifier-test/proxy-test/interact/config.toml @@ -0,0 +1 @@ +gateway = 'https://devnet-gateway.multiversx.com' diff --git a/contracts/examples/token-identifier-test/proxy-test/interact/src/basic_interact.rs b/contracts/examples/token-identifier-test/proxy-test/interact/src/basic_interact.rs new file mode 100644 index 0000000000..bfec3c5130 --- /dev/null +++ b/contracts/examples/token-identifier-test/proxy-test/interact/src/basic_interact.rs @@ -0,0 +1,324 @@ +mod basic_interact_cli; +mod basic_interact_config; +mod basic_interact_state; + +use proxy_test::proxy_test_proxy; +use basic_interact_config::Config; +use basic_interact_state::State; +use clap::Parser; + +use multiversx_sc_snippets::imports::*; + +const INTERACTOR_SCENARIO_TRACE_PATH: &str = "interactor_trace.scen.json"; + +const ADDER_CODE_PATH: MxscPath = MxscPath::new("../output/proxy-test.mxsc.json"); + +#[tokio::main] +async fn main() { + env_logger::init(); + + let mut basic_interact = ProxyTestInteract::init().await; + + let cli = basic_interact_cli::InteractCli::parse(); + match &cli.command { + Some(basic_interact_cli::InteractCliCommand::Add(args)) => { + if args.count == 1 { + basic_interact.add(args.value).await; + } else { + basic_interact.multi_add(args.value, args.count).await; + } + }, + Some(basic_interact_cli::InteractCliCommand::Deploy) => { + basic_interact.deploy().await; + }, + Some(basic_interact_cli::InteractCliCommand::Feed) => { + basic_interact.feed_contract_egld().await; + }, + Some(basic_interact_cli::InteractCliCommand::MultiDeploy(args)) => { + basic_interact.multi_deploy(args.count).await; + }, + Some(basic_interact_cli::InteractCliCommand::Sum) => { + basic_interact.print_sum().await; + }, + Some(basic_interact_cli::InteractCliCommand::Upgrade(args)) => { + basic_interact.upgrade(args.value).await + }, + Some(basic_interact_cli::InteractCliCommand::Issue) => { + basic_interact.issue_fungible_token().await + }, + Some(basic_interact_cli::InteractCliCommand::ViewLastIssued) => { + basic_interact.last_issued_token().await; + }, + None => {}, + } +} + +#[allow(unused)] +struct ProxyTestInteract { + interactor: Interactor, + adder_owner_address: Bech32Address, + wallet_address: Bech32Address, + state: State, +} + +impl ProxyTestInteract { + async fn init() -> Self { + let config = Config::load_config(); + let mut interactor = Interactor::new(config.gateway()) + .await + .with_tracer(INTERACTOR_SCENARIO_TRACE_PATH) + .await; + + let adder_owner_address = interactor.register_wallet(test_wallets::mike()); + let wallet_address = interactor.register_wallet(test_wallets::mike()); + + 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); + self.interactor + .retrieve_account(&self.adder_owner_address) + .await; + self.interactor.retrieve_account(&self.wallet_address).await; + } + + async fn deploy(&mut self) { + // warning: multi deploy not yet fully supported + // only works with last deployed address + + self.set_state().await; + + let new_address = self + .interactor + .tx() + .from(&self.adder_owner_address) + .gas(30_000_000) + .typed(proxy_test_proxy::ProxyTestProxy) + .init(0u32) + .code(ADDER_CODE_PATH) + .code_metadata(CodeMetadata::UPGRADEABLE) + .returns(ReturnsNewBech32Address) + .prepare_async() + .run() + .await; + + println!("new address: {new_address}"); + self.state.set_adder_address(new_address); + } + + async fn multi_deploy(&mut self, count: usize) { + if count == 0 { + println!("count must be greater than 0"); + return; + } + + self.set_state().await; + println!("deploying {count} contracts..."); + + let mut buffer = self.interactor.homogenous_call_buffer(); + for _ in 0..count { + buffer.push_tx(|tx| { + tx.from(&self.wallet_address) + .typed(proxy_test_proxy::ProxyTestProxy) + .init(0u32) + .code(ADDER_CODE_PATH) + .gas(30_000_000) + .returns(ReturnsNewBech32Address) + }); + } + + let results = buffer.run().await; + + // warning: multi deploy not yet fully supported + // only works with last deployed address + + for new_address in results { + println!("new address: {new_address}"); + + self.state.set_adder_address(new_address); + } + } + + async fn multi_add(&mut self, value: u32, count: usize) { + self.set_state().await; + println!("calling contract {count} times..."); + + let mut buffer = self.interactor.homogenous_call_buffer(); + for _ in 0..count { + buffer.push_tx(|tx| { + tx.from(&self.wallet_address) + .to(self.state.current_adder_address()) + .typed(proxy_test_proxy::ProxyTestProxy) + .add(value) + .gas(30_000_000) + }); + } + + let _ = buffer.run().await; + + println!("successfully performed add {count} times"); + } + + async fn feed_contract_egld(&mut self) { + self.interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_adder_address()) + .egld(NumExpr("0,050000000000000000")) + .prepare_async() + .run() + .await; + } + + async fn add(&mut self, value: u32) { + self.interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_adder_address()) + .gas(30_000_000) + .typed(proxy_test_proxy::ProxyTestProxy) + .add(value) + .prepare_async() + .run() + .await; + + println!("successfully performed add"); + } + + async fn print_sum(&mut self) { + let sum = self + .interactor + .query() + .to(self.state.current_adder_address()) + .typed(proxy_test_proxy::ProxyTestProxy) + .sum() + .returns(ReturnsResultUnmanaged) + .prepare_async() + .run() + .await; + + println!("sum: {sum}"); + } + + async fn last_issued_token(&mut self) { + let result_value = self + .interactor + .query() + .to(self.state.current_adder_address()) + .typed(proxy_test_proxy::ProxyTestProxy) + .last_issued_token() + .returns(ReturnsResultUnmanaged) + .prepare_async() + .run() + .await; + + println!("Result: {result_value:?}"); + } + + async fn last_error_message(&mut self) { + let result_value = self + .interactor + .query() + .to(self.state.current_adder_address()) + .typed(proxy_test_proxy::ProxyTestProxy) + .last_error_message() + .returns(ReturnsResultUnmanaged) + .prepare_async() + .run() + .await; + + println!("Result: {result_value:?}"); + } + + async fn upgrade(&mut self, new_value: u32) { + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_adder_address()) + .gas(30_000_000) + .typed(proxy_test_proxy::ProxyTestProxy) + .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(proxy_test_proxy::ProxyTestProxy) + .sum() + .returns(ReturnsResultUnmanaged) + .prepare_async() + .run() + .await; + assert_eq!(sum, RustBigUint::from(new_value)); + + println!("response: {response:?}"); + } + + async fn issue_fungible_token(&mut self) { + let egld_amount = BigUint::::from(50000000000000000u128); + + let token_display_name = ManagedBuffer::from("PROXYTOKEN"); + let token_ticker = ManagedBuffer::from("PRXY"); + let initial_supply = BigUint::::from(100000000000000000000u128); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_adder_address()) + .gas(60_000_000u64) + .typed(proxy_test_proxy::ProxyTestProxy) + .issue_fungible_token(token_display_name, token_ticker, initial_supply) + .egld(egld_amount) + .returns(ReturnsNewTokenIdentifier) + .prepare_async() + .run() + .await; + + println!("Result: {response:?}"); + } + + async fn send_egld(&mut self) { + let to = bech32::decode(""); + let amount = BigUint::::from(0u128); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_adder_address()) + .gas(60_000_000u64) + .typed(proxy_test_proxy::ProxyTestProxy) + .send_egld(to, amount) + .returns(ReturnsResultUnmanaged) + .prepare_async() + .run() + .await; + + println!("Result: {response:?}"); + } +} + +#[tokio::test] +#[ignore = "run on demand"] +async fn test() { + let mut basic_interact = ProxyTestInteract::init().await; + + basic_interact.deploy().await; + basic_interact.add(1u32).await; + + basic_interact.upgrade(7u32).await; +} diff --git a/contracts/examples/token-identifier-test/proxy-test/interact/src/basic_interact_cli.rs b/contracts/examples/token-identifier-test/proxy-test/interact/src/basic_interact_cli.rs new file mode 100644 index 0000000000..1c0fad8e53 --- /dev/null +++ b/contracts/examples/token-identifier-test/proxy-test/interact/src/basic_interact_cli.rs @@ -0,0 +1,56 @@ +use clap::{Args, Parser, Subcommand}; + +/// ProxyTest Interact CLI +#[derive(Default, PartialEq, Eq, Debug, Parser)] +#[command(version, about)] +#[command(propagate_version = true)] +pub struct InteractCli { + #[command(subcommand)] + pub command: Option, +} + +/// ProxyTest 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 = "view", about = "View Last Issued Token")] + ViewLastIssued, + #[command(name = "upgrade", about = "Upgrade contract")] + Upgrade(UpgradeArgs), + #[command(name = "issue", about = "Issues a token")] + Issue, +} + +#[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/token-identifier-test/proxy-test/interact/src/basic_interact_config.rs b/contracts/examples/token-identifier-test/proxy-test/interact/src/basic_interact_config.rs new file mode 100644 index 0000000000..e71bba553d --- /dev/null +++ b/contracts/examples/token-identifier-test/proxy-test/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"; + +/// ProxyTest 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/token-identifier-test/proxy-test/interact/src/basic_interact_state.rs b/contracts/examples/token-identifier-test/proxy-test/interact/src/basic_interact_state.rs new file mode 100644 index 0000000000..41453e36fd --- /dev/null +++ b/contracts/examples/token-identifier-test/proxy-test/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(); + } +} diff --git a/contracts/examples/token-identifier-test/proxy-test/meta/Cargo.toml b/contracts/examples/token-identifier-test/proxy-test/meta/Cargo.toml new file mode 100644 index 0000000000..3908d7714a --- /dev/null +++ b/contracts/examples/token-identifier-test/proxy-test/meta/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "proxy-test-meta" +version = "0.0.0" +edition = "2021" +publish = false + +[dependencies.proxy-test] +path = ".." + +[dependencies.multiversx-sc-meta-lib] +version = "0.52.3" +path = "../../../../../framework/meta-lib" +default-features = false diff --git a/contracts/examples/token-identifier-test/proxy-test/meta/src/main.rs b/contracts/examples/token-identifier-test/proxy-test/meta/src/main.rs new file mode 100644 index 0000000000..740dbc8ce1 --- /dev/null +++ b/contracts/examples/token-identifier-test/proxy-test/meta/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + multiversx_sc_meta_lib::cli_main::(); +} diff --git a/contracts/examples/token-identifier-test/proxy-test/multiversx.json b/contracts/examples/token-identifier-test/proxy-test/multiversx.json new file mode 100644 index 0000000000..7365539625 --- /dev/null +++ b/contracts/examples/token-identifier-test/proxy-test/multiversx.json @@ -0,0 +1,3 @@ +{ + "language": "rust" +} \ No newline at end of file diff --git a/contracts/examples/token-identifier-test/proxy-test/sc-config.toml b/contracts/examples/token-identifier-test/proxy-test/sc-config.toml new file mode 100644 index 0000000000..e4693e8ab1 --- /dev/null +++ b/contracts/examples/token-identifier-test/proxy-test/sc-config.toml @@ -0,0 +1,8 @@ +[settings] + +[[proxy]] +path = "src/proxy_test_proxy.rs" + +[[proxy]] +path = "interactor/src/proxy.rs" + diff --git a/contracts/examples/token-identifier-test/proxy-test/scenarios/interactor_trace.scen.json b/contracts/examples/token-identifier-test/proxy-test/scenarios/interactor_trace.scen.json new file mode 100644 index 0000000000..282c1d4746 --- /dev/null +++ b/contracts/examples/token-identifier-test/proxy-test/scenarios/interactor_trace.scen.json @@ -0,0 +1,76 @@ +{ + "steps": [ + { + "step": "setState", + "accounts": { + "0xe32afedc904fe1939746ad973beb383563cf63642ba669b3040f9b9428a5ed60": { + "nonce": "481", + "balance": "106274669842530000003", + "esdt": { + "str:CAN-14dc0a": "1000", + "str:CAN-2abf4b": "1000", + "str:CAN-6d39e6": "1000", + "str:CAN-ac1592": "1000" + } + } + } + }, + { + "step": "setState", + "newAddresses": [ + { + "creatorAddress": "0xe32afedc904fe1939746ad973beb383563cf63642ba669b3040f9b9428a5ed60", + "creatorNonce": "481", + "newAddress": "0x0000000000000000050028600ceb73ac22ec0b6f257aff7bed74dffa3ebfed60" + } + ] + }, + { + "step": "scDeploy", + "tx": { + "from": "0xe32afedc904fe1939746ad973beb383563cf63642ba669b3040f9b9428a5ed60", + "contractCode": "mxsc:../output/proxy-test.mxsc.json", + "arguments": [ + "0x00" + ], + "gasLimit": "70,000,000" + }, + "expect": { + "out": [], + "status": "0" + } + }, + { + "step": "scCall", + "tx": { + "from": "0xe32afedc904fe1939746ad973beb383563cf63642ba669b3040f9b9428a5ed60", + "to": "0x0000000000000000050028600ceb73ac22ec0b6f257aff7bed74dffa3ebfed60", + "function": "add", + "arguments": [ + "0x07" + ], + "gasLimit": "70,000,000" + }, + "expect": { + "out": [], + "status": "0" + } + }, + { + "step": "scCall", + "tx": { + "from": "0xe32afedc904fe1939746ad973beb383563cf63642ba669b3040f9b9428a5ed60", + "to": "0x0000000000000000050028600ceb73ac22ec0b6f257aff7bed74dffa3ebfed60", + "function": "add", + "arguments": [ + "0x05" + ], + "gasLimit": "70,000,000" + }, + "expect": { + "out": [], + "status": "0" + } + } + ] +} diff --git a/contracts/examples/token-identifier-test/proxy-test/scenarios/proxy_test.scen.json b/contracts/examples/token-identifier-test/proxy-test/scenarios/proxy_test.scen.json new file mode 100644 index 0000000000..39503c7e2b --- /dev/null +++ b/contracts/examples/token-identifier-test/proxy-test/scenarios/proxy_test.scen.json @@ -0,0 +1,99 @@ +{ + "name": "adder", + "comment": "add then check", + "gasSchedule": "v3", + "steps": [ + { + "step": "setState", + "accounts": { + "address:owner": { + "nonce": "1", + "balance": "0" + } + }, + "newAddresses": [ + { + "creatorAddress": "address:owner", + "creatorNonce": "1", + "newAddress": "sc:adder" + } + ] + }, + { + "step": "scDeploy", + "id": "1", + "tx": { + "from": "address:owner", + "contractCode": "mxsc:../output/proxy-test.mxsc.json", + "arguments": [ + "5" + ], + "gasLimit": "5,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [], + "status": "", + "logs": "*", + "gas": "*", + "refund": "*" + } + }, + { + "step": "scQuery", + "id": "2", + "tx": { + "to": "sc:adder", + "function": "getSum", + "arguments": [] + }, + "expect": { + "out": [ + "5" + ], + "status": "", + "logs": [] + } + }, + { + "step": "scCall", + "id": "3", + "tx": { + "from": "address:owner", + "to": "sc:adder", + "function": "add", + "arguments": [ + "3" + ], + "gasLimit": "5,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [], + "status": "", + "logs": "*", + "gas": "*", + "refund": "*" + } + }, + { + "step": "checkState", + "accounts": { + "address:owner": { + "nonce": "*", + "balance": "0", + "storage": {}, + "code": "" + }, + "sc:adder": { + "nonce": "0", + "balance": "0", + "storage": { + "str:sum": "8" + }, + "code": "mxsc:../output/proxy-test.mxsc.json" + } + } + } + ] +} diff --git a/contracts/examples/token-identifier-test/proxy-test/src/proxy_test.rs b/contracts/examples/token-identifier-test/proxy-test/src/proxy_test.rs new file mode 100644 index 0000000000..02a45adb47 --- /dev/null +++ b/contracts/examples/token-identifier-test/proxy-test/src/proxy_test.rs @@ -0,0 +1,105 @@ +#![no_std] + +use multiversx_sc::imports::*; + +pub mod proxy_test_proxy; + +/// One of the simplest smart contracts possible, +/// it holds a single variable in storage, which anyone can increment. +#[multiversx_sc::contract] +pub trait ProxyTest { + #[view(lastIssuedToken)] + #[storage_mapper("lastIssuedToken")] + fn last_issued_token(&self) -> SingleValueMapper; + + #[view(lastErrorMessage)] + #[storage_mapper("lastErrorMessage")] + fn last_error_message(&self) -> SingleValueMapper; + + #[view(getSum)] + #[storage_mapper("sum")] + fn sum(&self) -> SingleValueMapper; + + #[init] + fn init(&self, initial_value: BigUint) { + self.sum().set(initial_value); + } + + #[upgrade] + fn upgrade(&self, initial_value: BigUint) { + self.init(initial_value); + } + + /// Add desired amount to the storage variable. + #[endpoint] + fn add(&self, value: BigUint) { + self.sum().update(|sum| *sum += value); + } + + #[payable("EGLD")] + #[endpoint] + fn issue_fungible_token( + &self, + token_display_name: ManagedBuffer, + token_ticker: ManagedBuffer, + initial_supply: BigUint, + ) { + let issue_cost = self.call_value().egld_value(); + let caller = self.blockchain().get_caller(); + + self.send() + .esdt_system_sc_proxy() + .issue_fungible( + issue_cost.clone_value(), + &token_display_name, + &token_ticker, + &initial_supply, + FungibleTokenProperties { + num_decimals: 18, + 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, + }, + ) + .with_callback(self.callbacks().esdt_issue_callback(&caller)) + .async_call_and_exit() + } + + #[callback] + fn esdt_issue_callback( + &self, + caller: &ManagedAddress, + #[call_result] result: ManagedAsyncCallResult<()>, + ) { + let (token_identifier, returned_tokens) = self.call_value().egld_or_single_fungible_esdt(); + // callback is called with ESDTTransfer of the newly issued token, with the amount requested, + // 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_error_message().clear(); + }, + ManagedAsyncCallResult::Err(message) => { + // return issue cost to the caller + if token_identifier.is_egld() && returned_tokens > 0 { + self.tx().to(caller).egld(&returned_tokens).transfer(); + } + + self.last_error_message().set(&message.err_msg); + }, + } + } + + #[endpoint] + fn send_egld(&self, to: &ManagedAddress, amount: &BigUint) { + self.tx().to(to).egld(amount).transfer(); + } + + // 1. deploy + // 2. contract call --function(issue_fungible_token) -- arguments display_name, ticker, initial_supply +} diff --git a/contracts/examples/token-identifier-test/proxy-test/src/proxy_test_proxy.rs b/contracts/examples/token-identifier-test/proxy-test/src/proxy_test_proxy.rs new file mode 100644 index 0000000000..934bd2b156 --- /dev/null +++ b/contracts/examples/token-identifier-test/proxy-test/src/proxy_test_proxy.rs @@ -0,0 +1,166 @@ +// 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 ProxyTestProxy; + +impl TxProxyTrait for ProxyTestProxy +where + Env: TxEnv, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + type TxProxyMethods = ProxyTestProxyMethods; + + fn proxy_methods(self, tx: Tx) -> Self::TxProxyMethods { + ProxyTestProxyMethods { wrapped_tx: tx } + } +} + +pub struct ProxyTestProxyMethods +where + Env: TxEnv, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + wrapped_tx: Tx, +} + +#[rustfmt::skip] +impl ProxyTestProxyMethods +where + Env: TxEnv, + Env::Api: VMApi, + From: TxFrom, + Gas: TxGas, +{ + pub fn init< + Arg0: ProxyArg>, + >( + self, + initial_value: Arg0, + ) -> TxTypedDeploy { + self.wrapped_tx + .payment(NotPayable) + .raw_deploy() + .argument(&initial_value) + .original_result() + } +} + +#[rustfmt::skip] +impl ProxyTestProxyMethods +where + Env: TxEnv, + Env::Api: VMApi, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + pub fn upgrade< + Arg0: ProxyArg>, + >( + self, + initial_value: Arg0, + ) -> TxTypedUpgrade { + self.wrapped_tx + .payment(NotPayable) + .raw_upgrade() + .argument(&initial_value) + .original_result() + } +} + +#[rustfmt::skip] +impl ProxyTestProxyMethods +where + Env: TxEnv, + Env::Api: VMApi, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + pub fn last_issued_token( + self, + ) -> TxTypedCall> { + self.wrapped_tx + .payment(NotPayable) + .raw_call("lastIssuedToken") + .original_result() + } + + pub fn last_error_message( + self, + ) -> TxTypedCall> { + self.wrapped_tx + .payment(NotPayable) + .raw_call("lastErrorMessage") + .original_result() + } + + pub fn sum( + self, + ) -> TxTypedCall> { + self.wrapped_tx + .payment(NotPayable) + .raw_call("getSum") + .original_result() + } + + /// Add desired amount to the storage variable. + pub fn add< + Arg0: ProxyArg>, + >( + self, + value: Arg0, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("add") + .argument(&value) + .original_result() + } + + pub fn issue_fungible_token< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + Arg2: ProxyArg>, + >( + self, + token_display_name: Arg0, + token_ticker: Arg1, + initial_supply: Arg2, + ) -> TxTypedCall { + self.wrapped_tx + .raw_call("issue_fungible_token") + .argument(&token_display_name) + .argument(&token_ticker) + .argument(&initial_supply) + .original_result() + } + + pub fn send_egld< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + >( + self, + to: Arg0, + amount: Arg1, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("send_egld") + .argument(&to) + .argument(&amount) + .original_result() + } +} diff --git a/contracts/examples/token-identifier-test/proxy-test/tests/proxy_test_blackbox_test.rs b/contracts/examples/token-identifier-test/proxy-test/tests/proxy_test_blackbox_test.rs new file mode 100644 index 0000000000..930c13f0b5 --- /dev/null +++ b/contracts/examples/token-identifier-test/proxy-test/tests/proxy_test_blackbox_test.rs @@ -0,0 +1,80 @@ +use multiversx_sc_scenario::imports::*; + +use proxy_test::*; + +const OWNER_ADDRESS: TestAddress = TestAddress::new("owner"); +const ADDER_ADDRESS: TestSCAddress = TestSCAddress::new("adder"); +const CODE_PATH: MxscPath = MxscPath::new("output/proxy-test.mxsc.json"); + +fn world() -> ScenarioWorld { + let mut blockchain = ScenarioWorld::new(); + + blockchain.register_contract(CODE_PATH, proxy_test::ContractBuilder); + blockchain +} + +#[test] +fn adder_blackbox() { + let mut world = world(); + + world.start_trace(); + + world.account(OWNER_ADDRESS).nonce(1); + + let new_address = world + .tx() + .from(OWNER_ADDRESS) + .typed(proxy_test_proxy::ProxyTestProxy) + .init(5u32) + .code(CODE_PATH) + .new_address(ADDER_ADDRESS) + .returns(ReturnsNewAddress) + .run(); + + assert_eq!(new_address, ADDER_ADDRESS.to_address()); + + world + .query() + .to(ADDER_ADDRESS) + .typed(proxy_test_proxy::ProxyTestProxy) + .sum() + .returns(ExpectValue(5u32)) + .run(); + + world + .tx() + .from(OWNER_ADDRESS) + .to(ADDER_ADDRESS) + .typed(proxy_test_proxy::ProxyTestProxy) + .add(1u32) + .run(); + + world + .query() + .to(ADDER_ADDRESS) + .typed(proxy_test_proxy::ProxyTestProxy) + .sum() + .returns(ExpectValue(6u32)) + .run(); + + world.check_account(OWNER_ADDRESS); + + world + .check_account(ADDER_ADDRESS) + .check_storage("str:sum", "6"); + + world + .tx() + .from(OWNER_ADDRESS) + .to(ADDER_ADDRESS) + .typed(proxy_test_proxy::ProxyTestProxy) + .upgrade(100u64) + .code(CODE_PATH) + .run(); + + world + .check_account(ADDER_ADDRESS) + .check_storage("str:sum", "100"); + + world.write_scenario_trace("trace1.scen.json"); +} diff --git a/contracts/examples/token-identifier-test/proxy-test/tests/proxy_test_scenario_go_test.rs b/contracts/examples/token-identifier-test/proxy-test/tests/proxy_test_scenario_go_test.rs new file mode 100644 index 0000000000..f1e4a9e41c --- /dev/null +++ b/contracts/examples/token-identifier-test/proxy-test/tests/proxy_test_scenario_go_test.rs @@ -0,0 +1,15 @@ +use multiversx_sc_scenario::*; + +fn world() -> ScenarioWorld { + ScenarioWorld::vm_go() +} + +#[test] +fn adder_go() { + world().run("scenarios/proxy_test.scen.json"); +} + +#[test] +fn interactor_trace_go() { + world().run("scenarios/interactor_trace.scen.json"); +} diff --git a/contracts/examples/token-identifier-test/proxy-test/tests/proxy_test_scenario_rs_test.rs b/contracts/examples/token-identifier-test/proxy-test/tests/proxy_test_scenario_rs_test.rs new file mode 100644 index 0000000000..1c59ef7298 --- /dev/null +++ b/contracts/examples/token-identifier-test/proxy-test/tests/proxy_test_scenario_rs_test.rs @@ -0,0 +1,18 @@ +use multiversx_sc_scenario::*; + +fn world() -> ScenarioWorld { + let mut blockchain = ScenarioWorld::new(); + + blockchain.register_contract("mxsc:output/proxy-test.mxsc.json", proxy_test::ContractBuilder); + blockchain +} + +#[test] +fn adder_rs() { + world().run("scenarios/proxy_test.scen.json"); +} + +#[test] +fn interactor_trace_rs() { + world().run("scenarios/interactor_trace.scen.json"); +} diff --git a/contracts/examples/token-identifier-test/proxy-test/tests/proxy_test_unit_test.rs b/contracts/examples/token-identifier-test/proxy-test/tests/proxy_test_unit_test.rs new file mode 100644 index 0000000000..2f25237975 --- /dev/null +++ b/contracts/examples/token-identifier-test/proxy-test/tests/proxy_test_unit_test.rs @@ -0,0 +1,17 @@ +use proxy_test::*; +use multiversx_sc::types::BigUint; +use multiversx_sc_scenario::api::SingleTxApi; + +#[test] +fn adder_unit_test() { + let adder = proxy_test::contract_obj::(); + + adder.init(BigUint::from(5u32)); + assert_eq!(BigUint::from(5u32), adder.sum().get()); + + adder.add(BigUint::from(7u32)); + assert_eq!(BigUint::from(12u32), adder.sum().get()); + + adder.add(BigUint::from(1u32)); + assert_eq!(BigUint::from(13u32), adder.sum().get()); +} diff --git a/contracts/examples/token-identifier-test/proxy-test/tests/proxy_test_whitebox_test.rs b/contracts/examples/token-identifier-test/proxy-test/tests/proxy_test_whitebox_test.rs new file mode 100644 index 0000000000..5d393b6649 --- /dev/null +++ b/contracts/examples/token-identifier-test/proxy-test/tests/proxy_test_whitebox_test.rs @@ -0,0 +1,49 @@ +use proxy_test::*; +use multiversx_sc_scenario::imports::*; + +const ADDER_PATH_EXPR: &str = "mxsc:output/proxy-test.mxsc.json"; + +fn world() -> ScenarioWorld { + let mut blockchain = ScenarioWorld::new(); + + blockchain.register_contract("mxsc:output/proxy-test.mxsc.json", proxy_test::ContractBuilder); + blockchain +} + +#[test] +fn adder_whitebox() { + let mut world = world(); + let adder_whitebox = WhiteboxContract::new("sc:adder", proxy_test::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"), + ), + ); +} diff --git a/contracts/examples/token-identifier-test/proxy-test/wasm/Cargo.lock b/contracts/examples/token-identifier-test/proxy-test/wasm/Cargo.lock new file mode 100644 index 0000000000..5a2adbeecf --- /dev/null +++ b/contracts/examples/token-identifier-test/proxy-test/wasm/Cargo.lock @@ -0,0 +1,178 @@ +# 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 = "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-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 = "proxy-test" +version = "0.0.0" +dependencies = [ + "multiversx-sc", +] + +[[package]] +name = "proxy-test-wasm" +version = "0.0.0" +dependencies = [ + "multiversx-sc-wasm-adapter", + "proxy-test", +] + +[[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/examples/token-identifier-test/proxy-test/wasm/Cargo.toml b/contracts/examples/token-identifier-test/proxy-test/wasm/Cargo.toml new file mode 100644 index 0000000000..a33bce40cb --- /dev/null +++ b/contracts/examples/token-identifier-test/proxy-test/wasm/Cargo.toml @@ -0,0 +1,35 @@ +# Code generated by the multiversx-sc build system. DO NOT EDIT. + +# ########################################## +# ############## AUTO-GENERATED ############# +# ########################################## + +[package] +name = "proxy-test-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.proxy-test] +path = ".." + +[dependencies.multiversx-sc-wasm-adapter] +version = "0.52.3" +path = "../../../../../framework/wasm-adapter" + +[workspace] +members = ["."] diff --git a/contracts/examples/token-identifier-test/proxy-test/wasm/src/lib.rs b/contracts/examples/token-identifier-test/proxy-test/wasm/src/lib.rs new file mode 100644 index 0000000000..4cf6d22762 --- /dev/null +++ b/contracts/examples/token-identifier-test/proxy-test/wasm/src/lib.rs @@ -0,0 +1,32 @@ +// Code generated by the multiversx-sc build system. DO NOT EDIT. + +//////////////////////////////////////////////////// +////////////////// AUTO-GENERATED ////////////////// +//////////////////////////////////////////////////// + +// Init: 1 +// Upgrade: 1 +// Endpoints: 6 +// Async Callback: 1 +// Total number of exported functions: 9 + +#![no_std] + +multiversx_sc_wasm_adapter::allocator!(); +multiversx_sc_wasm_adapter::panic_handler!(); + +multiversx_sc_wasm_adapter::endpoints! { + proxy_test + ( + init => init + upgrade => upgrade + lastIssuedToken => last_issued_token + lastErrorMessage => last_error_message + getSum => sum + add => add + issue_fungible_token => issue_fungible_token + send_egld => send_egld + ) +} + +multiversx_sc_wasm_adapter::async_callback! { proxy_test } diff --git a/contracts/examples/token-identifier-test/returns-token-identifier-test/Cargo.toml b/contracts/examples/token-identifier-test/returns-token-identifier-test/Cargo.toml new file mode 100644 index 0000000000..81b16b9ebb --- /dev/null +++ b/contracts/examples/token-identifier-test/returns-token-identifier-test/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "returns-token-identifier-test" +version = "0.0.0" +publish = false +edition = "2021" +authors = ["you"] + +[lib] +path = "src/returns_token_identifier_test.rs" + +[dependencies.multiversx-sc] +version = "0.52.3" +path = "../../../../framework/base" + +[dev-dependencies.multiversx-sc-scenario] +version = "0.52.3" +path = "../../../../framework/scenario" diff --git a/contracts/examples/token-identifier-test/returns-token-identifier-test/README.md b/contracts/examples/token-identifier-test/returns-token-identifier-test/README.md new file mode 100644 index 0000000000..4538caeca9 --- /dev/null +++ b/contracts/examples/token-identifier-test/returns-token-identifier-test/README.md @@ -0,0 +1,3 @@ +# Adder + +`Adder` is a simple Smart Contract. diff --git a/contracts/examples/token-identifier-test/returns-token-identifier-test/interact/.gitignore b/contracts/examples/token-identifier-test/returns-token-identifier-test/interact/.gitignore new file mode 100644 index 0000000000..b2630809de --- /dev/null +++ b/contracts/examples/token-identifier-test/returns-token-identifier-test/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/contracts/examples/token-identifier-test/returns-token-identifier-test/interact/Cargo.toml b/contracts/examples/token-identifier-test/returns-token-identifier-test/interact/Cargo.toml new file mode 100644 index 0000000000..11929c55d6 --- /dev/null +++ b/contracts/examples/token-identifier-test/returns-token-identifier-test/interact/Cargo.toml @@ -0,0 +1,28 @@ +[[bin]] +name = "basic-interact-token" +path = "src/basic_interact.rs" + +[package] +name = "basic-interact-token" +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.returns-token-identifier-test] +path = ".." + +[dependencies.multiversx-sc-snippets] +version = "0.52.3" +path = "../../../../../framework/snippets" \ No newline at end of file diff --git a/contracts/examples/token-identifier-test/returns-token-identifier-test/interact/config.toml b/contracts/examples/token-identifier-test/returns-token-identifier-test/interact/config.toml new file mode 100644 index 0000000000..61ac8dbf87 --- /dev/null +++ b/contracts/examples/token-identifier-test/returns-token-identifier-test/interact/config.toml @@ -0,0 +1 @@ +gateway = 'https://devnet-gateway.multiversx.com' diff --git a/contracts/examples/token-identifier-test/returns-token-identifier-test/interact/src/basic_interact.rs b/contracts/examples/token-identifier-test/returns-token-identifier-test/interact/src/basic_interact.rs new file mode 100644 index 0000000000..844c9029b0 --- /dev/null +++ b/contracts/examples/token-identifier-test/returns-token-identifier-test/interact/src/basic_interact.rs @@ -0,0 +1,245 @@ +mod basic_interact_cli; +mod basic_interact_config; +mod basic_interact_state; + +use returns_token_identifier_test::returns_token_identifier_test_proxy; +use basic_interact_config::Config; +use basic_interact_state::State; +use clap::Parser; + +use multiversx_sc_snippets::imports::*; + +const INTERACTOR_SCENARIO_TRACE_PATH: &str = "interactor_trace.scen.json"; + +const ADDER_CODE_PATH: MxscPath = MxscPath::new("../output/returns-token-identifier-test.mxsc.json"); + +#[tokio::main] +async fn main() { + env_logger::init(); + + let mut basic_interact = ReturnsTokenIdentifierTestInteract::init().await; + + let cli = basic_interact_cli::InteractCli::parse(); + match &cli.command { + Some(basic_interact_cli::InteractCliCommand::Add(args)) => { + if args.count == 1 { + basic_interact.add(args.value).await; + } else { + basic_interact.multi_add(args.value, args.count).await; + } + }, + Some(basic_interact_cli::InteractCliCommand::Deploy) => { + basic_interact.deploy().await; + }, + Some(basic_interact_cli::InteractCliCommand::Feed) => { + basic_interact.feed_contract_egld().await; + }, + Some(basic_interact_cli::InteractCliCommand::MultiDeploy(args)) => { + basic_interact.multi_deploy(args.count).await; + }, + Some(basic_interact_cli::InteractCliCommand::Sum) => { + basic_interact.print_sum().await; + }, + Some(basic_interact_cli::InteractCliCommand::Upgrade(args)) => { + basic_interact.upgrade(args.value).await + }, + None => {}, + } +} + +#[allow(unused)] +struct ReturnsTokenIdentifierTestInteract { + interactor: Interactor, + adder_owner_address: Bech32Address, + wallet_address: Bech32Address, + state: State, +} + +impl ReturnsTokenIdentifierTestInteract { + async fn init() -> Self { + let config = Config::load_config(); + let mut interactor = Interactor::new(config.gateway()) + .await + .with_tracer(INTERACTOR_SCENARIO_TRACE_PATH) + .await; + + let adder_owner_address = + interactor.register_wallet(Wallet::from_pem_file("adder-owner.pem").unwrap()); + let wallet_address = interactor.register_wallet(test_wallets::mike()); + + 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); + self.interactor + .retrieve_account(&self.adder_owner_address) + .await; + self.interactor.retrieve_account(&self.wallet_address).await; + } + + async fn deploy(&mut self) { + // warning: multi deploy not yet fully supported + // only works with last deployed address + + self.set_state().await; + + let new_address = self + .interactor + .tx() + .from(&self.adder_owner_address) + .gas(3_000_000) + .typed(returns_token_identifier_test_proxy::ReturnsTokenIdentifierTestProxy) + .init(0u32) + .code(ADDER_CODE_PATH) + .code_metadata(CodeMetadata::UPGRADEABLE) + .returns(ReturnsNewBech32Address) + .prepare_async() + .run() + .await; + + println!("new address: {new_address}"); + self.state.set_adder_address(new_address); + } + + async fn multi_deploy(&mut self, count: usize) { + if count == 0 { + println!("count must be greater than 0"); + return; + } + + self.set_state().await; + println!("deploying {count} contracts..."); + + let mut buffer = self.interactor.homogenous_call_buffer(); + for _ in 0..count { + buffer.push_tx(|tx| { + tx.from(&self.wallet_address) + .typed(returns_token_identifier_test_proxy::ReturnsTokenIdentifierTestProxy) + .init(0u32) + .code(ADDER_CODE_PATH) + .gas(3_000_000) + .returns(ReturnsNewBech32Address) + }); + } + + let results = buffer.run().await; + + // warning: multi deploy not yet fully supported + // only works with last deployed address + + for new_address in results { + println!("new address: {new_address}"); + + self.state.set_adder_address(new_address); + } + } + + async fn multi_add(&mut self, value: u32, count: usize) { + self.set_state().await; + println!("calling contract {count} times..."); + + let mut buffer = self.interactor.homogenous_call_buffer(); + for _ in 0..count { + buffer.push_tx(|tx| { + tx.from(&self.wallet_address) + .to(self.state.current_adder_address()) + .typed(returns_token_identifier_test_proxy::ReturnsTokenIdentifierTestProxy) + .add(value) + .gas(3_000_000) + }); + } + + let _ = buffer.run().await; + + println!("successfully performed add {count} times"); + } + + async fn feed_contract_egld(&mut self) { + self.interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_adder_address()) + .egld(NumExpr("0,050000000000000000")) + .prepare_async() + .run() + .await; + } + + async fn add(&mut self, value: u32) { + self.interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_adder_address()) + .gas(3_000_000) + .typed(returns_token_identifier_test_proxy::ReturnsTokenIdentifierTestProxy) + .add(value) + .prepare_async() + .run() + .await; + + println!("successfully performed add"); + } + + async fn print_sum(&mut self) { + let sum = self + .interactor + .query() + .to(self.state.current_adder_address()) + .typed(returns_token_identifier_test_proxy::ReturnsTokenIdentifierTestProxy) + .sum() + .returns(ReturnsResultUnmanaged) + .prepare_async() + .run() + .await; + + println!("sum: {sum}"); + } + + async fn upgrade(&mut self, new_value: u32) { + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_adder_address()) + .gas(3_000_000) + .typed(returns_token_identifier_test_proxy::ReturnsTokenIdentifierTestProxy) + .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(returns_token_identifier_test_proxy::ReturnsTokenIdentifierTestProxy) + .sum() + .returns(ReturnsResultUnmanaged) + .prepare_async() + .run() + .await; + assert_eq!(sum, RustBigUint::from(new_value)); + + println!("response: {response:?}"); + } +} + +#[tokio::test] +#[ignore = "run on demand"] +async fn test() { + let mut basic_interact = ReturnsTokenIdentifierTestInteract::init().await; + + basic_interact.deploy().await; + basic_interact.add(1u32).await; + + basic_interact.upgrade(7u32).await; +} diff --git a/contracts/examples/token-identifier-test/returns-token-identifier-test/interact/src/basic_interact_cli.rs b/contracts/examples/token-identifier-test/returns-token-identifier-test/interact/src/basic_interact_cli.rs new file mode 100644 index 0000000000..d59c4d8d02 --- /dev/null +++ b/contracts/examples/token-identifier-test/returns-token-identifier-test/interact/src/basic_interact_cli.rs @@ -0,0 +1,52 @@ +use clap::{Args, Parser, Subcommand}; + +/// ReturnsTokenIdentifierTest Interact CLI +#[derive(Default, PartialEq, Eq, Debug, Parser)] +#[command(version, about)] +#[command(propagate_version = true)] +pub struct InteractCli { + #[command(subcommand)] + pub command: Option, +} + +/// ReturnsTokenIdentifierTest 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/token-identifier-test/returns-token-identifier-test/interact/src/basic_interact_config.rs b/contracts/examples/token-identifier-test/returns-token-identifier-test/interact/src/basic_interact_config.rs new file mode 100644 index 0000000000..9a91d4f2a8 --- /dev/null +++ b/contracts/examples/token-identifier-test/returns-token-identifier-test/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"; + +/// ReturnsTokenIdentifierTest 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/token-identifier-test/returns-token-identifier-test/interact/src/basic_interact_state.rs b/contracts/examples/token-identifier-test/returns-token-identifier-test/interact/src/basic_interact_state.rs new file mode 100644 index 0000000000..41453e36fd --- /dev/null +++ b/contracts/examples/token-identifier-test/returns-token-identifier-test/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(); + } +} diff --git a/contracts/examples/token-identifier-test/returns-token-identifier-test/meta/Cargo.toml b/contracts/examples/token-identifier-test/returns-token-identifier-test/meta/Cargo.toml new file mode 100644 index 0000000000..ac97843b5c --- /dev/null +++ b/contracts/examples/token-identifier-test/returns-token-identifier-test/meta/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "returns-token-identifier-test-meta" +version = "0.0.0" +edition = "2021" +publish = false + +[dependencies.returns-token-identifier-test] +path = ".." + +[dependencies.multiversx-sc-meta-lib] +version = "0.52.3" +path = "../../../../../framework/meta-lib" +default-features = false + diff --git a/contracts/examples/token-identifier-test/returns-token-identifier-test/meta/src/main.rs b/contracts/examples/token-identifier-test/returns-token-identifier-test/meta/src/main.rs new file mode 100644 index 0000000000..07b585af5e --- /dev/null +++ b/contracts/examples/token-identifier-test/returns-token-identifier-test/meta/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + multiversx_sc_meta_lib::cli_main::(); +} diff --git a/contracts/examples/token-identifier-test/returns-token-identifier-test/multiversx.json b/contracts/examples/token-identifier-test/returns-token-identifier-test/multiversx.json new file mode 100644 index 0000000000..7365539625 --- /dev/null +++ b/contracts/examples/token-identifier-test/returns-token-identifier-test/multiversx.json @@ -0,0 +1,3 @@ +{ + "language": "rust" +} \ No newline at end of file diff --git a/contracts/examples/token-identifier-test/returns-token-identifier-test/sc-config.toml b/contracts/examples/token-identifier-test/returns-token-identifier-test/sc-config.toml new file mode 100644 index 0000000000..3c5d273fb0 --- /dev/null +++ b/contracts/examples/token-identifier-test/returns-token-identifier-test/sc-config.toml @@ -0,0 +1,4 @@ +[settings] + +[[proxy]] +path = "src/returns_token_identifier_test_proxy.rs" diff --git a/contracts/examples/token-identifier-test/returns-token-identifier-test/scenarios/interactor_trace.scen.json b/contracts/examples/token-identifier-test/returns-token-identifier-test/scenarios/interactor_trace.scen.json new file mode 100644 index 0000000000..76d44644d5 --- /dev/null +++ b/contracts/examples/token-identifier-test/returns-token-identifier-test/scenarios/interactor_trace.scen.json @@ -0,0 +1,76 @@ +{ + "steps": [ + { + "step": "setState", + "accounts": { + "0xe32afedc904fe1939746ad973beb383563cf63642ba669b3040f9b9428a5ed60": { + "nonce": "481", + "balance": "106274669842530000003", + "esdt": { + "str:CAN-14dc0a": "1000", + "str:CAN-2abf4b": "1000", + "str:CAN-6d39e6": "1000", + "str:CAN-ac1592": "1000" + } + } + } + }, + { + "step": "setState", + "newAddresses": [ + { + "creatorAddress": "0xe32afedc904fe1939746ad973beb383563cf63642ba669b3040f9b9428a5ed60", + "creatorNonce": "481", + "newAddress": "0x0000000000000000050028600ceb73ac22ec0b6f257aff7bed74dffa3ebfed60" + } + ] + }, + { + "step": "scDeploy", + "tx": { + "from": "0xe32afedc904fe1939746ad973beb383563cf63642ba669b3040f9b9428a5ed60", + "contractCode": "mxsc:../output/returns-token-identifier-test.mxsc.json", + "arguments": [ + "0x00" + ], + "gasLimit": "70,000,000" + }, + "expect": { + "out": [], + "status": "0" + } + }, + { + "step": "scCall", + "tx": { + "from": "0xe32afedc904fe1939746ad973beb383563cf63642ba669b3040f9b9428a5ed60", + "to": "0x0000000000000000050028600ceb73ac22ec0b6f257aff7bed74dffa3ebfed60", + "function": "add", + "arguments": [ + "0x07" + ], + "gasLimit": "70,000,000" + }, + "expect": { + "out": [], + "status": "0" + } + }, + { + "step": "scCall", + "tx": { + "from": "0xe32afedc904fe1939746ad973beb383563cf63642ba669b3040f9b9428a5ed60", + "to": "0x0000000000000000050028600ceb73ac22ec0b6f257aff7bed74dffa3ebfed60", + "function": "add", + "arguments": [ + "0x05" + ], + "gasLimit": "70,000,000" + }, + "expect": { + "out": [], + "status": "0" + } + } + ] +} diff --git a/contracts/examples/token-identifier-test/returns-token-identifier-test/scenarios/returns_token_identifier_test.scen.json b/contracts/examples/token-identifier-test/returns-token-identifier-test/scenarios/returns_token_identifier_test.scen.json new file mode 100644 index 0000000000..da932ddda2 --- /dev/null +++ b/contracts/examples/token-identifier-test/returns-token-identifier-test/scenarios/returns_token_identifier_test.scen.json @@ -0,0 +1,99 @@ +{ + "name": "adder", + "comment": "add then check", + "gasSchedule": "v3", + "steps": [ + { + "step": "setState", + "accounts": { + "address:owner": { + "nonce": "1", + "balance": "0" + } + }, + "newAddresses": [ + { + "creatorAddress": "address:owner", + "creatorNonce": "1", + "newAddress": "sc:adder" + } + ] + }, + { + "step": "scDeploy", + "id": "1", + "tx": { + "from": "address:owner", + "contractCode": "mxsc:../output/returns-token-identifier-test.mxsc.json", + "arguments": [ + "5" + ], + "gasLimit": "5,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [], + "status": "", + "logs": "*", + "gas": "*", + "refund": "*" + } + }, + { + "step": "scQuery", + "id": "2", + "tx": { + "to": "sc:adder", + "function": "getSum", + "arguments": [] + }, + "expect": { + "out": [ + "5" + ], + "status": "", + "logs": [] + } + }, + { + "step": "scCall", + "id": "3", + "tx": { + "from": "address:owner", + "to": "sc:adder", + "function": "add", + "arguments": [ + "3" + ], + "gasLimit": "5,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [], + "status": "", + "logs": "*", + "gas": "*", + "refund": "*" + } + }, + { + "step": "checkState", + "accounts": { + "address:owner": { + "nonce": "*", + "balance": "0", + "storage": {}, + "code": "" + }, + "sc:adder": { + "nonce": "0", + "balance": "0", + "storage": { + "str:sum": "8" + }, + "code": "mxsc:../output/returns-token-identifier-test.mxsc.json" + } + } + } + ] +} diff --git a/contracts/examples/token-identifier-test/returns-token-identifier-test/src/returns_token_identifier_test.rs b/contracts/examples/token-identifier-test/returns-token-identifier-test/src/returns_token_identifier_test.rs new file mode 100644 index 0000000000..36b16396e0 --- /dev/null +++ b/contracts/examples/token-identifier-test/returns-token-identifier-test/src/returns_token_identifier_test.rs @@ -0,0 +1,31 @@ +#![no_std] + +use multiversx_sc::imports::*; + +pub mod returns_token_identifier_test_proxy; + +/// One of the simplest smart contracts possible, +/// it holds a single variable in storage, which anyone can increment. +#[multiversx_sc::contract] +pub trait ReturnsTokenIdentifierTest { + #[view(getSum)] + #[storage_mapper("sum")] + fn sum(&self) -> SingleValueMapper; + + #[init] + fn init(&self, initial_value: BigUint) { + self.sum().set(initial_value); + } + + #[upgrade] + fn upgrade(&self, initial_value: BigUint) { + self.init(initial_value); + } + + /// Add desired amount to the storage variable. + #[endpoint] + fn add(&self, value: BigUint) { + self.sum().update(|sum| *sum += value); + } + // TODO!: Call the proxy-test issue function!! +} diff --git a/contracts/examples/token-identifier-test/returns-token-identifier-test/src/returns_token_identifier_test_proxy.rs b/contracts/examples/token-identifier-test/returns-token-identifier-test/src/returns_token_identifier_test_proxy.rs new file mode 100644 index 0000000000..1129b35b96 --- /dev/null +++ b/contracts/examples/token-identifier-test/returns-token-identifier-test/src/returns_token_identifier_test_proxy.rs @@ -0,0 +1,114 @@ +// 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 ReturnsTokenIdentifierTestProxy; + +impl TxProxyTrait for ReturnsTokenIdentifierTestProxy +where + Env: TxEnv, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + type TxProxyMethods = ReturnsTokenIdentifierTestProxyMethods; + + fn proxy_methods(self, tx: Tx) -> Self::TxProxyMethods { + ReturnsTokenIdentifierTestProxyMethods { wrapped_tx: tx } + } +} + +pub struct ReturnsTokenIdentifierTestProxyMethods +where + Env: TxEnv, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + wrapped_tx: Tx, +} + +#[rustfmt::skip] +impl ReturnsTokenIdentifierTestProxyMethods +where + Env: TxEnv, + Env::Api: VMApi, + From: TxFrom, + Gas: TxGas, +{ + pub fn init< + Arg0: ProxyArg>, + >( + self, + initial_value: Arg0, + ) -> TxTypedDeploy { + self.wrapped_tx + .payment(NotPayable) + .raw_deploy() + .argument(&initial_value) + .original_result() + } +} + +#[rustfmt::skip] +impl ReturnsTokenIdentifierTestProxyMethods +where + Env: TxEnv, + Env::Api: VMApi, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + pub fn upgrade< + Arg0: ProxyArg>, + >( + self, + initial_value: Arg0, + ) -> TxTypedUpgrade { + self.wrapped_tx + .payment(NotPayable) + .raw_upgrade() + .argument(&initial_value) + .original_result() + } +} + +#[rustfmt::skip] +impl ReturnsTokenIdentifierTestProxyMethods +where + Env: TxEnv, + Env::Api: VMApi, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + pub fn sum( + self, + ) -> TxTypedCall> { + self.wrapped_tx + .payment(NotPayable) + .raw_call("getSum") + .original_result() + } + + /// Add desired amount to the storage variable. + pub fn add< + Arg0: ProxyArg>, + >( + self, + value: Arg0, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("add") + .argument(&value) + .original_result() + } +} diff --git a/contracts/examples/token-identifier-test/returns-token-identifier-test/tests/returns_token_identifier_test_blackbox_test.rs b/contracts/examples/token-identifier-test/returns-token-identifier-test/tests/returns_token_identifier_test_blackbox_test.rs new file mode 100644 index 0000000000..ce1d7f26a1 --- /dev/null +++ b/contracts/examples/token-identifier-test/returns-token-identifier-test/tests/returns_token_identifier_test_blackbox_test.rs @@ -0,0 +1,80 @@ +use multiversx_sc_scenario::imports::*; + +use returns_token_identifier_test::*; + +const OWNER_ADDRESS: TestAddress = TestAddress::new("owner"); +const ADDER_ADDRESS: TestSCAddress = TestSCAddress::new("adder"); +const CODE_PATH: MxscPath = MxscPath::new("output/returns-token-identifier-test.mxsc.json"); + +fn world() -> ScenarioWorld { + let mut blockchain = ScenarioWorld::new(); + + blockchain.register_contract(CODE_PATH, returns_token_identifier_test::ContractBuilder); + blockchain +} + +#[test] +fn adder_blackbox() { + let mut world = world(); + + world.start_trace(); + + world.account(OWNER_ADDRESS).nonce(1); + + let new_address = world + .tx() + .from(OWNER_ADDRESS) + .typed(returns_token_identifier_test_proxy::ReturnsTokenIdentifierTestProxy) + .init(5u32) + .code(CODE_PATH) + .new_address(ADDER_ADDRESS) + .returns(ReturnsNewAddress) + .run(); + + assert_eq!(new_address, ADDER_ADDRESS.to_address()); + + world + .query() + .to(ADDER_ADDRESS) + .typed(returns_token_identifier_test_proxy::ReturnsTokenIdentifierTestProxy) + .sum() + .returns(ExpectValue(5u32)) + .run(); + + world + .tx() + .from(OWNER_ADDRESS) + .to(ADDER_ADDRESS) + .typed(returns_token_identifier_test_proxy::ReturnsTokenIdentifierTestProxy) + .add(1u32) + .run(); + + world + .query() + .to(ADDER_ADDRESS) + .typed(returns_token_identifier_test_proxy::ReturnsTokenIdentifierTestProxy) + .sum() + .returns(ExpectValue(6u32)) + .run(); + + world.check_account(OWNER_ADDRESS); + + world + .check_account(ADDER_ADDRESS) + .check_storage("str:sum", "6"); + + world + .tx() + .from(OWNER_ADDRESS) + .to(ADDER_ADDRESS) + .typed(returns_token_identifier_test_proxy::ReturnsTokenIdentifierTestProxy) + .upgrade(100u64) + .code(CODE_PATH) + .run(); + + world + .check_account(ADDER_ADDRESS) + .check_storage("str:sum", "100"); + + world.write_scenario_trace("trace1.scen.json"); +} diff --git a/contracts/examples/token-identifier-test/returns-token-identifier-test/tests/returns_token_identifier_test_scenario_go_test.rs b/contracts/examples/token-identifier-test/returns-token-identifier-test/tests/returns_token_identifier_test_scenario_go_test.rs new file mode 100644 index 0000000000..ba5272d67a --- /dev/null +++ b/contracts/examples/token-identifier-test/returns-token-identifier-test/tests/returns_token_identifier_test_scenario_go_test.rs @@ -0,0 +1,15 @@ +use multiversx_sc_scenario::*; + +fn world() -> ScenarioWorld { + ScenarioWorld::vm_go() +} + +#[test] +fn adder_go() { + world().run("scenarios/returns_token_identifier_test.scen.json"); +} + +#[test] +fn interactor_trace_go() { + world().run("scenarios/interactor_trace.scen.json"); +} diff --git a/contracts/examples/token-identifier-test/returns-token-identifier-test/tests/returns_token_identifier_test_scenario_rs_test.rs b/contracts/examples/token-identifier-test/returns-token-identifier-test/tests/returns_token_identifier_test_scenario_rs_test.rs new file mode 100644 index 0000000000..5c511667e0 --- /dev/null +++ b/contracts/examples/token-identifier-test/returns-token-identifier-test/tests/returns_token_identifier_test_scenario_rs_test.rs @@ -0,0 +1,18 @@ +use multiversx_sc_scenario::*; + +fn world() -> ScenarioWorld { + let mut blockchain = ScenarioWorld::new(); + + blockchain.register_contract("mxsc:output/returns-token-identifier-test.mxsc.json", returns_token_identifier_test::ContractBuilder); + blockchain +} + +#[test] +fn adder_rs() { + world().run("scenarios/returns_token_identifier_test.scen.json"); +} + +#[test] +fn interactor_trace_rs() { + world().run("scenarios/interactor_trace.scen.json"); +} diff --git a/contracts/examples/token-identifier-test/returns-token-identifier-test/tests/returns_token_identifier_test_unit_test.rs b/contracts/examples/token-identifier-test/returns-token-identifier-test/tests/returns_token_identifier_test_unit_test.rs new file mode 100644 index 0000000000..a7d3b98e11 --- /dev/null +++ b/contracts/examples/token-identifier-test/returns-token-identifier-test/tests/returns_token_identifier_test_unit_test.rs @@ -0,0 +1,17 @@ +use returns_token_identifier_test::*; +use multiversx_sc::types::BigUint; +use multiversx_sc_scenario::api::SingleTxApi; + +#[test] +fn adder_unit_test() { + let adder = returns_token_identifier_test::contract_obj::(); + + adder.init(BigUint::from(5u32)); + assert_eq!(BigUint::from(5u32), adder.sum().get()); + + adder.add(BigUint::from(7u32)); + assert_eq!(BigUint::from(12u32), adder.sum().get()); + + adder.add(BigUint::from(1u32)); + assert_eq!(BigUint::from(13u32), adder.sum().get()); +} diff --git a/contracts/examples/token-identifier-test/returns-token-identifier-test/tests/returns_token_identifier_test_whitebox_test.rs b/contracts/examples/token-identifier-test/returns-token-identifier-test/tests/returns_token_identifier_test_whitebox_test.rs new file mode 100644 index 0000000000..0320b73dd3 --- /dev/null +++ b/contracts/examples/token-identifier-test/returns-token-identifier-test/tests/returns_token_identifier_test_whitebox_test.rs @@ -0,0 +1,49 @@ +use returns_token_identifier_test::*; +use multiversx_sc_scenario::imports::*; + +const ADDER_PATH_EXPR: &str = "mxsc:output/returns-token-identifier-test.mxsc.json"; + +fn world() -> ScenarioWorld { + let mut blockchain = ScenarioWorld::new(); + + blockchain.register_contract("mxsc:output/returns-token-identifier-test.mxsc.json", returns_token_identifier_test::ContractBuilder); + blockchain +} + +#[test] +fn adder_whitebox() { + let mut world = world(); + let adder_whitebox = WhiteboxContract::new("sc:adder", returns_token_identifier_test::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"), + ), + ); +} From 88a84e3c2b9e3d8f993bd500aea069f480453add Mon Sep 17 00:00:00 2001 From: JustEatAnApple Date: Thu, 29 Aug 2024 11:10:18 +0300 Subject: [PATCH 3/3] [WIP] Testing chaining SC for issue Co-authored-by: Andrei Vasilescu --- .../proxy-test/interact/src/basic_interact.rs | 8 +- .../proxy-test/sc-config.toml | 2 +- .../interact/src/basic_interact.rs | 43 ++++- .../interact/src/basic_interact_cli.rs | 2 + .../sc-config.toml | 4 + .../src/proxy_proxy_test.rs | 166 ++++++++++++++++ .../src/returns_token_identifier_test.rs | 54 +++++- .../returns_token_identifier_test_proxy.rs | 39 ++++ .../wasm/Cargo.lock | 178 ++++++++++++++++++ .../wasm/Cargo.toml | 35 ++++ .../wasm/src/lib.rs | 31 +++ 11 files changed, 549 insertions(+), 13 deletions(-) create mode 100644 contracts/examples/token-identifier-test/returns-token-identifier-test/src/proxy_proxy_test.rs create mode 100644 contracts/examples/token-identifier-test/returns-token-identifier-test/wasm/Cargo.lock create mode 100644 contracts/examples/token-identifier-test/returns-token-identifier-test/wasm/Cargo.toml create mode 100644 contracts/examples/token-identifier-test/returns-token-identifier-test/wasm/src/lib.rs diff --git a/contracts/examples/token-identifier-test/proxy-test/interact/src/basic_interact.rs b/contracts/examples/token-identifier-test/proxy-test/interact/src/basic_interact.rs index bfec3c5130..546c8eb419 100644 --- a/contracts/examples/token-identifier-test/proxy-test/interact/src/basic_interact.rs +++ b/contracts/examples/token-identifier-test/proxy-test/interact/src/basic_interact.rs @@ -69,8 +69,8 @@ impl ProxyTestInteract { .with_tracer(INTERACTOR_SCENARIO_TRACE_PATH) .await; - let adder_owner_address = interactor.register_wallet(test_wallets::mike()); - let wallet_address = interactor.register_wallet(test_wallets::mike()); + let adder_owner_address = interactor.register_wallet(test_wallets::alice()); + let wallet_address = interactor.register_wallet(test_wallets::alice()); Self { interactor, @@ -283,12 +283,12 @@ impl ProxyTestInteract { .typed(proxy_test_proxy::ProxyTestProxy) .issue_fungible_token(token_display_name, token_ticker, initial_supply) .egld(egld_amount) - .returns(ReturnsNewTokenIdentifier) + .returns(ReturnsResultUnmanaged) .prepare_async() .run() .await; - println!("Result: {response:?}"); + println!("Papacioc: {response:?}"); // asta e gol } async fn send_egld(&mut self) { diff --git a/contracts/examples/token-identifier-test/proxy-test/sc-config.toml b/contracts/examples/token-identifier-test/proxy-test/sc-config.toml index e4693e8ab1..8ae535d0f6 100644 --- a/contracts/examples/token-identifier-test/proxy-test/sc-config.toml +++ b/contracts/examples/token-identifier-test/proxy-test/sc-config.toml @@ -4,5 +4,5 @@ path = "src/proxy_test_proxy.rs" [[proxy]] -path = "interactor/src/proxy.rs" +path = "../returns-token-identifier-test/src/proxy_proxy_test.rs" diff --git a/contracts/examples/token-identifier-test/returns-token-identifier-test/interact/src/basic_interact.rs b/contracts/examples/token-identifier-test/returns-token-identifier-test/interact/src/basic_interact.rs index 844c9029b0..28861dcef1 100644 --- a/contracts/examples/token-identifier-test/returns-token-identifier-test/interact/src/basic_interact.rs +++ b/contracts/examples/token-identifier-test/returns-token-identifier-test/interact/src/basic_interact.rs @@ -43,6 +43,9 @@ async fn main() { Some(basic_interact_cli::InteractCliCommand::Upgrade(args)) => { basic_interact.upgrade(args.value).await }, + Some(basic_interact_cli::InteractCliCommand::ContractCall) => { + basic_interact.call_contract().await; + }, None => {}, } } @@ -64,8 +67,8 @@ impl ReturnsTokenIdentifierTestInteract { .await; 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(test_wallets::alice()); + let wallet_address = interactor.register_wallet(test_wallets::alice()); Self { interactor, @@ -93,7 +96,7 @@ impl ReturnsTokenIdentifierTestInteract { .interactor .tx() .from(&self.adder_owner_address) - .gas(3_000_000) + .gas(30_000_000) .typed(returns_token_identifier_test_proxy::ReturnsTokenIdentifierTestProxy) .init(0u32) .code(ADDER_CODE_PATH) @@ -123,7 +126,7 @@ impl ReturnsTokenIdentifierTestInteract { .typed(returns_token_identifier_test_proxy::ReturnsTokenIdentifierTestProxy) .init(0u32) .code(ADDER_CODE_PATH) - .gas(3_000_000) + .gas(30_000_000) .returns(ReturnsNewBech32Address) }); } @@ -151,7 +154,7 @@ impl ReturnsTokenIdentifierTestInteract { .to(self.state.current_adder_address()) .typed(returns_token_identifier_test_proxy::ReturnsTokenIdentifierTestProxy) .add(value) - .gas(3_000_000) + .gas(30_000_000) }); } @@ -176,7 +179,7 @@ impl ReturnsTokenIdentifierTestInteract { .tx() .from(&self.wallet_address) .to(self.state.current_adder_address()) - .gas(3_000_000) + .gas(30_000_000) .typed(returns_token_identifier_test_proxy::ReturnsTokenIdentifierTestProxy) .add(value) .prepare_async() @@ -207,7 +210,7 @@ impl ReturnsTokenIdentifierTestInteract { .tx() .from(&self.wallet_address) .to(self.state.current_adder_address()) - .gas(3_000_000) + .gas(30_000_000) .typed(returns_token_identifier_test_proxy::ReturnsTokenIdentifierTestProxy) .upgrade(BigUint::from(new_value)) .code_metadata(CodeMetadata::UPGRADEABLE) @@ -231,6 +234,32 @@ impl ReturnsTokenIdentifierTestInteract { println!("response: {response:?}"); } + + async fn call_contract(&mut self) { + let egld_amount = BigUint::::from(50000000000000000u128); + + let contract_address = Bech32Address::from_bech32_string("erd1qqqqqqqqqqqqqpgqyu0yylry6dyvynsqsmswqzvyewes38j0a4sqevrx55".to_string()); + + let token_display_name = ManagedBuffer::from("PROXYTOKEN"); + let token_ticker = ManagedBuffer::from("PRXY"); + let initial_supply = BigUint::::from(100000000000000000000u128); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_adder_address()) + .gas(30_000_000u64) + .typed(returns_token_identifier_test_proxy::ReturnsTokenIdentifierTestProxy) + .call_contract(contract_address, token_display_name, token_ticker, initial_supply) + //.egld(egld_amount) + .returns(ReturnsResultUnmanaged) + .prepare_async() + .run() + .await; + + println!("Result: {response:?}"); + } } #[tokio::test] diff --git a/contracts/examples/token-identifier-test/returns-token-identifier-test/interact/src/basic_interact_cli.rs b/contracts/examples/token-identifier-test/returns-token-identifier-test/interact/src/basic_interact_cli.rs index d59c4d8d02..d011c9d77e 100644 --- a/contracts/examples/token-identifier-test/returns-token-identifier-test/interact/src/basic_interact_cli.rs +++ b/contracts/examples/token-identifier-test/returns-token-identifier-test/interact/src/basic_interact_cli.rs @@ -24,6 +24,8 @@ pub enum InteractCliCommand { Sum, #[command(name = "upgrade", about = "Upgrade contract")] Upgrade(UpgradeArgs), + #[command(name = "contract-call", about = "Call Proxy")] + ContractCall, } #[derive(Default, Clone, PartialEq, Eq, Debug, Args)] diff --git a/contracts/examples/token-identifier-test/returns-token-identifier-test/sc-config.toml b/contracts/examples/token-identifier-test/returns-token-identifier-test/sc-config.toml index 3c5d273fb0..e450675a24 100644 --- a/contracts/examples/token-identifier-test/returns-token-identifier-test/sc-config.toml +++ b/contracts/examples/token-identifier-test/returns-token-identifier-test/sc-config.toml @@ -2,3 +2,7 @@ [[proxy]] path = "src/returns_token_identifier_test_proxy.rs" + +[[proxy]] +path = "interactor/src/proxy.rs" + diff --git a/contracts/examples/token-identifier-test/returns-token-identifier-test/src/proxy_proxy_test.rs b/contracts/examples/token-identifier-test/returns-token-identifier-test/src/proxy_proxy_test.rs new file mode 100644 index 0000000000..934bd2b156 --- /dev/null +++ b/contracts/examples/token-identifier-test/returns-token-identifier-test/src/proxy_proxy_test.rs @@ -0,0 +1,166 @@ +// 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 ProxyTestProxy; + +impl TxProxyTrait for ProxyTestProxy +where + Env: TxEnv, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + type TxProxyMethods = ProxyTestProxyMethods; + + fn proxy_methods(self, tx: Tx) -> Self::TxProxyMethods { + ProxyTestProxyMethods { wrapped_tx: tx } + } +} + +pub struct ProxyTestProxyMethods +where + Env: TxEnv, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + wrapped_tx: Tx, +} + +#[rustfmt::skip] +impl ProxyTestProxyMethods +where + Env: TxEnv, + Env::Api: VMApi, + From: TxFrom, + Gas: TxGas, +{ + pub fn init< + Arg0: ProxyArg>, + >( + self, + initial_value: Arg0, + ) -> TxTypedDeploy { + self.wrapped_tx + .payment(NotPayable) + .raw_deploy() + .argument(&initial_value) + .original_result() + } +} + +#[rustfmt::skip] +impl ProxyTestProxyMethods +where + Env: TxEnv, + Env::Api: VMApi, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + pub fn upgrade< + Arg0: ProxyArg>, + >( + self, + initial_value: Arg0, + ) -> TxTypedUpgrade { + self.wrapped_tx + .payment(NotPayable) + .raw_upgrade() + .argument(&initial_value) + .original_result() + } +} + +#[rustfmt::skip] +impl ProxyTestProxyMethods +where + Env: TxEnv, + Env::Api: VMApi, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + pub fn last_issued_token( + self, + ) -> TxTypedCall> { + self.wrapped_tx + .payment(NotPayable) + .raw_call("lastIssuedToken") + .original_result() + } + + pub fn last_error_message( + self, + ) -> TxTypedCall> { + self.wrapped_tx + .payment(NotPayable) + .raw_call("lastErrorMessage") + .original_result() + } + + pub fn sum( + self, + ) -> TxTypedCall> { + self.wrapped_tx + .payment(NotPayable) + .raw_call("getSum") + .original_result() + } + + /// Add desired amount to the storage variable. + pub fn add< + Arg0: ProxyArg>, + >( + self, + value: Arg0, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("add") + .argument(&value) + .original_result() + } + + pub fn issue_fungible_token< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + Arg2: ProxyArg>, + >( + self, + token_display_name: Arg0, + token_ticker: Arg1, + initial_supply: Arg2, + ) -> TxTypedCall { + self.wrapped_tx + .raw_call("issue_fungible_token") + .argument(&token_display_name) + .argument(&token_ticker) + .argument(&initial_supply) + .original_result() + } + + pub fn send_egld< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + >( + self, + to: Arg0, + amount: Arg1, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("send_egld") + .argument(&to) + .argument(&amount) + .original_result() + } +} diff --git a/contracts/examples/token-identifier-test/returns-token-identifier-test/src/returns_token_identifier_test.rs b/contracts/examples/token-identifier-test/returns-token-identifier-test/src/returns_token_identifier_test.rs index 36b16396e0..10f9d7280f 100644 --- a/contracts/examples/token-identifier-test/returns-token-identifier-test/src/returns_token_identifier_test.rs +++ b/contracts/examples/token-identifier-test/returns-token-identifier-test/src/returns_token_identifier_test.rs @@ -2,12 +2,21 @@ use multiversx_sc::imports::*; +pub mod proxy_proxy_test; pub mod returns_token_identifier_test_proxy; /// One of the simplest smart contracts possible, /// it holds a single variable in storage, which anyone can increment. #[multiversx_sc::contract] pub trait ReturnsTokenIdentifierTest { + #[view(lastIssuedToken)] + #[storage_mapper("lastIssuedToken")] + fn last_issued_token(&self) -> SingleValueMapper; + + #[view(lastErrorMessage)] + #[storage_mapper("lastErrorMessage")] + fn last_error_message(&self) -> SingleValueMapper; + #[view(getSum)] #[storage_mapper("sum")] fn sum(&self) -> SingleValueMapper; @@ -27,5 +36,48 @@ pub trait ReturnsTokenIdentifierTest { fn add(&self, value: BigUint) { self.sum().update(|sum| *sum += value); } - // TODO!: Call the proxy-test issue function!! + + #[payable("*")] + #[endpoint] + fn call_contract( + &self, + contract_address: &ManagedAddress, + token_display_name: ManagedBuffer, + token_ticker: ManagedBuffer, + initial_supply: BigUint, + ) { + let caller = self.blockchain().get_caller(); + self.tx() + .to(contract_address) + .typed(proxy_proxy_test::ProxyTestProxy) + .issue_fungible_token(token_display_name, token_ticker, initial_supply) + .with_callback(self.callbacks().esdt_issue_callback(&caller)) + .async_call_and_exit(); + } + + #[callback] + fn esdt_issue_callback( + &self, + caller: &ManagedAddress, + #[call_result] result: ManagedAsyncCallResult<()>, + ) { + let (token_identifier, returned_tokens) = self.call_value().egld_or_single_fungible_esdt(); + // callback is called with ESDTTransfer of the newly issued token, with the amount requested, + // 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_error_message().clear(); + }, + ManagedAsyncCallResult::Err(message) => { + // return issue cost to the caller + if token_identifier.is_egld() && returned_tokens > 0 { + self.tx().to(caller).egld(&returned_tokens).transfer(); + } + + self.last_error_message().set(&message.err_msg); + }, + } + } + // erd1qqqqqqqqqqqqqpgqyu0yylry6dyvynsqsmswqzvyewes38j0a4sqevrx55 } diff --git a/contracts/examples/token-identifier-test/returns-token-identifier-test/src/returns_token_identifier_test_proxy.rs b/contracts/examples/token-identifier-test/returns-token-identifier-test/src/returns_token_identifier_test_proxy.rs index 1129b35b96..3f016dfd6b 100644 --- a/contracts/examples/token-identifier-test/returns-token-identifier-test/src/returns_token_identifier_test_proxy.rs +++ b/contracts/examples/token-identifier-test/returns-token-identifier-test/src/returns_token_identifier_test_proxy.rs @@ -89,6 +89,24 @@ where To: TxTo, Gas: TxGas, { + pub fn last_issued_token( + self, + ) -> TxTypedCall> { + self.wrapped_tx + .payment(NotPayable) + .raw_call("lastIssuedToken") + .original_result() + } + + pub fn last_error_message( + self, + ) -> TxTypedCall> { + self.wrapped_tx + .payment(NotPayable) + .raw_call("lastErrorMessage") + .original_result() + } + pub fn sum( self, ) -> TxTypedCall> { @@ -111,4 +129,25 @@ where .argument(&value) .original_result() } + + pub fn call_contract< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + Arg2: ProxyArg>, + Arg3: ProxyArg>, + >( + self, + contract_address: Arg0, + token_display_name: Arg1, + token_ticker: Arg2, + initial_supply: Arg3, + ) -> TxTypedCall { + self.wrapped_tx + .raw_call("call_contract") + .argument(&contract_address) + .argument(&token_display_name) + .argument(&token_ticker) + .argument(&initial_supply) + .original_result() + } } diff --git a/contracts/examples/token-identifier-test/returns-token-identifier-test/wasm/Cargo.lock b/contracts/examples/token-identifier-test/returns-token-identifier-test/wasm/Cargo.lock new file mode 100644 index 0000000000..d5b3c8b46f --- /dev/null +++ b/contracts/examples/token-identifier-test/returns-token-identifier-test/wasm/Cargo.lock @@ -0,0 +1,178 @@ +# 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 = "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-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 = "returns-token-identifier-test" +version = "0.0.0" +dependencies = [ + "multiversx-sc", +] + +[[package]] +name = "returns-token-identifier-test-wasm" +version = "0.0.0" +dependencies = [ + "multiversx-sc-wasm-adapter", + "returns-token-identifier-test", +] + +[[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/examples/token-identifier-test/returns-token-identifier-test/wasm/Cargo.toml b/contracts/examples/token-identifier-test/returns-token-identifier-test/wasm/Cargo.toml new file mode 100644 index 0000000000..f2872c5e04 --- /dev/null +++ b/contracts/examples/token-identifier-test/returns-token-identifier-test/wasm/Cargo.toml @@ -0,0 +1,35 @@ +# Code generated by the multiversx-sc build system. DO NOT EDIT. + +# ########################################## +# ############## AUTO-GENERATED ############# +# ########################################## + +[package] +name = "returns-token-identifier-test-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.returns-token-identifier-test] +path = ".." + +[dependencies.multiversx-sc-wasm-adapter] +version = "0.52.3" +path = "../../../../../framework/wasm-adapter" + +[workspace] +members = ["."] diff --git a/contracts/examples/token-identifier-test/returns-token-identifier-test/wasm/src/lib.rs b/contracts/examples/token-identifier-test/returns-token-identifier-test/wasm/src/lib.rs new file mode 100644 index 0000000000..8b6600c5c1 --- /dev/null +++ b/contracts/examples/token-identifier-test/returns-token-identifier-test/wasm/src/lib.rs @@ -0,0 +1,31 @@ +// Code generated by the multiversx-sc build system. DO NOT EDIT. + +//////////////////////////////////////////////////// +////////////////// AUTO-GENERATED ////////////////// +//////////////////////////////////////////////////// + +// Init: 1 +// Upgrade: 1 +// Endpoints: 5 +// Async Callback: 1 +// Total number of exported functions: 8 + +#![no_std] + +multiversx_sc_wasm_adapter::allocator!(); +multiversx_sc_wasm_adapter::panic_handler!(); + +multiversx_sc_wasm_adapter::endpoints! { + returns_token_identifier_test + ( + init => init + upgrade => upgrade + lastIssuedToken => last_issued_token + lastErrorMessage => last_error_message + getSum => sum + add => add + call_contract => call_contract + ) +} + +multiversx_sc_wasm_adapter::async_callback! { returns_token_identifier_test }