Skip to content

Commit

Permalink
call value - EGLD backwards compatibility protection
Browse files Browse the repository at this point in the history
  • Loading branch information
andrei-marinica committed Dec 5, 2024
1 parent 90820a0 commit 0f19b6a
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 12 deletions.
1 change: 1 addition & 0 deletions framework/base/src/api/managed_types/const_handles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub const CALL_VALUE_SINGLE_ESDT_TOKEN_NAME: RawHandle = -22;
pub const CALLBACK_CLOSURE_ARGS_BUFFER: RawHandle = -23;
pub const MBUF_TEMPORARY_1: RawHandle = -25;
pub const MBUF_TEMPORARY_2: RawHandle = -26;
pub const MBUF_EGLD_000000: RawHandle = -27;

pub const ADDRESS_CALLER: RawHandle = -30;
pub const ADDRESS_SELF: RawHandle = -31;
Expand Down
70 changes: 61 additions & 9 deletions framework/base/src/contract_base/wrappers/call_value_wrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,19 @@ use core::marker::PhantomData;
use crate::{
api::{
const_handles, use_raw_handle, CallValueApi, CallValueApiImpl, ErrorApi, ErrorApiImpl,
HandleConstraints, ManagedTypeApi, StaticVarApiImpl,
HandleConstraints, ManagedBufferApiImpl, ManagedTypeApi, StaticVarApiImpl,
},
err_msg,
types::{
BigUint, ConstDecimals, EgldOrEsdtTokenIdentifier, EgldOrEsdtTokenPayment,
EgldOrMultiEsdtPayment, EsdtTokenPayment, ManagedDecimal, ManagedRef, ManagedType,
ManagedVec, ManagedVecRef, TokenIdentifier,
ManagedVec, ManagedVecItem, ManagedVecItemPayload, ManagedVecPayloadIterator,
ManagedVecRef, TokenIdentifier,
},
};

const EGLD_000000_TOKEN_IDENTIFIER: &str = "EGLD-000000";

#[derive(Default)]
pub struct CallValueWrapper<A>
where
Expand Down Expand Up @@ -55,13 +58,11 @@ where
/// Will return 0 results if nothing was transfered, or just EGLD.
/// Fully managed underlying types, very efficient.
pub fn all_esdt_transfers(&self) -> ManagedRef<'static, A, ManagedVec<A, EsdtTokenPayment<A>>> {
let mut call_value_handle: A::ManagedBufferHandle =
use_raw_handle(A::static_var_api_impl().get_call_value_multi_esdt_handle());
if call_value_handle == const_handles::UNINITIALIZED_HANDLE {
call_value_handle = use_raw_handle(const_handles::CALL_VALUE_MULTI_ESDT);
A::static_var_api_impl()
.set_call_value_multi_esdt_handle(call_value_handle.get_raw_handle());
A::call_value_api_impl().load_all_esdt_transfers(call_value_handle.clone());
let call_value_handle = load_all_transfers::<A>();

let egld_payment = find_egld_000000_transfer::<A>(call_value_handle.clone());
if egld_payment.is_some() {
A::error_api_impl().signal_error(err_msg::INCORRECT_NUM_ESDT_TRANSFERS.as_bytes())
}
unsafe { ManagedRef::wrap_handle(call_value_handle) }
}
Expand Down Expand Up @@ -164,3 +165,54 @@ where
}
}
}

fn load_all_transfers<A>() -> A::ManagedBufferHandle
where
A: CallValueApi + ErrorApi + ManagedTypeApi,
{
let mut call_value_handle: A::ManagedBufferHandle =
use_raw_handle(A::static_var_api_impl().get_call_value_multi_esdt_handle());
if call_value_handle == const_handles::UNINITIALIZED_HANDLE {
call_value_handle = use_raw_handle(const_handles::CALL_VALUE_MULTI_ESDT);
A::static_var_api_impl()
.set_call_value_multi_esdt_handle(call_value_handle.get_raw_handle());
A::call_value_api_impl().load_all_esdt_transfers(call_value_handle.clone());
}
call_value_handle
}

fn find_egld_000000_transfer<A>(
transfers_vec_handle: A::ManagedBufferHandle,
) -> Option<A::ManagedBufferHandle>
where
A: CallValueApi + ErrorApi + ManagedTypeApi,
{
A::managed_type_impl().mb_overwrite(
use_raw_handle(const_handles::MBUF_EGLD_000000),
EGLD_000000_TOKEN_IDENTIFIER.as_bytes(),
);
unsafe {
let mut iter: ManagedVecPayloadIterator<
A,
<EsdtTokenPayment<A> as ManagedVecItem>::PAYLOAD,
> = ManagedVecPayloadIterator::new(transfers_vec_handle);

if iter.remaining_count() <= 1 {
// EGLD is not allowed in single transfers
return None;
}

let egld_payload = iter.find(|payload| {
let token_identifier_handle = i32::read_from_payload(payload.slice_unchecked(0));
A::managed_type_impl().mb_eq(
use_raw_handle(const_handles::MBUF_EGLD_000000),
use_raw_handle(token_identifier_handle),
)
});

egld_payload.map(|payload| {
let amount_handle = i32::read_from_payload(payload.slice_unchecked(12));
use_raw_handle(amount_handle)
})
}
}
1 change: 1 addition & 0 deletions framework/base/src/err_msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub const BAD_TOKEN_TICKER_FORMAT: &str = "bad token ticker format";
pub const SINGLE_ESDT_EXPECTED: &str = "function expects single ESDT payment";
pub const TOO_MANY_ESDT_TRANSFERS: &str = "too many ESDT transfers";
pub const ESDT_INVALID_TOKEN_INDEX: &str = "invalid token index";
pub const ESDT_UNEXPECTED_EGLD: &str = "unexpected EGLD transfer";
pub const INCORRECT_NUM_ESDT_TRANSFERS: &str = "incorrect number of ESDT transfers";
pub static FUNGIBLE_TOKEN_EXPECTED_ERR_MSG: &str = "fungible ESDT token expected";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ where
M: ManagedTypeApi,
P: ManagedVecItemPayload,
{
pub(super) vec_handle: M::ManagedBufferHandle,
vec_handle: M::ManagedBufferHandle,
byte_start: usize,
byte_end: usize,
_phantom: PhantomData<P>,
Expand Down Expand Up @@ -40,6 +40,11 @@ where
_phantom: PhantomData,
}
}

pub fn remaining_count(&self) -> usize {
let size = P::payload_size();
(self.byte_end - self.byte_start) / size
}
}

impl<M, P> Iterator for ManagedVecPayloadIterator<M, P>
Expand Down Expand Up @@ -67,8 +72,7 @@ where
}

fn size_hint(&self) -> (usize, Option<usize>) {
let size = P::payload_size();
let remaining = (self.byte_end - self.byte_start) / size;
let remaining = self.remaining_count();
(remaining, Some(remaining))
}
}
Expand Down

0 comments on commit 0f19b6a

Please sign in to comment.