diff --git a/framework/base/src/contract_base/wrappers/send_wrapper.rs b/framework/base/src/contract_base/wrappers/send_wrapper.rs
index aa0c837fde..519c71158d 100644
--- a/framework/base/src/contract_base/wrappers/send_wrapper.rs
+++ b/framework/base/src/contract_base/wrappers/send_wrapper.rs
@@ -188,16 +188,17 @@ where
}
/// Sends a single ESDT transfer to target address.
- #[inline]
- #[allow(clippy::too_many_arguments)]
pub fn direct_esdt(
&self,
to: &ManagedAddress,
token_identifier: &TokenIdentifier,
- nonce: u64,
+ token_nonce: u64,
amount: &BigUint,
) {
- self.direct_esdt_with_gas_limit(to, token_identifier, nonce, amount, 0, Empty, &[]);
+ Tx::new_tx_from_sc()
+ .to(to)
+ .esdt_refs(token_identifier, token_nonce, amount)
+ .transfer();
}
/// Sends a single ESDT transfer to target address.
diff --git a/framework/base/src/types/interaction/contract_call_convert.rs b/framework/base/src/types/interaction/contract_call_convert.rs
index 88e6ae6627..fe4225d9a4 100644
--- a/framework/base/src/types/interaction/contract_call_convert.rs
+++ b/framework/base/src/types/interaction/contract_call_convert.rs
@@ -38,7 +38,7 @@ where
function_call: self
.basic
.function_call
- .convert_to_single_transfer_fungible_call(&payment),
+ .convert_to_single_transfer_fungible_call(payment.as_refs()),
explicit_gas_limit: self.basic.explicit_gas_limit,
_return_type: PhantomData,
},
@@ -55,7 +55,7 @@ where
function_call: self
.basic
.function_call
- .convert_to_single_transfer_nft_call(&self.basic.to, &payment),
+ .convert_to_single_transfer_nft_call(&self.basic.to, payment.as_refs()),
explicit_gas_limit: self.basic.explicit_gas_limit,
_return_type: PhantomData,
},
diff --git a/framework/base/src/types/interaction/function_call.rs b/framework/base/src/types/interaction/function_call.rs
index efb149e2b4..1d78735a79 100644
--- a/framework/base/src/types/interaction/function_call.rs
+++ b/framework/base/src/types/interaction/function_call.rs
@@ -9,7 +9,10 @@ use crate::{
CallTypeApi, ManagedTypeApi, ESDT_MULTI_TRANSFER_FUNC_NAME, ESDT_NFT_TRANSFER_FUNC_NAME,
ESDT_TRANSFER_FUNC_NAME,
},
- types::{EsdtTokenPayment, ManagedAddress, ManagedBuffer, ManagedVec, MultiValueEncoded},
+ types::{
+ EsdtTokenPayment, EsdtTokenPaymentRefs, ManagedAddress, ManagedBuffer, ManagedVec,
+ MultiValueEncoded,
+ },
};
use super::{ContractCallNoPayment, ManagedArgBuffer, TypedFunctionCall};
@@ -159,7 +162,7 @@ where
/// Constructs `ESDTTransfer` builtin function call.
pub(super) fn convert_to_single_transfer_fungible_call(
self,
- payment: &EsdtTokenPayment,
+ payment: EsdtTokenPaymentRefs<'_, Api>,
) -> FunctionCall {
FunctionCall::new(ESDT_TRANSFER_FUNC_NAME)
.argument(&payment.token_identifier)
@@ -177,7 +180,7 @@ where
pub(super) fn convert_to_single_transfer_nft_call(
self,
to: &ManagedAddress,
- payment: &EsdtTokenPayment,
+ payment: EsdtTokenPaymentRefs<'_, Api>,
) -> FunctionCall {
FunctionCall::new(ESDT_NFT_TRANSFER_FUNC_NAME)
.argument(&payment.token_identifier)
diff --git a/framework/base/src/types/interaction/tx.rs b/framework/base/src/types/interaction/tx.rs
index 9e41ae8b2d..27b11f59f8 100644
--- a/framework/base/src/types/interaction/tx.rs
+++ b/framework/base/src/types/interaction/tx.rs
@@ -1,6 +1,7 @@
use crate::{
api::CallTypeApi,
contract_base::BlockchainWrapper,
+ proxy_imports::{EsdtTokenPaymentRefs, TokenIdentifier},
types::{
BigUint, CodeMetadata, EgldOrEsdtTokenPayment, EsdtTokenPayment, ManagedAddress,
ManagedBuffer, ManagedOption, ManagedVec, MultiEsdtPayment,
@@ -203,6 +204,30 @@ where
}
}
+ /// Sets a single token payment, with the token identifier and amount kept as references.
+ ///
+ /// This is handy whem we only want one ESDT transfer and we want to avoid unnecessary object clones.
+ pub fn esdt_refs<'a>(
+ self,
+ token_identifier: &'a TokenIdentifier,
+ token_nonce: u64,
+ amount: &'a BigUint,
+ ) -> Tx, Gas, Data, RH> {
+ Tx {
+ env: self.env,
+ from: self.from,
+ to: self.to,
+ payment: EsdtTokenPaymentRefs {
+ token_identifier,
+ token_nonce,
+ amount,
+ },
+ gas: self.gas,
+ data: self.data,
+ result_handler: self.result_handler,
+ }
+ }
+
/// Adds a collection of ESDT payments to a transaction.
pub fn multi_esdt(
self,
diff --git a/framework/base/src/types/interaction/tx_payment.rs b/framework/base/src/types/interaction/tx_payment.rs
index 2511d2ede8..4b2f54e29f 100644
--- a/framework/base/src/types/interaction/tx_payment.rs
+++ b/framework/base/src/types/interaction/tx_payment.rs
@@ -4,6 +4,7 @@ mod tx_payment_multi_esdt;
mod tx_payment_none;
mod tx_payment_other;
mod tx_payment_single_esdt;
+mod tx_payment_single_esdt_ref;
pub use tx_payment_egld::{Egld, EgldPayment};
pub use tx_payment_egld_value::TxEgldValue;
diff --git a/framework/base/src/types/interaction/tx_payment/tx_payment_multi_esdt.rs b/framework/base/src/types/interaction/tx_payment/tx_payment_multi_esdt.rs
index de9f65eff9..3c1a554d03 100644
--- a/framework/base/src/types/interaction/tx_payment/tx_payment_multi_esdt.rs
+++ b/framework/base/src/types/interaction/tx_payment/tx_payment_multi_esdt.rs
@@ -15,18 +15,27 @@ where
fn perform_transfer_execute(
self,
- _env: &Env,
+ env: &Env,
to: &ManagedAddress,
gas_limit: u64,
fc: FunctionCall,
) {
- let _ = SendRawWrapper::::new().multi_esdt_transfer_execute(
- to,
- self,
- gas_limit,
- &fc.function_name,
- &fc.arg_buffer,
- );
+ match self.len() {
+ 0 => ().perform_transfer_execute(env, to, gas_limit, fc),
+ 1 => self
+ .get(0)
+ .as_refs()
+ .perform_transfer_execute(env, to, gas_limit, fc),
+ _ => {
+ let _ = SendRawWrapper::::new().multi_esdt_transfer_execute(
+ to,
+ self,
+ gas_limit,
+ &fc.function_name,
+ &fc.arg_buffer,
+ );
+ },
+ }
}
fn with_normalized(
@@ -44,7 +53,7 @@ where
{
match self.len() {
0 => ().with_normalized(env, from, to, fc, f),
- 1 => self.get(0).with_normalized(env, from, to, fc, f),
+ 1 => self.get(0).as_refs().with_normalized(env, from, to, fc, f),
_ => to.with_address_ref(env, |to_addr| {
let fc_conv = fc.convert_to_multi_transfer_esdt_call(to_addr, self);
f(&from.resolve_address(env), &BigUint::zero(), &fc_conv)
diff --git a/framework/base/src/types/interaction/tx_payment/tx_payment_single_esdt.rs b/framework/base/src/types/interaction/tx_payment/tx_payment_single_esdt.rs
index f2fdf5aacb..f5bf61c0f1 100644
--- a/framework/base/src/types/interaction/tx_payment/tx_payment_single_esdt.rs
+++ b/framework/base/src/types/interaction/tx_payment/tx_payment_single_esdt.rs
@@ -23,7 +23,8 @@ where
gas_limit: u64,
fc: FunctionCall,
) {
- MultiEsdtPayment::from_single_item(self).perform_transfer_execute(env, to, gas_limit, fc);
+ self.as_refs()
+ .perform_transfer_execute(env, to, gas_limit, fc);
}
fn with_normalized(
@@ -39,15 +40,7 @@ where
To: TxToSpecified,
F: FnOnce(&ManagedAddress, &BigUint, &FunctionCall) -> R,
{
- to.with_address_ref(env, |to_addr| {
- if self.token_nonce == 0 {
- let fc_conv = fc.convert_to_single_transfer_fungible_call(&self);
- f(to_addr, &BigUint::zero(), &fc_conv)
- } else {
- let fc_conv = fc.convert_to_single_transfer_nft_call(to_addr, &self);
- f(&from.resolve_address(env), &BigUint::zero(), &fc_conv)
- }
- })
+ self.as_refs().with_normalized(env, from, to, fc, f)
}
fn into_full_payment_data(self, _env: &Env) -> FullPaymentData {
diff --git a/framework/base/src/types/interaction/tx_payment/tx_payment_single_esdt_ref.rs b/framework/base/src/types/interaction/tx_payment/tx_payment_single_esdt_ref.rs
new file mode 100644
index 0000000000..c0d568e11b
--- /dev/null
+++ b/framework/base/src/types/interaction/tx_payment/tx_payment_single_esdt_ref.rs
@@ -0,0 +1,81 @@
+use crate::{
+ api::ManagedTypeApi,
+ contract_base::SendRawWrapper,
+ types::{
+ BigUint, EsdtTokenPayment, EsdtTokenPaymentRefs, ManagedAddress, ManagedVec,
+ MultiEsdtPayment, TokenIdentifier, TxFrom, TxToSpecified,
+ },
+};
+
+use super::{AnnotatedEgldPayment, FullPaymentData, FunctionCall, TxEgldValue, TxEnv, TxPayment};
+
+impl<'a, Env> TxPayment for EsdtTokenPaymentRefs<'a, Env::Api>
+where
+ Env: TxEnv,
+{
+ fn is_no_payment(&self) -> bool {
+ self.amount == &0u32
+ }
+
+ fn perform_transfer_execute(
+ self,
+ env: &Env,
+ to: &ManagedAddress,
+ gas_limit: u64,
+ fc: FunctionCall,
+ ) {
+ if self.token_nonce == 0 {
+ // fungible ESDT
+ let _ = SendRawWrapper::::new().transfer_esdt_execute(
+ to,
+ self.token_identifier,
+ self.amount,
+ gas_limit,
+ &fc.function_name,
+ &fc.arg_buffer,
+ );
+ } else {
+ // non-fungible/semi-fungible ESDT
+ let _ = SendRawWrapper::::new().transfer_esdt_nft_execute(
+ to,
+ self.token_identifier,
+ self.token_nonce,
+ self.amount,
+ gas_limit,
+ &fc.function_name,
+ &fc.arg_buffer,
+ );
+ }
+ }
+
+ fn with_normalized(
+ self,
+ env: &Env,
+ from: &From,
+ to: To,
+ fc: FunctionCall,
+ f: F,
+ ) -> R
+ where
+ From: TxFrom,
+ To: TxToSpecified,
+ F: FnOnce(&ManagedAddress, &BigUint, &FunctionCall) -> R,
+ {
+ to.with_address_ref(env, |to_addr| {
+ if self.token_nonce == 0 {
+ let fc_conv = fc.convert_to_single_transfer_fungible_call(self);
+ f(to_addr, &BigUint::zero(), &fc_conv)
+ } else {
+ let fc_conv = fc.convert_to_single_transfer_nft_call(to_addr, self);
+ f(&from.resolve_address(env), &BigUint::zero(), &fc_conv)
+ }
+ })
+ }
+
+ fn into_full_payment_data(self, _env: &Env) -> FullPaymentData {
+ FullPaymentData {
+ egld: None,
+ multi_esdt: MultiEsdtPayment::from_single_item(self.to_owned_payment()),
+ }
+ }
+}
diff --git a/framework/base/src/types/managed/wrapped/esdt_token_payment.rs b/framework/base/src/types/managed/wrapped/esdt_token_payment.rs
index 246b28de1d..161c2c1ee3 100644
--- a/framework/base/src/types/managed/wrapped/esdt_token_payment.rs
+++ b/framework/base/src/types/managed/wrapped/esdt_token_payment.rs
@@ -222,3 +222,31 @@ impl ManagedVecItem for EsdtTokenPayment {
writer(&arr[..])
}
}
+
+/// The version of `EsdtTokenPayment` that contains referrences instead of owned fields.
+pub struct EsdtTokenPaymentRefs<'a, M: ManagedTypeApi> {
+ pub token_identifier: &'a TokenIdentifier,
+ pub token_nonce: u64,
+ pub amount: &'a BigUint,
+}
+
+impl EsdtTokenPayment {
+ pub fn as_refs(&self) -> EsdtTokenPaymentRefs<'_, M> {
+ EsdtTokenPaymentRefs {
+ token_identifier: &self.token_identifier,
+ token_nonce: self.token_nonce,
+ amount: &self.amount,
+ }
+ }
+}
+
+impl<'a, M: ManagedTypeApi> EsdtTokenPaymentRefs<'a, M> {
+ /// Will clone the referenced values.
+ pub fn to_owned_payment(&self) -> EsdtTokenPayment {
+ EsdtTokenPayment {
+ token_identifier: self.token_identifier.clone(),
+ token_nonce: self.token_nonce,
+ amount: self.amount.clone(),
+ }
+ }
+}
diff --git a/framework/base/src/types/managed/wrapped/mod.rs b/framework/base/src/types/managed/wrapped/mod.rs
index 8ac485fa38..a2dcd6008a 100644
--- a/framework/base/src/types/managed/wrapped/mod.rs
+++ b/framework/base/src/types/managed/wrapped/mod.rs
@@ -23,7 +23,7 @@ pub use egld_or_esdt_token_payment::EgldOrEsdtTokenPayment;
pub use egld_or_multi_esdt_payment::EgldOrMultiEsdtPayment;
pub(crate) use encoded_managed_vec_item::EncodedManagedVecItem;
pub use esdt_token_data::EsdtTokenData;
-pub use esdt_token_payment::{EsdtTokenPayment, MultiEsdtPayment};
+pub use esdt_token_payment::{EsdtTokenPayment, EsdtTokenPaymentRefs, MultiEsdtPayment};
pub use managed_address::ManagedAddress;
pub use managed_buffer_cached_builder::ManagedBufferCachedBuilder;
pub(crate) use managed_byte_array::ManagedBufferSizeContext;