Skip to content

Commit

Permalink
system sc interaction and proxy, modify creator tests, set token type
Browse files Browse the repository at this point in the history
  • Loading branch information
mihaicalinluca committed Dec 5, 2024
1 parent e8dfee4 commit 675066c
Show file tree
Hide file tree
Showing 8 changed files with 278 additions and 41 deletions.
26 changes: 12 additions & 14 deletions framework/base/src/contract_base/wrappers/send_wrapper.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
use core::marker::PhantomData;

use multiversx_chain_core::types::EsdtTokenType;

use crate::codec::Empty;

use crate::types::ManagedRef;
use crate::types::{ManagedRef, SystemSCAddress};
use crate::{
api::{BlockchainApi, CallTypeApi, StorageReadApi},
codec,
Expand Down Expand Up @@ -55,7 +53,7 @@ where
self.esdt_system_sc_tx()
}

/// Prepares a proxy object to call the system SC.
/// Prepares a proxy object to call the ESDT system SC.
/// It has the destination address set, as well as the contract type (as specified in the proxy).
pub fn esdt_system_sc_tx(
&self,
Expand All @@ -65,6 +63,16 @@ where
.typed(system_proxy::ESDTSystemSCProxy)
}

/// Prepares a proxy object to call the system SC.
/// It has the destination address set, as well as the contract type (as specified in the proxy).
pub fn system_sc_tx(
&self,
) -> system_proxy::SystemSCProxyMethods<TxScEnv<A>, (), SystemSCAddress, ()> {
Tx::new_tx_from_sc()
.to(SystemSCAddress)
.typed(system_proxy::SystemSCProxy)
}

/// Convenient way to quickly instance a minimal contract call (with no EGLD, no arguments, etc.)
///
/// You can further configure this contract call by chaining methods to it.
Expand Down Expand Up @@ -766,16 +774,6 @@ where
.sync_call()
}

/// Sets the token type for a specific token.
pub fn esdt_set_token_type(&self, token_id: &TokenIdentifier<A>, token_type: EsdtTokenType) {
Tx::new_tx_from_sc()
.to(ToSelf)
.gas(GasLeft)
.typed(system_proxy::UserBuiltinProxy)
.esdt_set_token_type(token_id, token_type)
.sync_call()
}

/// Modifies royalties for a specific token.
pub fn esdt_modify_royalties(
&self,
Expand Down
2 changes: 2 additions & 0 deletions framework/base/src/types/interaction/markers.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
mod esdt_system_sc_address;
mod gas_left;
mod system_sc_address;
mod to_caller;
mod to_self;

pub use esdt_system_sc_address::ESDTSystemSCAddress;
pub use gas_left::GasLeft;
pub use system_sc_address::SystemSCAddress;
pub use to_caller::ToCaller;
pub use to_self::ToSelf;
75 changes: 75 additions & 0 deletions framework/base/src/types/interaction/markers/system_sc_address.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
use hex_literal::hex;
use multiversx_chain_core::types::Address;
use multiversx_sc_codec::{EncodeErrorHandler, TopEncode, TopEncodeOutput};

use crate::{
abi::TypeAbiFrom,
api::ManagedTypeApi,
types::{AnnotatedValue, ManagedAddress, ManagedBuffer, TxEnv, TxTo, TxToSpecified},
};

/// Address of the system smart contract that manages ESDT.
const SYSTEM_SC_ADDRESS_BYTES: [u8; 32] =
hex!("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01");
const SYSTEM_SC_ADDRESS_BECH32: &str =
"erd1llllllllllllllllllllllllllllllllllllllllllllllllluqsl6e366";
const SYSTEM_SC_ADDRESS_ANNOTATION: &str =
"bech32:erd1llllllllllllllllllllllllllllllllllllllllllllllllluqsl6e366";

/// Indicates the system SC address, which is the same on any MultiversX blockchain.
pub struct SystemSCAddress;

impl SystemSCAddress {
pub fn to_managed_address<Api>(self) -> ManagedAddress<Api>
where
Api: ManagedTypeApi,
{
ManagedAddress::from(SYSTEM_SC_ADDRESS_BYTES)
}

pub fn to_address(&self) -> Address {
SYSTEM_SC_ADDRESS_BYTES.into()
}

pub fn to_bech32_str(&self) -> &str {
SYSTEM_SC_ADDRESS_BECH32
}

pub fn to_bech32_string(&self) -> alloc::string::String {
SYSTEM_SC_ADDRESS_BECH32.into()
}
}

impl<Env> AnnotatedValue<Env, ManagedAddress<Env::Api>> for SystemSCAddress
where
Env: TxEnv,
{
fn annotation(&self, _env: &Env) -> ManagedBuffer<Env::Api> {
ManagedBuffer::from(SYSTEM_SC_ADDRESS_ANNOTATION)
}

fn to_value(&self, _env: &Env) -> ManagedAddress<Env::Api> {
SystemSCAddress.to_managed_address()
}
}

impl<Env> TxTo<Env> for SystemSCAddress where Env: TxEnv {}
impl<Env> TxToSpecified<Env> for SystemSCAddress where Env: TxEnv {}

impl TopEncode for SystemSCAddress {
fn top_encode_or_handle_err<O, H>(&self, output: O, h: H) -> Result<(), H::HandledErr>
where
O: TopEncodeOutput,
H: EncodeErrorHandler,
{
SYSTEM_SC_ADDRESS_BYTES.top_encode_or_handle_err(output, h)
}
}

impl<M> TypeAbiFrom<SystemSCAddress> for ManagedAddress<M> where M: ManagedTypeApi {}

impl core::fmt::Display for SystemSCAddress {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str(SYSTEM_SC_ADDRESS_BECH32)
}
}
2 changes: 2 additions & 0 deletions framework/base/src/types/interaction/system_proxy.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
mod builtin_func_proxy;
mod esdt_system_sc_proxy;
mod legacy_system_sc_proxy;
mod system_sc_proxy;
pub(crate) mod token_properties;

