From aa106c3319adae61c96115d4a6e95044931bc715 Mon Sep 17 00:00:00 2001 From: Yaroslav Bolyukin Date: Mon, 28 Jun 2021 15:20:05 +0000 Subject: [PATCH] feat: implement ERC721Burnable/Mintable interfaces --- --- 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 CollectionHandle { @@ -178,6 +182,91 @@ } } +#[solidity_interface(name = "ERC721Burnable")] +impl CollectionHandle { + fn burn(&mut self, caller: caller, token_id: uint256) -> Result { + let caller = T::CrossAccountId::from_eth(caller); + let token_id = token_id.try_into().map_err(|_| "amount overflow")?; + + >::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 CollectionHandle { + fn minting_finished(&self) -> Result { + Ok(false) + } + + fn mint(&mut self, caller: caller, to: address, token_id: uint256) -> Result { + 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 ::get(self.id) + .checked_add(1) + .ok_or("item id overflow")? + != token_id + { + return Err("item id should be next".into()); + } + + >::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 { + 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 ::get(self.id) + .checked_add(1) + .ok_or("item id overflow")? + != token_id + { + return Err("item id should be next".into()); + } + + >::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 { + Err("not implementable".into()) + } +} + #[solidity_interface(name = "ERC721UniqueExtensions")] impl CollectionHandle { #[solidity(rename_selector = "transfer")] @@ -196,6 +285,13 @@ .map_err(|_| "transfer error")?; Ok(()) } + + fn next_token_id(&self) -> Result { + 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 CollectionHandle {} --- a/pallets/nft/src/lib.rs +++ b/pallets/nft/src/lib.rs @@ -1251,6 +1251,10 @@ Self::can_create_items_in_collection(collection, sender, owner, 1)?; Self::validate_create_item_args(collection, &data)?; Self::create_item_no_validation(collection, owner, data)?; + + Ok(()) + } + pub fn transfer_internal( sender: &T::CrossAccountId, recipient: &T::CrossAccountId, @@ -1819,6 +1823,11 @@ >::remove(collection_id, item_id); >::remove(collection_id, item_id); + collection.log(ERC721Events::Transfer { + from: *item.owner.as_eth(), + to: H160::default(), + token_id: item_id.into(), + })?; Self::deposit_event(RawEvent::ItemDestroyed(collection.id, item_id)); Ok(()) } -- gitstuff