From f14cf65a4b6060f100023baaf155c2d4c2d415dd Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Tue, 28 May 2024 21:23:51 +0300 Subject: [PATCH] promise transfer no data example --- .../promises-features/src/common.rs | 3 + .../src/fwd_call_promises.rs | 47 ++++++++++ .../promises-features/wasm/src/lib.rs | 8 +- .../promises_call_transfer_callback.scen.json | 94 +++++++++++++++++++ .../tests/composability_scenario_go_test.rs | 6 ++ .../tests/composability_scenario_rs_test.rs | 6 ++ 6 files changed, 161 insertions(+), 3 deletions(-) create mode 100644 contracts/feature-tests/composability/scenarios/promises_call_transfer_callback.scen.json diff --git a/contracts/feature-tests/composability/promises-features/src/common.rs b/contracts/feature-tests/composability/promises-features/src/common.rs index 9d0e245fb9..cbc494ce1b 100644 --- a/contracts/feature-tests/composability/promises-features/src/common.rs +++ b/contracts/feature-tests/composability/promises-features/src/common.rs @@ -20,6 +20,9 @@ pub trait CommonModule { #[indexed] payment: &BigUint, ); + #[event("callback_result")] + fn callback_result(&self, #[indexed] result: MultiValueEncoded); + #[view] #[storage_mapper("callback_data")] fn callback_data(&self) -> VecMapper>; diff --git a/contracts/feature-tests/composability/promises-features/src/fwd_call_promises.rs b/contracts/feature-tests/composability/promises-features/src/fwd_call_promises.rs index 92a2c8e0e1..672ac20a40 100644 --- a/contracts/feature-tests/composability/promises-features/src/fwd_call_promises.rs +++ b/contracts/feature-tests/composability/promises-features/src/fwd_call_promises.rs @@ -55,4 +55,51 @@ pub trait CallPromisesModule: common::CommonModule { args: ManagedVec::new(), }); } + + #[endpoint] + #[payable("*")] + fn forward_payment_callback(&self, to: ManagedAddress) { + let payment = self.call_value().any_payment(); + let gas_limit = self.blockchain().get_gas_left() / 2; + + self.tx() + .to(&to) + .raw_call("") + .gas(gas_limit) + .payment(payment) + .callback(self.callbacks().transfer_callback()) + .register_promise(); + } + + #[promises_callback] + fn transfer_callback(&self, #[call_result] result: MultiValueEncoded) { + self.callback_result(result); + + let call_value = self.call_value().any_payment(); + match call_value { + EgldOrMultiEsdtPayment::Egld(egld) => { + self.retrieve_funds_callback_event(&EgldOrEsdtTokenIdentifier::egld(), 0, &egld); + let _ = self.callback_data().push(&CallbackData { + callback_name: ManagedBuffer::from(b"transfer_callback"), + token_identifier: EgldOrEsdtTokenIdentifier::egld(), + token_nonce: 0, + token_amount: egld, + args: ManagedVec::new(), + }); + }, + EgldOrMultiEsdtPayment::MultiEsdt(multi_esdt) => { + for esdt in multi_esdt.into_iter() { + let token_identifier = EgldOrEsdtTokenIdentifier::esdt(esdt.token_identifier); + self.retrieve_funds_callback_event(&token_identifier, 0, &esdt.amount); + let _ = self.callback_data().push(&CallbackData { + callback_name: ManagedBuffer::from(b"transfer_callback"), + token_identifier, + token_nonce: 0, + token_amount: esdt.amount, + args: ManagedVec::new(), + }); + } + }, + } + } } diff --git a/contracts/feature-tests/composability/promises-features/wasm/src/lib.rs b/contracts/feature-tests/composability/promises-features/wasm/src/lib.rs index 1dc649df0d..895ab88636 100644 --- a/contracts/feature-tests/composability/promises-features/wasm/src/lib.rs +++ b/contracts/feature-tests/composability/promises-features/wasm/src/lib.rs @@ -5,10 +5,10 @@ //////////////////////////////////////////////////// // Init: 1 -// Endpoints: 10 +// Endpoints: 11 // Async Callback (empty): 1 -// Promise callbacks: 3 -// Total number of exported functions: 15 +// Promise callbacks: 4 +// Total number of exported functions: 17 #![no_std] @@ -24,12 +24,14 @@ multiversx_sc_wasm_adapter::endpoints! { clear_callback_data => clear_callback_data forward_promise_accept_funds => forward_promise_accept_funds forward_promise_retrieve_funds => forward_promise_retrieve_funds + forward_payment_callback => forward_payment_callback promise_raw_single_token => promise_raw_single_token promise_raw_multi_transfer => promise_raw_multi_transfer forward_sync_retrieve_funds_bt => forward_sync_retrieve_funds_bt forward_sync_retrieve_funds_bt_twice => forward_sync_retrieve_funds_bt_twice forward_promise_retrieve_funds_back_transfers => forward_promise_retrieve_funds_back_transfers retrieve_funds_callback => retrieve_funds_callback + transfer_callback => transfer_callback the_one_callback => the_one_callback retrieve_funds_back_transfers_callback => retrieve_funds_back_transfers_callback ) diff --git a/contracts/feature-tests/composability/scenarios/promises_call_transfer_callback.scen.json b/contracts/feature-tests/composability/scenarios/promises_call_transfer_callback.scen.json new file mode 100644 index 0000000000..3658141127 --- /dev/null +++ b/contracts/feature-tests/composability/scenarios/promises_call_transfer_callback.scen.json @@ -0,0 +1,94 @@ +{ + "steps": [ + { + "step": "setState", + "accounts": { + "address:a_user": { + "nonce": "0", + "balance": "1000" + }, + "sc:vault": { + "nonce": "0", + "balance": "0", + "code": "mxsc:../vault/output/vault.mxsc.json" + }, + "sc:forwarder": { + "nonce": "0", + "balance": "0", + "code": "mxsc:../promises-features/output/promises-features.mxsc.json" + } + } + }, + { + "step": "scCall", + "id": "1", + "tx": { + "from": "address:a_user", + "to": "sc:forwarder", + "egldValue": "1000", + "function": "forward_payment_callback", + "arguments": [ + "sc:vault" + ], + "gasLimit": "60,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [], + "status": "0", + "logs": [ + { + "address": "sc:forwarder", + "endpoint": "str:transferValueOnly", + "topics": [ + "1000", + "sc:vault" + ], + "data": [ + "str:AsyncCall", + "str:accept_funds" + ] + }, + { + "address": "sc:vault", + "endpoint": "str:accept_funds", + "topics": [ + "str:accept_funds", + "1000" + ], + "data": [ + "" + ] + } + ], + "gas": "*", + "refund": "*" + } + }, + { + "step": "checkState", + "accounts": { + "address:a_user": { + "nonce": "*", + "balance": "0", + "storage": {}, + "code": "" + }, + "sc:vault": { + "nonce": "0", + "balance": "1000", + "storage": { + "str:call_counts|nested:str:accept_funds": "1" + }, + "code": "mxsc:../vault/output/vault.mxsc.json" + }, + "sc:forwarder": { + "nonce": "0", + "balance": "0", + "storage": {}, + "code": "mxsc:../promises-features/output/promises-features.mxsc.json" + } + } + } + ] +} diff --git a/contracts/feature-tests/composability/tests/composability_scenario_go_test.rs b/contracts/feature-tests/composability/tests/composability_scenario_go_test.rs index 8f61befdbe..704ef3668c 100644 --- a/contracts/feature-tests/composability/tests/composability_scenario_go_test.rs +++ b/contracts/feature-tests/composability/tests/composability_scenario_go_test.rs @@ -437,6 +437,12 @@ fn promises_call_callback_directly_go() { world().run("scenarios/promises_call_callback_directly.scen.json"); } +#[test] +#[ignore = "VM does not support this"] +fn promises_call_transfer_callback_go() { + world().run("scenarios/promises_call_transfer_callback.scen.json"); +} + #[test] #[ignore = "TODO"] fn promises_multi_transfer_go() { diff --git a/contracts/feature-tests/composability/tests/composability_scenario_rs_test.rs b/contracts/feature-tests/composability/tests/composability_scenario_rs_test.rs index 33db8b4b49..2d0eee062b 100644 --- a/contracts/feature-tests/composability/tests/composability_scenario_rs_test.rs +++ b/contracts/feature-tests/composability/tests/composability_scenario_rs_test.rs @@ -487,6 +487,12 @@ fn promises_call_callback_directly_rs() { world().run("scenarios/promises_call_callback_directly.scen.json"); } +#[test] +#[ignore = "VM does not support this"] +fn promises_call_transfer_callback_rs() { + world().run("scenarios/promises_call_transfer_callback.scen.json"); +} + #[test] fn promises_multi_transfer_rs() { world().run("scenarios/promises_multi_transfer.scen.json");