difftreelog
feat implement ERC721Burnable/Mintable interfaces
in: master
2 files changed
pallets/nft/src/eth/erc.rsdiffbeforeafterboth--- a/pallets/nft/src/eth/erc.rs
+++ b/pallets/nft/src/eth/erc.rs
@@ -1,12 +1,16 @@
use core::char::{decode_utf16, REPLACEMENT_CHARACTER};
use evm_coder::{ToLog, execution::Result, solidity, solidity_interface, types::*};
+use nft_data_structs::{CreateItemData, CreateNftData};
use core::convert::TryInto;
use alloc::format;
-use crate::{Allowances, Module, Balance, CollectionHandle, CollectionMode, Config, NftItemList};
-use frame_support::storage::StorageDoubleMap;
+use crate::{
+ Allowances, Module, Balance, CollectionHandle, CollectionMode, Config, NftItemList,
+ ItemListIndex,
+};
+use frame_support::storage::{StorageMap, StorageDoubleMap};
use pallet_evm::AddressMapping;
use super::account::CrossAccountId;
-use sp_std::vec::Vec;
+use sp_std::{vec, vec::Vec};
#[solidity_interface(name = "ERC165")]
impl<T: Config> CollectionHandle<T> {
@@ -178,6 +182,91 @@
}
}
+#[solidity_interface(name = "ERC721Burnable")]
+impl<T: Config> CollectionHandle<T> {
+ fn burn(&mut self, caller: caller, token_id: uint256) -> Result<void> {
+ let caller = T::CrossAccountId::from_eth(caller);
+ let token_id = token_id.try_into().map_err(|_| "amount overflow")?;
+
+ <Module<T>>::burn_item_internal(&caller, &self, token_id, 1).map_err(|_| "burn error")?;
+ Ok(())
+ }
+}
+
+#[derive(ToLog)]
+pub enum ERC721MintableEvents {
+ #[allow(dead_code)]
+ MintingFinished {},
+}
+
+#[solidity_interface(name = "ERC721Mintable", events(ERC721MintableEvents))]
+impl<T: Config> CollectionHandle<T> {
+ fn minting_finished(&self) -> Result<bool> {
+ Ok(false)
+ }
+
+ fn mint(&mut self, caller: caller, to: address, token_id: uint256) -> Result<bool> {
+ let caller = T::CrossAccountId::from_eth(caller);
+ let to = T::CrossAccountId::from_eth(to);
+ let token_id: u32 = token_id.try_into().map_err(|_| "amount overflow")?;
+ if <ItemListIndex>::get(self.id)
+ .checked_add(1)
+ .ok_or("item id overflow")?
+ != token_id
+ {
+ return Err("item id should be next".into());
+ }
+
+ <Module<T>>::create_item_internal(
+ &caller,
+ &self,
+ &to,
+ CreateItemData::NFT(CreateNftData {
+ const_data: vec![],
+ variable_data: vec![],
+ }),
+ )
+ .map_err(|_| "mint error")?;
+ Ok(true)
+ }
+
+ #[solidity(rename_selector = "mintWithTokenURI")]
+ fn mint_with_token_uri(
+ &mut self,
+ caller: caller,
+ to: address,
+ token_id: uint256,
+ token_uri: string,
+ ) -> Result<bool> {
+ let caller = T::CrossAccountId::from_eth(caller);
+ let to = T::CrossAccountId::from_eth(to);
+ let token_id: u32 = token_id.try_into().map_err(|_| "amount overflow")?;
+ if <ItemListIndex>::get(self.id)
+ .checked_add(1)
+ .ok_or("item id overflow")?
+ != token_id
+ {
+ return Err("item id should be next".into());
+ }
+
+ <Module<T>>::create_item_internal(
+ &caller,
+ &self,
+ &to,
+ CreateItemData::NFT(CreateNftData {
+ const_data: token_uri.into(),
+ variable_data: vec![],
+ }),
+ )
+ .map_err(|_| "mint error")?;
+ Ok(true)
+ }
+
+ fn finish_minting(&mut self, _caller: caller) -> Result<bool> {
+ Err("not implementable".into())
+ }
+}
+
#[solidity_interface(name = "ERC721UniqueExtensions")]
impl<T: Config> CollectionHandle<T> {
#[solidity(rename_selector = "transfer")]
@@ -196,6 +285,13 @@
.map_err(|_| "transfer error")?;
Ok(())
}
+
+ fn next_token_id(&self) -> Result<uint256> {
+ Ok(ItemListIndex::get(self.id)
+ .checked_add(1)
+ .ok_or("item id overflow")?
+ .into())
+ }
}
#[solidity_interface(
@@ -205,7 +301,9 @@
ERC721,
ERC721Metadata,
ERC721Enumerable,
- ERC721UniqueExtensions
+ ERC721UniqueExtensions,
+ ERC721Mintable,
+ ERC721Burnable,
)
)]
impl<T: Config> CollectionHandle<T> {}
pallets/nft/src/lib.rsdiffbeforeafterboth1236 }1236 }1237}1237}123812381239impl<T: Config> Module<T> {1239impl<T: Config> Module<T> {1240 pub fn create_item_internal(1240 pub fn create_item_internal(1241 sender: &T::CrossAccountId,1241 sender: &T::CrossAccountId,1242 collection: &CollectionHandle<T>,1242 collection: &CollectionHandle<T>,1243 owner: &T::CrossAccountId,1243 owner: &T::CrossAccountId,1244 data: CreateItemData,1244 data: CreateItemData,1245 ) -> DispatchResult {1245 ) -> DispatchResult {1246 ensure!(1246 ensure!(1247 owner != &T::CrossAccountId::from_eth(H160([0; 20])),1247 owner != &T::CrossAccountId::from_eth(H160([0; 20])),1248 Error::<T>::AddressIsZero1248 Error::<T>::AddressIsZero1249 );1249 );125012501251 Self::can_create_items_in_collection(collection, sender, owner, 1)?;1251 Self::can_create_items_in_collection(collection, sender, owner, 1)?;1252 Self::validate_create_item_args(collection, &data)?;1252 Self::validate_create_item_args(collection, &data)?;1253 Self::create_item_no_validation(collection, owner, data)?;1253 Self::create_item_no_validation(collection, owner, data)?;12541255 Ok(())1256 }12571254 pub fn transfer_internal(1258 pub fn transfer_internal(1255 sender: &T::CrossAccountId,1259 sender: &T::CrossAccountId,1819 <NftItemList<T>>::remove(collection_id, item_id);1823 <NftItemList<T>>::remove(collection_id, item_id);1820 <VariableMetaDataBasket<T>>::remove(collection_id, item_id);1824 <VariableMetaDataBasket<T>>::remove(collection_id, item_id);182118251826 collection.log(ERC721Events::Transfer {1827 from: *item.owner.as_eth(),1828 to: H160::default(),1829 token_id: item_id.into(),1830 })?;1822 Self::deposit_event(RawEvent::ItemDestroyed(collection.id, item_id));1831 Self::deposit_event(RawEvent::ItemDestroyed(collection.id, item_id));1823 Ok(())1832 Ok(())1824 }1833 }2328 }2337 }2329}2338}233023392331sp_api::decl_runtime_apis! {2340sp_api::decl_runtime_apis! {2332 pub trait NftApi {2341 pub trait NftApi {2333 /// Used for ethereum integration2342 /// Used for ethereum integration2334 fn eth_contract_code(account: H160) -> Option<Vec<u8>>;2343 fn eth_contract_code(account: H160) -> Option<Vec<u8>>;2335 }2344 }2336}2345}23372346