pub use builtin_func_proxy::*;
pub use esdt_system_sc_proxy::{ESDTSystemSCProxy, ESDTSystemSCProxyMethods, IssueCall};
pub use legacy_system_sc_proxy::ESDTSystemSmartContractProxy;
pub use system_sc_proxy::{SystemSCProxy, SystemSCProxyMethods};
pub use token_properties::*;
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use multiversx_sc_codec::{Empty, TopEncode};

use crate::types::{
BigUint, EsdtTokenType, ManagedAddress, ManagedBuffer, ManagedVec, NotPayable, ProxyArg,
TokenIdentifier, Tx, TxEnv, TxFrom, TxGas, TxProxyTrait, TxTo, TxTypedCall,
BigUint, ManagedAddress, ManagedBuffer, ManagedVec, NotPayable, ProxyArg, TokenIdentifier, Tx,
TxEnv, TxFrom, TxGas, TxProxyTrait, TxTo, TxTypedCall,
};

use crate::chain_core::builtin_func_names::{
Expand All @@ -11,7 +11,7 @@ use crate::chain_core::builtin_func_names::{
ESDT_METADATA_UPDATE_FUNC_NAME, ESDT_MODIFY_CREATOR_FUNC_NAME, ESDT_MODIFY_ROYALTIES_FUNC_NAME,
ESDT_NFT_ADD_QUANTITY_FUNC_NAME, ESDT_NFT_ADD_URI_FUNC_NAME, ESDT_NFT_BURN_FUNC_NAME,
ESDT_NFT_CREATE_FUNC_NAME, ESDT_NFT_UPDATE_ATTRIBUTES_FUNC_NAME, ESDT_SET_NEW_URIS_FUNC_NAME,
ESDT_SET_TOKEN_TYPE_FUNC_NAME, SET_USERNAME_FUNC_NAME,
SET_USERNAME_FUNC_NAME,
};

/// Proxy describing the user builtin function signatures.
Expand Down Expand Up @@ -217,24 +217,6 @@ where
tx.original_result()
}

pub fn esdt_set_token_type<
Arg0: ProxyArg<TokenIdentifier<Env::Api>>,
Arg1: ProxyArg<EsdtTokenType>,
>(
self,
token_id: Arg0,
token_type: Arg1,
) -> TxTypedCall<Env, From, To, NotPayable, Gas, ()> {
let tx = self
.wrapped_tx
.payment(NotPayable)
.raw_call(ESDT_SET_TOKEN_TYPE_FUNC_NAME)
.argument(&token_id)
.argument(&token_type);

tx.original_result()
}

pub fn esdt_modify_royalties<
Arg0: ProxyArg<TokenIdentifier<Env::Api>>,
Arg1: ProxyArg<u64>,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
use multiversx_chain_core::builtin_func_names::ESDT_SET_TOKEN_TYPE_FUNC_NAME;

use crate::types::{
EsdtTokenType, NotPayable, ProxyArg, TokenIdentifier, Tx, TxEnv, TxFrom, TxGas, TxProxyTrait,
TxTo, TxTypedCall,
};

/// Proxy for the system smart contract.
pub struct SystemSCProxy;

impl<Env, From, To, Gas> TxProxyTrait<Env, From, To, Gas> for SystemSCProxy
where
Env: TxEnv,
From: TxFrom<Env>,
To: TxTo<Env>,
Gas: TxGas<Env>,
{
type TxProxyMethods = SystemSCProxyMethods<Env, From, To, Gas>;

fn proxy_methods(self, tx: Tx<Env, From, To, (), Gas, (), ()>) -> Self::TxProxyMethods {
SystemSCProxyMethods { wrapped_tx: tx }
}
}

