From 928ca501e0e461d322d954f75589ed6ba0bb5a6d Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Wed, 27 Mar 2024 12:26:36 +0200 Subject: [PATCH] NumExpr & GasLeft --- .../adder/interact/src/basic_interact.rs | 4 +- .../interact/src/multisig_interact.rs | 8 +-- .../interact/src/multisig_interact_nfts.rs | 12 ++--- .../interact/src/multisig_interact_wegld.rs | 9 ++-- .../contract_base/wrappers/send_wrapper.rs | 6 +-- .../base/src/types/interaction/annotated.rs | 13 ++++- .../annotated/annotated_impl_u64.rs | 11 +--- .../base/src/types/interaction/markers.rs | 7 +++ .../src/types/interaction/markers/gas_left.rs | 29 ++++++++++ .../tx_to_caller.rs => markers/to_caller.rs} | 6 +-- .../tx_to_self.rs => markers/to_self.rs} | 6 +-- framework/base/src/types/interaction/mod.rs | 2 + framework/base/src/types/interaction/tx_to.rs | 6 --- .../scenario/src/facade/world_tx/expr.rs | 2 + .../src/facade/world_tx/expr/num_expr.rs | 53 +++++++++++++++++++ 15 files changed, 133 insertions(+), 41 deletions(-) create mode 100644 framework/base/src/types/interaction/markers.rs create mode 100644 framework/base/src/types/interaction/markers/gas_left.rs rename framework/base/src/types/interaction/{tx_to/tx_to_caller.rs => markers/to_caller.rs} (91%) rename framework/base/src/types/interaction/{tx_to/tx_to_self.rs => markers/to_self.rs} (90%) create mode 100644 framework/scenario/src/facade/world_tx/expr/num_expr.rs diff --git a/contracts/examples/adder/interact/src/basic_interact.rs b/contracts/examples/adder/interact/src/basic_interact.rs index 7941bd7626..6664d030ba 100644 --- a/contracts/examples/adder/interact/src/basic_interact.rs +++ b/contracts/examples/adder/interact/src/basic_interact.rs @@ -17,7 +17,7 @@ use multiversx_sc_snippets::{ scenario_format::interpret_trait::{InterpretableFrom, InterpreterContext}, scenario_model::{BytesValue, ScDeployStep, Scenario}, standalone::retrieve_account_as_scenario_set_state, - test_wallets, ContractInfo, WithRawTxResponse, + test_wallets, ContractInfo, NumExpr, WithRawTxResponse, }, tokio, Interactor, InteractorPrepareAsync, StepBuffer, }; @@ -170,7 +170,7 @@ impl AdderInteract { .tx() .from(&self.wallet_address) .to(self.state.adder().to_address()) - .egld(50000000000000000u64) // TODO: annotate "0,050000000000000000" + .egld(NumExpr("0,050000000000000000")) .prepare_async() .run() .await; diff --git a/contracts/examples/multisig/interact/src/multisig_interact.rs b/contracts/examples/multisig/interact/src/multisig_interact.rs index c60d0c9fac..83295c0b3e 100644 --- a/contracts/examples/multisig/interact/src/multisig_interact.rs +++ b/contracts/examples/multisig/interact/src/multisig_interact.rs @@ -16,7 +16,7 @@ use multiversx_sc_scenario::{ multiversx_sc::types::{BigUint, ReturnsNewAddress, ReturnsResult}, scenario_format::interpret_trait::InterpretableFrom, standalone::retrieve_account_as_scenario_set_state, - test_wallets, + test_wallets, NumExpr, }; use multiversx_sc_snippets::{ dns_address_for_name, env_logger, @@ -167,7 +167,7 @@ impl MultisigInteract { .typed(multisig_proxy::MultisigProxy) .init(&Config::load_config().quorum(), board) .code(&self.multisig_code) - .with_gas_limit(100_000_000u64) + .gas(NumExpr("100,000,000")) .returns(ReturnsNewAddress) .prepare_async() .run() @@ -260,7 +260,7 @@ impl MultisigInteract { .tx() .from(&self.wallet_address) .to(self.state.multisig().to_address()) - .with_gas_limit(gas_expr) + .gas(gas_expr) .typed(multisig_proxy::MultisigProxy) .perform_action_endpoint(action_id) .prepare_async() @@ -371,7 +371,7 @@ impl MultisigInteract { .tx() .from(&self.wallet_address) .to(self.state.multisig().to_address()) - .with_gas_limit(30_000_000u64) + .gas(NumExpr("30,000,000")) .typed(multisig_proxy::MultisigProxy) .dns_register(dns_address, name) .prepare_async() diff --git a/contracts/examples/multisig/interact/src/multisig_interact_nfts.rs b/contracts/examples/multisig/interact/src/multisig_interact_nfts.rs index e1d48158fd..62314ef63c 100644 --- a/contracts/examples/multisig/interact/src/multisig_interact_nfts.rs +++ b/contracts/examples/multisig/interact/src/multisig_interact_nfts.rs @@ -5,7 +5,7 @@ use multiversx_sc_scenario::{ codec::Empty, types::{FunctionCall, ReturnsResult}, }, - ReturnsNewTokenIdentifier, + NumExpr, ReturnsNewTokenIdentifier, }; use super::*; @@ -45,7 +45,7 @@ impl MultisigInteract { .tx() .from(&self.wallet_address) .to(self.state.multisig().to_address()) - .with_gas_limit(10_000_000u64) + .gas(NumExpr("10,000,000")) .typed(multisig_proxy::MultisigProxy) .propose_async_call( system_sc_address, @@ -81,7 +81,7 @@ impl MultisigInteract { .tx() .from(&self.wallet_address) .to(&self.state.multisig().to_address()) - .with_gas_limit(80_000_000u64) + .gas(NumExpr("80,000,000")) .typed(multisig_proxy::MultisigProxy) .perform_action_endpoint(action_id) .returns(ReturnsNewTokenIdentifier) @@ -103,7 +103,7 @@ impl MultisigInteract { .tx() .from(&self.wallet_address) .to(&self.state.multisig().to_address()) - .with_gas_limit(10_000_000u64) + .gas(NumExpr("10,000,000")) .typed(multisig_proxy::MultisigProxy) .propose_async_call( system_sc_address, @@ -136,7 +136,7 @@ impl MultisigInteract { .tx() .from(&self.wallet_address) .to(&self.state.multisig().to_address()) - .with_gas_limit(80_000_000u64) + .gas(NumExpr("80,000,000")) .typed(multisig_proxy::MultisigProxy) .perform_action_endpoint(action_id) .returns(ReturnsNewTokenIdentifier) @@ -158,7 +158,7 @@ impl MultisigInteract { .tx() .from(&self.wallet_address) .to(&self.state.multisig().to_address()) - .with_gas_limit(10_000_000u64) + .gas(NumExpr("10,000,000")) .typed(multisig_proxy::MultisigProxy) .propose_async_call( &self.system_sc_address, diff --git a/contracts/examples/multisig/interact/src/multisig_interact_wegld.rs b/contracts/examples/multisig/interact/src/multisig_interact_wegld.rs index 92efedc86e..6e3c10563e 100644 --- a/contracts/examples/multisig/interact/src/multisig_interact_wegld.rs +++ b/contracts/examples/multisig/interact/src/multisig_interact_wegld.rs @@ -1,6 +1,9 @@ use std::time::Duration; -use multiversx_sc_scenario::multiversx_sc::types::{ContractCallBase, FunctionCall, ReturnsResult}; +use multiversx_sc_scenario::{ + multiversx_sc::types::{ContractCallBase, FunctionCall, ReturnsResult}, + NumExpr, +}; #[allow(unused_imports)] use multiversx_sc_snippets::multiversx_sc::types::{ EsdtTokenPayment, MultiValueEncoded, TokenIdentifier, @@ -65,7 +68,7 @@ impl MultisigInteract { .tx() .from(&self.wallet_address) .to(&self.state.multisig().to_address()) - .with_gas_limit(10_000_000u64) + .gas(NumExpr("10,000,000")) .typed(multisig_proxy::MultisigProxy) .propose_async_call( bech32::decode(WEGLD_SWAP_SC_BECH32), @@ -98,7 +101,7 @@ impl MultisigInteract { .tx() .from(&self.wallet_address) .to(&self.state.multisig().to_address()) - .with_gas_limit(10_000_000u64) + .gas(NumExpr("10,000,000")) .typed(multisig_proxy::MultisigProxy) .propose_async_call( contract_call.basic.to, diff --git a/framework/base/src/contract_base/wrappers/send_wrapper.rs b/framework/base/src/contract_base/wrappers/send_wrapper.rs index 6083b7b92a..dc63932e22 100644 --- a/framework/base/src/contract_base/wrappers/send_wrapper.rs +++ b/framework/base/src/contract_base/wrappers/send_wrapper.rs @@ -12,7 +12,7 @@ use crate::{ }, codec, esdt::ESDTSystemSmartContractProxy, - proxy_imports::{ReturnsRawResult, ToSelf}, + proxy_imports::{GasLeft, ReturnsRawResult, ToSelf}, types::{ BigUint, ContractCall, ContractCallNoPayment, EgldOrEsdtTokenIdentifier, EsdtTokenPayment, ManagedAddress, ManagedArgBuffer, ManagedBuffer, ManagedType, ManagedVec, TokenIdentifier, @@ -386,7 +386,7 @@ where ) -> ManagedVec> { Tx::new_tx_from_sc() .to(ToSelf) - .with_gas_limit(gas) + .gas(gas) .raw_call() .function_name(endpoint_name) .arguments_raw(arg_buffer) @@ -401,7 +401,7 @@ where ) { Tx::new_tx_from_sc() .to(ToSelf) - .with_gas_limit(A::blockchain_api_impl().get_gas_left()) + .gas(GasLeft) .raw_call() .function_name(function_name) .arguments_raw(arg_buffer) diff --git a/framework/base/src/types/interaction/annotated.rs b/framework/base/src/types/interaction/annotated.rs index a7f18c6745..ab2953b4fb 100644 --- a/framework/base/src/types/interaction/annotated.rs +++ b/framework/base/src/types/interaction/annotated.rs @@ -4,7 +4,8 @@ mod annotated_impl_managed_buffer; mod annotated_impl_u64; use crate::{ - proxy_imports::ManagedRef, + formatter::FormatBuffer, + proxy_imports::{ManagedBufferCachedBuilder, ManagedRef, ManagedTypeApi}, types::{heap::Address, BigUint, ManagedAddress, ManagedBuffer}, }; @@ -36,3 +37,13 @@ where f(&self.to_value(env)) } } + +/// Useful for u64 display in several places. +pub(super) fn display_u64(n: u64) -> ManagedBuffer +where + Api: ManagedTypeApi, +{ + let mut result = ManagedBufferCachedBuilder::new_from_slice(&[]); + result.append_display(&n); + result.into_managed_buffer() +} diff --git a/framework/base/src/types/interaction/annotated/annotated_impl_u64.rs b/framework/base/src/types/interaction/annotated/annotated_impl_u64.rs index 0905710c25..9c1435c581 100644 --- a/framework/base/src/types/interaction/annotated/annotated_impl_u64.rs +++ b/framework/base/src/types/interaction/annotated/annotated_impl_u64.rs @@ -7,16 +7,7 @@ use crate::{ }, }; -use super::{AnnotatedValue, TxEnv}; - -pub(crate) fn display_u64(n: u64) -> ManagedBuffer -where - Api: ManagedTypeApi, -{ - let mut result = ManagedBufferCachedBuilder::new_from_slice(&[]); - result.append_display(&n); - result.into_managed_buffer() -} +use super::{display_u64, AnnotatedValue, TxEnv}; impl AnnotatedValue for u64 where diff --git a/framework/base/src/types/interaction/markers.rs b/framework/base/src/types/interaction/markers.rs new file mode 100644 index 0000000000..10ccdea5d0 --- /dev/null +++ b/framework/base/src/types/interaction/markers.rs @@ -0,0 +1,7 @@ +mod gas_left; +mod to_caller; +mod to_self; + +pub use gas_left::GasLeft; +pub use to_caller::ToCaller; +pub use to_self::ToSelf; diff --git a/framework/base/src/types/interaction/markers/gas_left.rs b/framework/base/src/types/interaction/markers/gas_left.rs new file mode 100644 index 0000000000..69f43753f6 --- /dev/null +++ b/framework/base/src/types/interaction/markers/gas_left.rs @@ -0,0 +1,29 @@ +use crate::{ + api::{BlockchainApi, BlockchainApiImpl, ManagedTypeApi}, + formatter::FormatBuffer, + types::{ + interaction::display_u64, AnnotatedValue, BigUint, ManagedAddress, ManagedBuffer, + ManagedBufferCachedBuilder, TxCodeValue, TxEgldValue, TxEnv, TxFrom, TxFromSpecified, + TxGasValue, TxTo, TxToSpecified, + }, +}; + +/// Indicates that all remaining gas should be sent to a transaction. +/// +/// Usually unwise, other than for synchronous calls, you always want to have some gas left in the contract after the call. +pub struct GasLeft; + +impl AnnotatedValue for GasLeft +where + Env: TxEnv, +{ + fn annotation(&self, env: &Env) -> ManagedBuffer { + display_u64(self.to_value(env)) + } + + fn to_value(&self, env: &Env) -> u64 { + Env::Api::blockchain_api_impl().get_gas_left() + } +} + +impl TxGasValue for GasLeft where Env: TxEnv {} diff --git a/framework/base/src/types/interaction/tx_to/tx_to_caller.rs b/framework/base/src/types/interaction/markers/to_caller.rs similarity index 91% rename from framework/base/src/types/interaction/tx_to/tx_to_caller.rs rename to framework/base/src/types/interaction/markers/to_caller.rs index 7217f47c8b..7d311438b9 100644 --- a/framework/base/src/types/interaction/tx_to/tx_to_caller.rs +++ b/framework/base/src/types/interaction/markers/to_caller.rs @@ -1,11 +1,11 @@ use crate::{ api::{const_handles, use_raw_handle, BlockchainApi, BlockchainApiImpl, CallTypeApi}, contract_base::BlockchainWrapper, - types::{AnnotatedValue, ManagedAddress, ManagedBuffer, ManagedType, TxScEnv}, + types::{ + AnnotatedValue, ManagedAddress, ManagedBuffer, ManagedType, TxScEnv, TxTo, TxToSpecified, + }, }; -use super::{TxTo, TxToSpecified}; - /// Indicates that transaction should be sent to the caller (the sender of the current transaction). pub struct ToCaller; diff --git a/framework/base/src/types/interaction/tx_to/tx_to_self.rs b/framework/base/src/types/interaction/markers/to_self.rs similarity index 90% rename from framework/base/src/types/interaction/tx_to/tx_to_self.rs rename to framework/base/src/types/interaction/markers/to_self.rs index 72350c312e..7b8115b38e 100644 --- a/framework/base/src/types/interaction/tx_to/tx_to_self.rs +++ b/framework/base/src/types/interaction/markers/to_self.rs @@ -1,11 +1,11 @@ use crate::{ api::{const_handles, use_raw_handle, BlockchainApi, BlockchainApiImpl, CallTypeApi}, contract_base::BlockchainWrapper, - types::{AnnotatedValue, ManagedAddress, ManagedBuffer, ManagedType, TxScEnv}, + types::{ + AnnotatedValue, ManagedAddress, ManagedBuffer, ManagedType, TxScEnv, TxTo, TxToSpecified, + }, }; -use super::{TxTo, TxToSpecified}; - /// Indicates that transaction should be sent to itself. pub struct ToSelf; diff --git a/framework/base/src/types/interaction/mod.rs b/framework/base/src/types/interaction/mod.rs index 125f16150b..ffe4cec68f 100644 --- a/framework/base/src/types/interaction/mod.rs +++ b/framework/base/src/types/interaction/mod.rs @@ -19,6 +19,7 @@ mod deploy_call; mod expr; mod function_call; mod managed_arg_buffer; +mod markers; mod tx; mod tx_call_async; mod tx_call_async_promises; @@ -60,6 +61,7 @@ pub use deploy_call::*; pub use expr::*; pub use function_call::FunctionCall; pub use managed_arg_buffer::ManagedArgBuffer; +pub use markers::*; pub use tx::*; pub use tx_call_async::*; pub use tx_call_async_promises::*; diff --git a/framework/base/src/types/interaction/tx_to.rs b/framework/base/src/types/interaction/tx_to.rs index 03f3105858..6ba0f6eec8 100644 --- a/framework/base/src/types/interaction/tx_to.rs +++ b/framework/base/src/types/interaction/tx_to.rs @@ -1,9 +1,3 @@ -mod tx_to_caller; -mod tx_to_self; - -pub use tx_to_caller::ToCaller; -pub use tx_to_self::ToSelf; - use crate::types::{heap::Address, ManagedAddress}; use super::{AnnotatedValue, TxEnv}; diff --git a/framework/scenario/src/facade/world_tx/expr.rs b/framework/scenario/src/facade/world_tx/expr.rs index 2d28c5bdbd..37750ee973 100644 --- a/framework/scenario/src/facade/world_tx/expr.rs +++ b/framework/scenario/src/facade/world_tx/expr.rs @@ -1,5 +1,7 @@ mod file_expr; mod mxsc_expr; +mod num_expr; pub use file_expr::FileExpr; pub use mxsc_expr::MxscExpr; +pub use num_expr::NumExpr; diff --git a/framework/scenario/src/facade/world_tx/expr/num_expr.rs b/framework/scenario/src/facade/world_tx/expr/num_expr.rs new file mode 100644 index 0000000000..de9137b8fc --- /dev/null +++ b/framework/scenario/src/facade/world_tx/expr/num_expr.rs @@ -0,0 +1,53 @@ +use crate::{api::StaticApi, ScenarioEnvExec, ScenarioTxEnv, ScenarioTxEnvData}; +use core::ptr; +use multiversx_chain_scenario_format::{ + interpret_trait::InterpreterContext, value_interpreter::interpret_string, +}; +use multiversx_sc::{ + api::ManagedTypeApi, + types::{ + AnnotatedValue, BigUint, ManagedAddress, ManagedBuffer, TxCodeValue, TxEgldValue, TxEnv, + TxFrom, TxFromSpecified, TxGasValue, TxTo, TxToSpecified, + }, +}; +use std::path::PathBuf; + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct NumExpr<'a>(pub &'a str); + +fn interpret_big_uint(s: &str) -> BigUint +where + Api: ManagedTypeApi, +{ + let bytes = interpret_string(s, &InterpreterContext::new()); + BigUint::from_bytes_be(&bytes) +} + +impl<'a, Env> AnnotatedValue> for NumExpr<'a> +where + Env: ScenarioTxEnv, +{ + fn annotation(&self, _env: &Env) -> ManagedBuffer { + self.0.into() + } + + fn to_value(&self, env: &Env) -> BigUint { + interpret_big_uint(self.0) + } +} + +impl<'a, Env> AnnotatedValue for NumExpr<'a> +where + Env: ScenarioTxEnv, +{ + fn annotation(&self, _env: &Env) -> ManagedBuffer { + self.0.into() + } + + fn to_value(&self, env: &Env) -> u64 { + interpret_big_uint::(self.0).to_u64().unwrap() + } +} + +impl<'a, Env> TxEgldValue for NumExpr<'a> where Env: ScenarioTxEnv {} +impl<'a, Env> TxGasValue for NumExpr<'a> where Env: ScenarioTxEnv {}