difftreelog
feat add a way to split RFT between multiple owners on mint
in: master
12 files changed
pallets/common/src/eth.rsdiffbeforeafterboth632 }632 }633}633}634635/// Token minting parameters636#[derive(AbiCoder, Default, Debug)]637pub struct MintTokenData {638 /// Minted token owner639 pub owner: CrossAddress,640 /// Minted token properties641 pub properties: Vec<Property>,642}643634pallets/nonfungible/src/erc.rsdiffbeforeafterboth26 char::{REPLACEMENT_CHARACTER, decode_utf16},26 char::{REPLACEMENT_CHARACTER, decode_utf16},27 convert::TryInto,27 convert::TryInto,28};28};29use evm_coder::{abi::AbiType, ToLog, generate_stubgen, solidity_interface, types::*};29use evm_coder::{abi::AbiType, AbiCoder, ToLog, generate_stubgen, solidity_interface, types::*};30use frame_support::BoundedVec;30use frame_support::BoundedVec;31use up_data_structs::{31use up_data_structs::{32 TokenId, PropertyPermission, PropertyKeyPermission, Property, CollectionId, PropertyKey,32 TokenId, PropertyPermission, PropertyKeyPermission, Property, CollectionId, PropertyKey,64 },64 },65}65}6667/// Token minting parameters68#[derive(AbiCoder, Default, Debug)]69pub struct MintTokenData {70 /// Minted token owner71 pub owner: eth::CrossAddress,72 /// Minted token properties73 pub properties: Vec<eth::Property>,74}667567frontier_contract! {76frontier_contract! {68 macro_rules! NonfungibleHandle_result {...}77 macro_rules! NonfungibleHandle_result {...}984 /// @notice Function to mint a token.993 /// @notice Function to mint a token.985 /// @param data Array of pairs of token owner and token's properties for minted token994 /// @param data Array of pairs of token owner and token's properties for minted token986 #[weight(<SelfWeightOf<T>>::create_multiple_items(data.len() as u32) + <SelfWeightOf<T>>::set_token_properties(data.len() as u32))]995 #[weight(<SelfWeightOf<T>>::create_multiple_items(data.len() as u32) + <SelfWeightOf<T>>::set_token_properties(data.len() as u32))]987 fn mint_bulk_cross(&mut self, caller: Caller, data: Vec<eth::MintTokenData>) -> Result<bool> {996 fn mint_bulk_cross(&mut self, caller: Caller, data: Vec<MintTokenData>) -> Result<bool> {988 let caller = T::CrossAccountId::from_eth(caller);997 let caller = T::CrossAccountId::from_eth(caller);989 let budget = self998 let budget = self990 .recorder999 .recorder991 .weight_calls_budget(<StructureWeight<T>>::find_parent());1000 .weight_calls_budget(<StructureWeight<T>>::find_parent());9921001993 let mut create_nft_data = Vec::with_capacity(data.len());1002 let mut create_nft_data = Vec::with_capacity(data.len());994 for eth::MintTokenData { owner, properties } in data {1003 for MintTokenData { owner, properties } in data {995 let owner = owner.into_sub_cross_account::<T>()?;1004 let owner = owner.into_sub_cross_account::<T>()?;996 create_nft_data.push(CreateItemData::<T> {1005 create_nft_data.push(CreateItemData::<T> {997 properties: properties1006 properties: propertiespallets/nonfungible/src/stubs/UniqueNFT.rawdiffbeforeafterbothbinary blob — no preview
pallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth1055 string uri;1055 string uri;1056}1056}105710571058/// Token minting parameters1058struct MintTokenData {1059struct MintTokenData {1060 /// Minted token owner1059 CrossAddress owner;1061 CrossAddress owner;1062 /// Minted token properties1060 Property[] properties;1063 Property[] properties;1061}1064}10621065pallets/refungible/src/erc.rsdiffbeforeafterboth26 char::{REPLACEMENT_CHARACTER, decode_utf16},26 char::{REPLACEMENT_CHARACTER, decode_utf16},27 convert::TryInto,27 convert::TryInto,28};28};29use evm_coder::{abi::AbiType, ToLog, generate_stubgen, solidity_interface, types::*};29use evm_coder::{abi::AbiType, AbiCoder, ToLog, generate_stubgen, solidity_interface, types::*};30use frame_support::{BoundedBTreeMap, BoundedVec};30use frame_support::{BoundedBTreeMap, BoundedVec};31use pallet_common::{31use pallet_common::{32 CollectionHandle, CollectionPropertyPermissions, CommonCollectionOperations,32 CollectionHandle, CollectionPropertyPermissions, CommonCollectionOperations,71 },71 },72}72}7374/// Token minting parameters75#[derive(AbiCoder, Default, Debug)]76pub struct OwnerPieces {77 /// Minted token owner78 pub owner: eth::CrossAddress,79 /// Number of token pieces80 pub pieces: u128,81}8283/// Token minting parameters84#[derive(AbiCoder, Default, Debug)]85pub struct MintTokenData {86 /// Minted token owner and number of pieces87 pub owners: Vec<OwnerPieces>,88 /// Minted token properties89 pub properties: Vec<eth::Property>,90}739174/// @title A contract that allows to set and delete token properties and change token property permissions.92/// @title A contract that allows to set and delete token properties and change token property permissions.75#[solidity_interface(name = TokenProperties, events(ERC721TokenEvent), enum(derive(PreDispatch)), enum_attr(weight))]93#[solidity_interface(name = TokenProperties, events(ERC721TokenEvent), enum(derive(PreDispatch)), enum_attr(weight))]1027 fn mint_bulk_cross(1045 fn mint_bulk_cross(1028 &mut self,1046 &mut self,1029 caller: Caller,1047 caller: Caller,1030 token_properties: Vec<eth::MintTokenData>,1048 token_properties: Vec<MintTokenData>,1031 ) -> Result<bool> {1049 ) -> Result<bool> {1032 let caller = T::CrossAccountId::from_eth(caller);1050 let caller = T::CrossAccountId::from_eth(caller);1033 let budget = self1051 let budget = self1034 .recorder1052 .recorder1035 .weight_calls_budget(<StructureWeight<T>>::find_parent());1053 .weight_calls_budget(<StructureWeight<T>>::find_parent());103610541037 let mut create_rft_data = Vec::with_capacity(token_properties.len());1055 let mut create_rft_data = Vec::with_capacity(token_properties.len());1038 for eth::MintTokenData { owner, properties } in token_properties {1056 for MintTokenData { owners, properties } in token_properties {1039 let owner = owner.into_sub_cross_account::<T>()?;1040 let users: BoundedBTreeMap<_, _, _> = [(owner, 1)]1057 let users: BoundedBTreeMap<_, _, _> = owners1041 .into_iter()1058 .into_iter()1059 .map(|data| Ok((data.owner.into_sub_cross_account::<T>()?, data.pieces)))1042 .collect::<BTreeMap<_, _>>()1060 .collect::<Result<BTreeMap<_, _>>>()?1043 .try_into()1061 .try_into()1044 .map_err(|_| "too many users")?;1062 .map_err(|_| "too many users")?;1045 create_rft_data.push(CreateItemData::<T> {1063 create_rft_data.push(CreateItemData::<T> {pallets/refungible/src/stubs/UniqueRefungible.rawdiffbeforeafterbothbinary blob — no preview
pallets/refungible/src/stubs/UniqueRefungible.soldiffbeforeafterboth800}800}801801802/// @title Unique extensions for ERC721.802/// @title Unique extensions for ERC721.803/// @dev the ERC-165 identifier for this interface is 0x3e828d60803/// @dev the ERC-165 identifier for this interface is 0x4abaabdb804contract ERC721UniqueExtensions is Dummy, ERC165 {804contract ERC721UniqueExtensions is Dummy, ERC165 {805 /// @notice A descriptive name for a collection of NFTs in this contract805 /// @notice A descriptive name for a collection of NFTs in this contract806 /// @dev EVM selector for this function is: 0x06fdde03,806 /// @dev EVM selector for this function is: 0x06fdde03,988988989 /// @notice Function to mint a token.989 /// @notice Function to mint a token.990 /// @param tokenProperties Properties of minted token990 /// @param tokenProperties Properties of minted token991 /// @dev EVM selector for this function is: 0xab427b0c,991 /// @dev EVM selector for this function is: 0xdf7a5db7,992 /// or in textual repr: mintBulkCross(((address,uint256),(string,bytes)[])[])992 /// or in textual repr: mintBulkCross((((address,uint256),uint128)[],(string,bytes)[])[])993 function mintBulkCross(MintTokenData[] memory tokenProperties) public returns (bool) {993 function mintBulkCross(MintTokenData[] memory tokenProperties) public returns (bool) {994 require(false, stub_error);994 require(false, stub_error);995 tokenProperties;995 tokenProperties;1056 string uri;1056 string uri;1057}1057}105810581059/// Token minting parameters1059struct MintTokenData {1060struct MintTokenData {1061 /// Minted token owner and number of pieces1060 CrossAddress owner;1062 OwnerPieces[] owners;1063 /// Minted token properties1061 Property[] properties;1064 Property[] properties;1062}1065}10661067/// Token minting parameters1068struct OwnerPieces {1069 /// Minted token owner1070 CrossAddress owner;1071 /// Number of token pieces1072 uint128 pieces;1073}106310741064/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension1075/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension1065/// @dev See https://eips.ethereum.org/EIPS/eip-7211076/// @dev See https://eips.ethereum.org/EIPS/eip-721tests/src/eth/abi/reFungible.jsondiffbeforeafterboth451 "inputs": [451 "inputs": [452 {452 {453 "components": [453 "components": [454 {455 "components": [454 {456 {455 "components": [457 "components": [456 { "internalType": "address", "name": "eth", "type": "address" },458 {459 "internalType": "struct CrossAddress",469 "internalType": "struct CrossAddress",460 "name": "owner",470 "name": "owner",461 "type": "tuple"471 "type": "tuple"462 },472 },473 { "internalType": "uint128", "name": "pieces", "type": "uint128" }474 ],475 "internalType": "struct OwnerPieces[]",476 "name": "owners",477 "type": "tuple[]"478 },463 {479 {464 "components": [480 "components": [465 { "internalType": "string", "name": "key", "type": "string" },481 { "internalType": "string", "name": "key", "type": "string" },tests/src/eth/api/UniqueNFT.soldiffbeforeafterboth711 string uri;711 string uri;712}712}713713714/// Token minting parameters714struct MintTokenData {715struct MintTokenData {716 /// Minted token owner715 CrossAddress owner;717 CrossAddress owner;718 /// Minted token properties716 Property[] properties;719 Property[] properties;717}720}718721tests/src/eth/api/UniqueRefungible.soldiffbeforeafterboth551}551}552552553/// @title Unique extensions for ERC721.553/// @title Unique extensions for ERC721.554/// @dev the ERC-165 identifier for this interface is 0x3e828d60554/// @dev the ERC-165 identifier for this interface is 0x4abaabdb555interface ERC721UniqueExtensions is Dummy, ERC165 {555interface ERC721UniqueExtensions is Dummy, ERC165 {556 /// @notice A descriptive name for a collection of NFTs in this contract556 /// @notice A descriptive name for a collection of NFTs in this contract557 /// @dev EVM selector for this function is: 0x06fdde03,557 /// @dev EVM selector for this function is: 0x06fdde03,670670671 /// @notice Function to mint a token.671 /// @notice Function to mint a token.672 /// @param tokenProperties Properties of minted token672 /// @param tokenProperties Properties of minted token673 /// @dev EVM selector for this function is: 0xab427b0c,673 /// @dev EVM selector for this function is: 0xdf7a5db7,674 /// or in textual repr: mintBulkCross(((address,uint256),(string,bytes)[])[])674 /// or in textual repr: mintBulkCross((((address,uint256),uint128)[],(string,bytes)[])[])675 function mintBulkCross(MintTokenData[] memory tokenProperties) external returns (bool);675 function mintBulkCross(MintTokenData[] memory tokenProperties) external returns (bool);676676677 // /// @notice Function to mint multiple tokens with the given tokenUris.677 // /// @notice Function to mint multiple tokens with the given tokenUris.712 string uri;712 string uri;713}713}714714715/// Token minting parameters715struct MintTokenData {716struct MintTokenData {717 /// Minted token owner and number of pieces716 CrossAddress owner;718 OwnerPieces[] owners;719 /// Minted token properties717 Property[] properties;720 Property[] properties;718}721}722723/// Token minting parameters724struct OwnerPieces {725 /// Minted token owner726 CrossAddress owner;727 /// Number of token pieces728 uint128 pieces;729}719730720/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension731/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension721/// @dev See https://eips.ethereum.org/EIPS/eip-721732/// @dev See https://eips.ethereum.org/EIPS/eip-721tests/src/eth/nonFungible.test.tsdiffbeforeafterboth216 name: 'A',216 name: 'A',217 description: 'B',217 description: 'B',218 tokenPrefix: 'C',218 tokenPrefix: 'C',219 collectionMode: 'rft',219 collectionMode: 'nft',220 adminList: [callerCross],220 adminList: [callerCross],221 tokenPropertyPermissions: [221 tokenPropertyPermissions: [222 {key: 'key_0_0', permissions},222 {key: 'key_0_0', permissions},tests/src/eth/reFungible.test.tsdiffbeforeafterboth131 const callerCross = helper.ethCrossAccount.fromAddress(caller);131 const callerCross = helper.ethCrossAccount.fromAddress(caller);132 const receiver = helper.eth.createAccount();132 const receiver = helper.eth.createAccount();133 const receiverCross = helper.ethCrossAccount.fromAddress(receiver);133 const receiverCross = helper.ethCrossAccount.fromAddress(receiver);134 const receiver2 = helper.eth.createAccount();135 const receiver2Cross = helper.ethCrossAccount.fromAddress(receiver2);134136135 const permissions = [137 const permissions = [136 {code: TokenPermissionField.Mutable, value: true},138 {code: TokenPermissionField.Mutable, value: true},157 },159 },158 ).send();160 ).send();159161160 const contract = await helper.ethNativeContract.collection(collectionAddress, 'nft', caller);162 const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', caller);161 {163 {162 const nextTokenId = await contract.methods.nextTokenId().call();164 const nextTokenId = await contract.methods.nextTokenId().call();163 expect(nextTokenId).to.be.equal('1');165 expect(nextTokenId).to.be.equal('1');164 const result = await contract.methods.mintBulkCross([166 const result = await contract.methods.mintBulkCross([165 {167 {168 owners: [{166 owner: receiverCross,169 owner: receiverCross,170 pieces: 1,171 }],167 properties: [172 properties: [168 {key: 'key_0_0', value: Buffer.from('value_0_0')},173 {key: 'key_0_0', value: Buffer.from('value_0_0')},169 ],174 ],170 },175 },171 {176 {177 owners: [{172 owner: receiverCross,178 owner: receiverCross,179 pieces: 2,180 }],173 properties: [181 properties: [174 {key: 'key_1_0', value: Buffer.from('value_1_0')},182 {key: 'key_1_0', value: Buffer.from('value_1_0')},175 {key: 'key_1_1', value: Buffer.from('value_1_1')},183 {key: 'key_1_1', value: Buffer.from('value_1_1')},176 ],184 ],177 },185 },178 {186 {187 owners: [188 {179 owner: receiverCross,189 owner: receiverCross,190 pieces: 1,191 },192 {193 owner: receiver2Cross,194 pieces: 2,195 },196 ],180 properties: [197 properties: [181 {key: 'key_2_0', value: Buffer.from('value_2_0')},198 {key: 'key_2_0', value: Buffer.from('value_2_0')},182 {key: 'key_2_1', value: Buffer.from('value_2_1')},199 {key: 'key_2_1', value: Buffer.from('value_2_1')},190 const event = events[i];207 const event = events[i];191 expect(event.address).to.equal(collectionAddress);208 expect(event.address).to.equal(collectionAddress);192 expect(event.returnValues.from).to.equal('0x0000000000000000000000000000000000000000');209 expect(event.returnValues.from).to.equal('0x0000000000000000000000000000000000000000');210 if(i == 0 || i == 1)193 expect(event.returnValues.to).to.equal(receiver);211 expect(event.returnValues.to).to.equal(receiver);212 else213 expect(event.returnValues.to).to.equal('0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF');214194 expect(event.returnValues.tokenId).to.equal(`${+nextTokenId + i}`);215 expect(event.returnValues.tokenId).to.equal(`${+nextTokenId + i}`);195 }216 }