-
Notifications
You must be signed in to change notification settings - Fork 99
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1100 from multiversx/system-sc
System SC mock
- Loading branch information
Showing
16 changed files
with
503 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,4 +5,4 @@ | |
state.toml | ||
|
||
# Trace file of interactor tooling | ||
interactor_trace.scen.json | ||
interactor*.scen.json |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
mod system_sc_issue; | ||
mod system_sc_special_roles; | ||
mod system_sc_unimplemented; | ||
|
||
use crate::{ | ||
tx_mock::{TxContext, TxResult}, | ||
types::VMAddress, | ||
}; | ||
use hex_literal::hex; | ||
use system_sc_issue::*; | ||
use system_sc_special_roles::*; | ||
use system_sc_unimplemented::*; | ||
|
||
/// Address of the system smart contract that manages ESDT. | ||
/// Bech32: erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u | ||
pub const ESDT_SYSTEM_SC_ADDRESS_ARRAY: [u8; 32] = | ||
hex!("000000000000000000010000000000000000000000000000000000000002ffff"); | ||
|
||
pub fn is_system_sc_address(address: &VMAddress) -> bool { | ||
address.as_array() == &ESDT_SYSTEM_SC_ADDRESS_ARRAY | ||
} | ||
|
||
pub fn execute_system_sc(tx_context: TxContext) -> (TxContext, TxResult) { | ||
let func_name = tx_context.tx_input_box.func_name.clone(); | ||
match func_name.as_str() { | ||
"issue" => issue(tx_context), | ||
"issueSemiFungible" => issue_semi_fungible(tx_context), | ||
"issueNonFungible" => issue_non_fungible(tx_context), | ||
"registerMetaESDT" => register_meta_esdt(tx_context), | ||
"changeSFTToMetaESDT" => change_sft_to_meta_esdt(tx_context), | ||
"registerAndSetAllRoles" => register_and_set_all_roles(), | ||
"ESDTBurn" => esdt_burn(tx_context), | ||
"mint" => mint(tx_context), | ||
"freeze" => freeze(tx_context), | ||
"unFreeze" => unfreeze(tx_context), | ||
"wipe" => wipe(tx_context), | ||
"pause" => pause(tx_context), | ||
"unPause" => unpause(tx_context), | ||
"freezeSingleNFT" => freeze_single_nft(tx_context), | ||
"unFreezeSingleNFT" => unfreeze_single_nft(tx_context), | ||
"wipeSingleNFT" => wipe_single_nft(tx_context), | ||
"claim" => claim(tx_context), | ||
"configChange" => config_change(tx_context), | ||
"controlChanges" => control_changes(tx_context), | ||
"transferOwnership" => transfer_ownership(tx_context), | ||
"getTokenProperties" => get_token_properties(tx_context), | ||
"getSpecialRoles" => get_special_roles(tx_context), | ||
"setSpecialRole" => set_special_role(tx_context), | ||
"unSetSpecialRole" => unset_special_role(tx_context), | ||
"transferNFTCreateRole" => transfer_nft_create_role(tx_context), | ||
"stopNFTCreate" => stop_nft_create(tx_context), | ||
"getAllAddressesAndRoles" => get_all_addresses_and_roles(tx_context), | ||
"getContractConfig" => get_contract_config(tx_context), | ||
"changeToMultiShardCreate" => change_to_multi_shard_create(tx_context), | ||
"setBurnRoleGlobally" => set_burn_role_globally(tx_context), | ||
"unsetBurnRoleGlobally" => unset_burn_role_globally(tx_context), | ||
"sendAllTransferRoleAddresses" => send_all_transfer_role_addresses(tx_context), | ||
invalid_func_name => panic!("invalid system SC function: {invalid_func_name}"), | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
use num_bigint::BigUint; | ||
|
||
use crate::{ | ||
crypto_functions::keccak256, | ||
tx_mock::{TxCache, TxContext, TxInput, TxResult}, | ||
types::top_decode_u64, | ||
}; | ||
|
||
/// Issues a new token. | ||
pub fn issue(tx_context: TxContext) -> (TxContext, TxResult) { | ||
let tx_input = tx_context.input_ref(); | ||
let tx_cache = tx_context.blockchain_cache(); | ||
let tx_result: TxResult; | ||
|
||
if tx_input.args.len() < 4 { | ||
tx_result = TxResult::from_vm_error("not enough arguments"); | ||
return (tx_context, tx_result); | ||
} | ||
let _name = tx_input.args[0].clone(); | ||
let ticker = tx_input.args[1].clone(); | ||
let _total_supply = BigUint::from_bytes_be(tx_input.args[2].clone().as_ref()); | ||
let _decimals = top_decode_u64(tx_input.args[3].clone().as_ref()) as u32; | ||
|
||
let mut new_token_identifiers = tx_cache.get_new_token_identifiers(); | ||
|
||
let token_identifier = if let Some((i, ti)) = | ||
first_token_identifier_with_ticker(&new_token_identifiers, &ticker) | ||
{ | ||
new_token_identifiers.remove(i); | ||
ti.into_bytes() | ||
} else { | ||
generate_token_identifier_from_ticker(tx_input, tx_cache, &ticker) | ||
}; | ||
|
||
println!( | ||
"\n\ngenerated new token_identifier: {}\n\n", | ||
std::str::from_utf8(&token_identifier).unwrap() | ||
); | ||
|
||
tx_cache.with_account_mut(&tx_input.from, |account| { | ||
account.esdt.issue_token(&token_identifier); | ||
}); | ||
tx_cache.set_new_token_identifiers(new_token_identifiers); | ||
|
||
tx_result = TxResult { | ||
result_values: vec![token_identifier], | ||
..Default::default() | ||
}; | ||
|
||
(tx_context, tx_result) | ||
} | ||
|
||
/// Issues a new semi-fungible token. | ||
pub fn issue_semi_fungible(tx_context: TxContext) -> (TxContext, TxResult) { | ||
issue_non_fungible(tx_context) | ||
} | ||
|
||
/// Issues a new non-fungible token. | ||
pub fn issue_non_fungible(tx_context: TxContext) -> (TxContext, TxResult) { | ||
let tx_input = tx_context.input_ref(); | ||
let tx_cache = tx_context.blockchain_cache(); | ||
let tx_result: TxResult; | ||
|
||
if tx_input.args.len() < 2 { | ||
tx_result = TxResult::from_vm_error("not enough arguments"); | ||
return (tx_context, tx_result); | ||
} | ||
let _name = tx_input.args[0].clone(); | ||
let ticker = tx_input.args[1].clone(); | ||
|
||
let mut new_token_identifiers = tx_cache.get_new_token_identifiers(); | ||
|
||
let token_identifier = if let Some((i, ti)) = | ||
first_token_identifier_with_ticker(&new_token_identifiers, &ticker) | ||
{ | ||
new_token_identifiers.remove(i); | ||
ti.into_bytes() | ||
} else { | ||
generate_token_identifier_from_ticker(tx_input, tx_cache, &ticker) | ||
}; | ||
|
||
tx_cache.with_account_mut(&tx_input.from, |account| { | ||
account.esdt.issue_token(&token_identifier); | ||
}); | ||
tx_cache.set_new_token_identifiers(new_token_identifiers); | ||
|
||
tx_result = TxResult { | ||
result_values: vec![token_identifier], | ||
..Default::default() | ||
}; | ||
|
||
(tx_context, tx_result) | ||
} | ||
|
||
fn first_token_identifier_with_ticker( | ||
token_identifiers: &[String], | ||
ticker: &[u8], | ||
) -> Option<(usize, String)> { | ||
let extract_ticker = | ||
|ti: &String| -> String { ti.split('-').map(|x| x.to_string()).next().unwrap() }; | ||
|
||
token_identifiers | ||
.iter() | ||
.position(|x| extract_ticker(x).as_bytes() == ticker) | ||
.map(|i| (i, token_identifiers[i].clone())) | ||
} | ||
|
||
fn generate_token_identifier_from_ticker( | ||
tx_input: &TxInput, | ||
tx_cache: &TxCache, | ||
ticker: &[u8], | ||
) -> Vec<u8> { | ||
let new_random_base = [ | ||
tx_input.from.as_bytes(), | ||
tx_cache | ||
.blockchain_ref() | ||
.current_block_info | ||
.block_random_seed | ||
.as_slice(), | ||
] | ||
.concat(); | ||
let new_random = keccak256(&new_random_base); | ||
let new_random_for_ticker = &new_random[..3]; | ||
|
||
let token_identifier = [ | ||
ticker, | ||
"-".as_bytes(), | ||
hex::encode(new_random_for_ticker).as_bytes(), | ||
] | ||
.concat(); | ||
|
||
token_identifier | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
|
||
#[test] | ||
fn test_first_token_identifier_with_ticker_ok() { | ||
let ticker = String::from("BBBB").into_bytes(); | ||
let new_token_indetifiers = vec![ | ||
"AAAA-0123".to_string(), | ||
"BBBB-4567".to_string(), | ||
"BBBB-0123".to_string(), | ||
"CCCC-4567".to_string(), | ||
]; | ||
|
||
let ti = first_token_identifier_with_ticker(&new_token_indetifiers, &ticker); | ||
let expected = b"BBBB-4567".as_slice(); | ||
assert_eq!(expected, ti.unwrap().1.into_bytes()); | ||
} | ||
|
||
#[test] | ||
fn test_first_token_identifier_with_ticker_is_none() { | ||
let ticker = String::from("BBBB").into_bytes(); | ||
let new_token_indetifiers = vec!["AAAA-0123".to_string()]; | ||
|
||
let i = first_token_identifier_with_ticker(&new_token_indetifiers, &ticker); | ||
let expected = None; | ||
assert_eq!(expected, i); | ||
} | ||
} |
Oops, something went wrong.