Skip to content

Commit 5087df0

Browse files
Merge pull request #2281 from XOXNO/feat/built_in_functions_nft_update
Add ESDT metadata recreate and update mock functions
2 parents d8f980b + 0376f8c commit 5087df0

File tree

4 files changed

+194
-2
lines changed

4 files changed

+194
-2
lines changed

chain/vm/src/builtin_functions/builtin_func_container.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ use super::{
22
BuiltinFunctionEsdtTransferInfo,
33
builtin_func_trait::BuiltinFunction,
44
esdt_nft::{
5-
ESDTLocalBurn, ESDTLocalMint, ESDTNftAddQuantity, ESDTNftAddUri, ESDTNftBurn,
6-
ESDTNftCreate, ESDTNftUpdateAttributes,
5+
ESDTLocalBurn, ESDTLocalMint, ESDTMetadataRecreate, ESDTMetadataUpdate, ESDTNftAddQuantity,
6+
ESDTNftAddUri, ESDTNftBurn, ESDTNftCreate, ESDTNftUpdateAttributes,
77
},
88
general::{ChangeOwner, ClaimDeveloperRewards, DeleteUsername, SetUsername, UpgradeContract},
99
transfer::{ESDTMultiTransfer, ESDTNftTransfer, ESDTTransfer},
@@ -106,6 +106,12 @@ impl<'a> BuiltinFunctionCall<'a> {
106106
ESDTNftUpdateAttributes,
107107
f,
108108
),
109+
ESDT_METADATA_RECREATE_FUNC_NAME => {
110+
self.check_role_and_execute(EsdtLocalRole::NftRecreate, ESDTMetadataRecreate, f)
111+
}
112+
ESDT_METADATA_UPDATE_FUNC_NAME => {
113+
self.check_role_and_execute(EsdtLocalRole::NftRecreate, ESDTMetadataUpdate, f)
114+
}
109115

110116
ESDT_MULTI_TRANSFER_FUNC_NAME => self.execute_bf(ESDTMultiTransfer, f),
111117
ESDT_NFT_TRANSFER_FUNC_NAME => self.execute_bf(ESDTNftTransfer, f),
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
use multiversx_chain_core::types::ReturnCode;
2+
3+
use crate::{
4+
blockchain::state::EsdtInstanceMetadata,
5+
chain_core::builtin_func_names::ESDT_METADATA_RECREATE_FUNC_NAME,
6+
host::context::{BlockchainUpdate, TxCache, TxInput, TxLog, TxResult},
7+
host::runtime::{RuntimeInstanceCallLambda, RuntimeRef},
8+
types::{top_decode_u64, top_encode_u64},
9+
};
10+
11+
use super::super::builtin_func_trait::BuiltinFunction;
12+
13+
pub struct ESDTMetadataRecreate;
14+
15+
impl BuiltinFunction for ESDTMetadataRecreate {
16+
fn name(&self) -> &str {
17+
ESDT_METADATA_RECREATE_FUNC_NAME
18+
}
19+
20+
fn execute<F>(
21+
&self,
22+
tx_input: TxInput,
23+
tx_cache: TxCache,
24+
_runtime: &RuntimeRef,
25+
_f: F,
26+
) -> (TxResult, BlockchainUpdate)
27+
where
28+
F: RuntimeInstanceCallLambda,
29+
{
30+
if tx_input.args.len() < 6 {
31+
let err_result = TxResult::from_vm_error("ESDTMetaDataRecreate too few arguments");
32+
return (err_result, BlockchainUpdate::empty());
33+
}
34+
assert!(
35+
tx_input.to == tx_input.from,
36+
"ESDTMetaDataRecreate expects that to == from"
37+
);
38+
39+
let token_identifier = tx_input.args[0].as_slice();
40+
let nonce = top_decode_u64(tx_input.args[1].as_slice());
41+
let name = tx_input.args[2].clone();
42+
let royalties = top_decode_u64(tx_input.args[3].as_slice());
43+
let hash = tx_input.args[4].clone();
44+
let attributes = tx_input.args[5].clone();
45+
let uris = tx_input.args[6..].to_vec();
46+
47+
tx_cache.with_account_mut(&tx_input.from, |account| {
48+
let esdt_data = account
49+
.esdt
50+
.get_mut_by_identifier(token_identifier)
51+
.unwrap_or_else(|| panic!("ESDTMetaDataRecreate: token not found"));
52+
53+
let instance = esdt_data
54+
.instances
55+
.get_mut_by_nonce(nonce)
56+
.unwrap_or_else(|| panic!("ESDTMetaDataRecreate: nonce not found"));
57+
58+
// Recreate replaces all metadata fields unconditionally.
59+
instance.metadata = EsdtInstanceMetadata {
60+
name,
61+
creator: instance.metadata.creator.clone(),
62+
royalties,
63+
hash: Some(hash),
64+
uri: uris,
65+
attributes,
66+
};
67+
});
68+
69+
let esdt_metadata_recreate_log = TxLog {
70+
address: tx_input.from,
71+
endpoint: ESDT_METADATA_RECREATE_FUNC_NAME.into(),
72+
topics: vec![
73+
token_identifier.to_vec(),
74+
top_encode_u64(nonce),
75+
Vec::new(), // value = 0
76+
],
77+
data: vec![],
78+
};
79+
80+
let tx_result = TxResult {
81+
result_status: ReturnCode::Success,
82+
result_logs: vec![esdt_metadata_recreate_log],
83+
..Default::default()
84+
};
85+
86+
(tx_result, tx_cache.into_blockchain_updates())
87+
}
88+
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
use multiversx_chain_core::types::ReturnCode;
2+
3+
use crate::{
4+
chain_core::builtin_func_names::ESDT_METADATA_UPDATE_FUNC_NAME,
5+
host::context::{BlockchainUpdate, TxCache, TxInput, TxLog, TxResult},
6+
host::runtime::{RuntimeInstanceCallLambda, RuntimeRef},
7+
types::{top_decode_u64, top_encode_u64},
8+
};
9+
10+
use super::super::builtin_func_trait::BuiltinFunction;
11+
12+
pub struct ESDTMetadataUpdate;
13+
14+
impl BuiltinFunction for ESDTMetadataUpdate {
15+
fn name(&self) -> &str {
16+
ESDT_METADATA_UPDATE_FUNC_NAME
17+
}
18+
19+
fn execute<F>(
20+
&self,
21+
tx_input: TxInput,
22+
tx_cache: TxCache,
23+
_runtime: &RuntimeRef,
24+
_f: F,
25+
) -> (TxResult, BlockchainUpdate)
26+
where
27+
F: RuntimeInstanceCallLambda,
28+
{
29+
if tx_input.args.len() < 6 {
30+
let err_result = TxResult::from_vm_error("ESDTMetaDataUpdate too few arguments");
31+
return (err_result, BlockchainUpdate::empty());
32+
}
33+
assert!(
34+
tx_input.to == tx_input.from,
35+
"ESDTMetaDataUpdate expects that to == from"
36+
);
37+
38+
let token_identifier = tx_input.args[0].as_slice();
39+
let nonce = top_decode_u64(tx_input.args[1].as_slice());
40+
let name = tx_input.args[2].clone();
41+
let royalties = top_decode_u64(tx_input.args[3].as_slice());
42+
let hash = tx_input.args[4].clone();
43+
let attributes = tx_input.args[5].clone();
44+
let uris = tx_input.args[6..].to_vec();
45+
46+
tx_cache.with_account_mut(&tx_input.from, |account| {
47+
let esdt_data = account
48+
.esdt
49+
.get_mut_by_identifier(token_identifier)
50+
.unwrap_or_else(|| panic!("ESDTMetaDataUpdate: token not found"));
51+
52+
let instance = esdt_data
53+
.instances
54+
.get_mut_by_nonce(nonce)
55+
.unwrap_or_else(|| panic!("ESDTMetaDataUpdate: nonce not found"));
56+
57+
// Update only overwrites non-empty fields (merge semantics).
58+
if !name.is_empty() {
59+
instance.metadata.name = name;
60+
}
61+
if royalties > 0 {
62+
instance.metadata.royalties = royalties;
63+
}
64+
if !hash.is_empty() {
65+
instance.metadata.hash = Some(hash);
66+
}
67+
if !attributes.is_empty() {
68+
instance.metadata.attributes = attributes;
69+
}
70+
if !uris.is_empty() {
71+
instance.metadata.uri = uris;
72+
}
73+
});
74+
75+
let esdt_metadata_update_log = TxLog {
76+
address: tx_input.from,
77+
endpoint: ESDT_METADATA_UPDATE_FUNC_NAME.into(),
78+
topics: vec![
79+
token_identifier.to_vec(),
80+
top_encode_u64(nonce),
81+
Vec::new(), // value = 0
82+
],
83+
data: vec![],
84+
};
85+
86+
let tx_result = TxResult {
87+
result_status: ReturnCode::Success,
88+
result_logs: vec![esdt_metadata_update_log],
89+
..Default::default()
90+
};
91+
92+
(tx_result, tx_cache.into_blockchain_updates())
93+
}
94+
}

chain/vm/src/builtin_functions/esdt_nft/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
mod esdt_local_burn;
22
mod esdt_local_mint;
3+
mod esdt_metadata_recreate_mock;
4+
mod esdt_metadata_update_mock;
35
mod esdt_nft_add_quantity_mock;
46
mod esdt_nft_add_uri_mock;
57
mod esdt_nft_burn_mock;
@@ -8,6 +10,8 @@ mod esdt_nft_update_attributes_mock;
810

911
pub use esdt_local_burn::*;
1012
pub use esdt_local_mint::*;
13+
pub use esdt_metadata_recreate_mock::*;
14+
pub use esdt_metadata_update_mock::*;
1115
pub use esdt_nft_add_quantity_mock::*;
1216
pub use esdt_nft_add_uri_mock::*;
1317
pub use esdt_nft_burn_mock::*;

0 commit comments

Comments
 (0)