/// Method container of the ESDT system smart contract proxy.
pub struct SystemSCProxyMethods<Env, From, To, Gas>
where
Env: TxEnv,
From: TxFrom<Env>,
To: TxTo<Env>,
Gas: TxGas<Env>,
{
wrapped_tx: Tx<Env, From, To, (), Gas, (), ()>,
}

impl<Env, From, To, Gas> SystemSCProxyMethods<Env, From, To, Gas>
where
Env: TxEnv,
From: TxFrom<Env>,
To: TxTo<Env>,
Gas: TxGas<Env>,
{
/// Sets the token type for a specific token.
pub fn esdt_set_token_type<
Arg0: ProxyArg<TokenIdentifier<Env::Api>>,
Arg1: ProxyArg<EsdtTokenType>,
>(
self,
token_id: Arg0,
token_type: Arg1,
) -> TxTypedCall<Env, From, To, NotPayable, Gas, ()> {
let tx = self
.wrapped_tx
.payment(NotPayable)
.raw_call(ESDT_SET_TOKEN_TYPE_FUNC_NAME)
.argument(&token_id)
.argument(&token_type);

tx.original_result()
}
}
44 changes: 39 additions & 5 deletions tools/interactor-system-func-calls/src/system_sc_interact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ pub async fn system_sc_interact_cli() {
pub struct SysFuncCallsInteract {
interactor: Interactor,
wallet_address: Bech32Address,
other_wallet_address: Bech32Address,
#[allow(unused)]
state: State,
}
Expand All @@ -236,13 +237,15 @@ impl SysFuncCallsInteract {

interactor.set_current_dir_from_workspace("tools/interactor-system-func-calls");
let wallet_address = interactor.register_wallet(test_wallets::alice()).await;
let other_wallet_address = interactor.register_wallet(test_wallets::mike()).await;

// generate blocks until ESDTSystemSCAddress is enabled
interactor.generate_blocks_until_epoch(1).await.unwrap();

Self {
interactor,
wallet_address: wallet_address.into(),
other_wallet_address: other_wallet_address.into(),
state: State::load_state(),
}
}
Expand Down Expand Up @@ -426,6 +429,25 @@ impl SysFuncCallsInteract {
token_id
}

pub async fn set_roles_for_other(&mut self, token_id: &[u8], roles: Vec<EsdtLocalRole>) {
let wallet_address = &self.other_wallet_address.clone().into_address();
println!("Setting the following roles: {roles:?} for {token_id:?} for other_address");

self.interactor
.tx()
.from(&self.wallet_address)
.to(ESDTSystemSCAddress)
.gas(100_000_000u64)
.typed(ESDTSystemSCProxy)
.set_special_roles(
ManagedAddress::from_address(wallet_address),
TokenIdentifier::from(token_id),
roles.into_iter(),
)
.run()
.await;
}

pub async fn set_roles(&mut self, token_id: &[u8], roles: Vec<EsdtLocalRole>) {
let wallet_address = &self.wallet_address.clone().into_address();
println!("Setting the following roles: {roles:?} for {token_id:?}");
Expand Down Expand Up @@ -812,9 +834,9 @@ impl SysFuncCallsInteract {
self.interactor
.tx()
.from(&self.wallet_address)
.to(&self.wallet_address)
.to(SystemSCAddress)
.gas(100_000_000u64)
.typed(UserBuiltinProxy)
.typed(SystemSCProxy)
.esdt_set_token_type(token_id, token_type)
.run()
.await;
Expand Down Expand Up @@ -853,16 +875,28 @@ impl SysFuncCallsInteract {
.await;
}

pub async fn send_esdt(&mut self, token_id: &[u8], nonce: u64, amount: RustBigUint) {
println!("Sending token {token_id:?} with nonce {nonce:?} to other_wallet_address...");

self.interactor
.tx()
.from(&self.wallet_address)
.to(&self.other_wallet_address)
.single_esdt(&token_id.into(), nonce, &amount.into()) // .transfer()
.run()
.await;
}

// changes creator into caller
pub async fn modify_creator(&mut self, token_id: &[u8], nonce: u64) {
println!(
"Modifying the creator (into caller) for token {token_id:?} with nonce {nonce:?}..."
"Modifying the creator (into caller - other_wallet_address) for token {token_id:?} with nonce {nonce:?}..."
);

self.interactor
.tx()
.from(&self.wallet_address)
.to(&self.wallet_address)
.from(&self.other_wallet_address)
.to(&self.other_wallet_address)
.gas(100_000_000u64)
.typed(UserBuiltinProxy)
.esdt_nft_modify_creator(token_id, nonce)
Expand Down
Loading

0 comments on commit 675066c

Please sign in to comment.