difftreelog
misk: Move TokenChanged event into ERC721 contracts
in: master
16 files changed
pallets/common/src/erc.rsdiffbeforeafterboth26};26};27use pallet_evm_coder_substrate::dispatch_to_evm;27use pallet_evm_coder_substrate::dispatch_to_evm;28use sp_std::{vec, vec::Vec};28use sp_std::{vec, vec::Vec};29use sp_core::U256;30use up_data_structs::{29use up_data_structs::{31 CollectionMode, CollectionPermissions, OwnerRestrictedSet, Property, SponsoringRateLimit,30 CollectionMode, CollectionPermissions, OwnerRestrictedSet, Property, SponsoringRateLimit,32 SponsorshipState,31 SponsorshipState,67 collection_id: Address,66 collection_id: Address,68 },67 },6970 /// The token has been changed.71 TokenChanged {72 /// Collection ID.73 #[indexed]74 collection_id: Address,75 /// Token ID.76 token_id: U256,77 },78}68}796980/// Does not always represent a full collection, for RFT it is either70/// Does not always represent a full collection, for RFT it is eitherpallets/common/src/lib.rsdiffbeforeafterboth1250 mut stored_properties: Properties,1250 mut stored_properties: Properties,1251 is_token_owner: impl Fn() -> Result<bool, DispatchError>,1251 is_token_owner: impl Fn() -> Result<bool, DispatchError>,1252 set_token_properties: impl FnOnce(Properties),1252 set_token_properties: impl FnOnce(Properties),1253 log: evm_coder::ethereum::Log,1253 ) -> DispatchResult {1254 ) -> DispatchResult {1254 let is_collection_admin = collection.is_owner_or_admin(sender);1255 let is_collection_admin = collection.is_owner_or_admin(sender);1255 let permissions = Self::property_permissions(collection.id);1256 let permissions = Self::property_permissions(collection.id);1304 }1305 }1305 }1306 }130613071307 <PalletEvm<T>>::deposit_log(1308 <PalletEvm<T>>::deposit_log(log.clone());1308 CollectionHelpersEvents::TokenChanged {1309 collection_id: eth::collection_id_to_address(collection.id),1310 token_id: token_id.into(),1311 }1312 .to_log(T::ContractAddress::get()),1313 );1314 }1309 }13151310pallets/nonfungible/src/erc.rsdiffbeforeafterboth50 TokenProperties, SelfWeightOf, weights::WeightInfo,50 TokenProperties, SelfWeightOf, weights::WeightInfo,51};51};5253/// Nft events.54#[derive(ToLog)]55pub enum ERC721TokenEvent {56 /// The token has been changed.57 TokenChanged {58 /// Collection ID.59 #[indexed]60 collection_id: Address,61 /// Token ID.62 token_id: U256,63 },64}526553frontier_contract! {66frontier_contract! {54 macro_rules! NonfungibleHandle_result {...}67 macro_rules! NonfungibleHandle_result {...}55 impl<T: Config> Contract for NonfungibleHandle<T> {...}68 impl<T: Config> Contract for NonfungibleHandle<T> {...}56}69}577058/// @title A contract that allows to set and delete token properties and change token property permissions.71/// @title A contract that allows to set and delete token properties and change token property permissions.59#[solidity_interface(name = TokenProperties, enum(derive(PreDispatch)), enum_attr(weight))]72#[solidity_interface(name = TokenProperties, events(ERC721TokenEvent), enum(derive(PreDispatch)), enum_attr(weight))]60impl<T: Config> NonfungibleHandle<T> {73impl<T: Config> NonfungibleHandle<T> {61 /// @notice Set permissions for token property.74 /// @notice Set permissions for token property.62 /// @dev Throws error if `msg.sender` is not admin or owner of the collection.75 /// @dev Throws error if `msg.sender` is not admin or owner of the collection.pallets/nonfungible/src/lib.rsdiffbeforeafterboth112};112};113use pallet_structure::{Pallet as PalletStructure, Error as StructureError};113use pallet_structure::{Pallet as PalletStructure, Error as StructureError};114use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder};114use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder};115use sp_core::H160;115use sp_core::{Get, H160};116use sp_runtime::{ArithmeticError, DispatchError, DispatchResult, TransactionOutcome};116use sp_runtime::{ArithmeticError, DispatchError, DispatchResult, TransactionOutcome};117use sp_std::{vec::Vec, vec, collections::btree_map::BTreeMap};117use sp_std::{vec::Vec, vec, collections::btree_map::BTreeMap};118use core::ops::Deref;118use core::ops::Deref;622 stored_properties,622 stored_properties,623 is_token_owner,623 is_token_owner,624 |properties| <TokenProperties<T>>::set((collection.id, token_id), properties),624 |properties| <TokenProperties<T>>::set((collection.id, token_id), properties),625 erc::ERC721TokenEvent::TokenChanged {626 collection_id: collection_id_to_address(collection.id),627 token_id: token_id.into(),628 }629 .to_log(T::ContractAddress::get()),625 )630 )626 }631 }627632pallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth17 }17 }18}18}1920/// @dev inlined interface21contract ERC721TokenEvent {22 event TokenChanged(address indexed collectionId, uint256 tokenId);23}192420/// @title A contract that allows to set and delete token properties and change token property permissions.25/// @title A contract that allows to set and delete token properties and change token property permissions.21/// @dev the ERC-165 identifier for this interface is 0xde0695c226/// @dev the ERC-165 identifier for this interface is 0xde0695c222contract TokenProperties is Dummy, ERC165 {27contract TokenProperties is Dummy, ERC165, ERC721TokenEvent {23 // /// @notice Set permissions for token property.28 // /// @notice Set permissions for token property.24 // /// @dev Throws error if `msg.sender` is not admin or owner of the collection.29 // /// @dev Throws error if `msg.sender` is not admin or owner of the collection.25 // /// @param key Property key.30 // /// @param key Property key.pallets/refungible/src/erc.rsdiffbeforeafterboth595960pub const ADDRESS_FOR_PARTIALLY_OWNED_TOKENS: H160 = H160::repeat_byte(0xff);60pub const ADDRESS_FOR_PARTIALLY_OWNED_TOKENS: H160 = H160::repeat_byte(0xff);6162/// Rft events.63#[derive(ToLog)]64pub enum ERC721TokenEvent {65 /// The token has been changed.66 TokenChanged {67 /// Collection ID.68 #[indexed]69 collection_id: Address,70 /// Token ID.71 token_id: U256,72 },73}617462/// @title A contract that allows to set and delete token properties and change token property permissions.75/// @title A contract that allows to set and delete token properties and change token property permissions.63#[solidity_interface(name = TokenProperties, enum(derive(PreDispatch)), enum_attr(weight))]76#[solidity_interface(name = TokenProperties, events(ERC721TokenEvent), enum(derive(PreDispatch)), enum_attr(weight))]64impl<T: Config> RefungibleHandle<T> {77impl<T: Config> RefungibleHandle<T> {65 /// @notice Set permissions for token property.78 /// @notice Set permissions for token property.66 /// @dev Throws error if `msg.sender` is not admin or owner of the collection.79 /// @dev Throws error if `msg.sender` is not admin or owner of the collection.pallets/refungible/src/lib.rsdiffbeforeafterboth100 Event as CommonEvent, Pallet as PalletCommon,100 Event as CommonEvent, Pallet as PalletCommon,101};101};102use pallet_structure::Pallet as PalletStructure;102use pallet_structure::Pallet as PalletStructure;103use sp_core::H160;103use sp_core::{Get, H160};104use sp_runtime::{ArithmeticError, DispatchError, DispatchResult, TransactionOutcome};104use sp_runtime::{ArithmeticError, DispatchError, DispatchResult, TransactionOutcome};105use sp_std::{vec::Vec, vec, collections::btree_map::BTreeMap};105use sp_std::{vec::Vec, vec, collections::btree_map::BTreeMap};106use up_data_structs::{106use up_data_structs::{571 stored_properties,571 stored_properties,572 is_token_owner,572 is_token_owner,573 |properties| <TokenProperties<T>>::set((collection.id, token_id), properties),573 |properties| <TokenProperties<T>>::set((collection.id, token_id), properties),574 erc::ERC721TokenEvent::TokenChanged {575 collection_id: collection_id_to_address(collection.id),576 token_id: token_id.into(),577 }578 .to_log(T::ContractAddress::get()),574 )579 )575 }580 }576581pallets/refungible/src/stubs/UniqueRefungible.soldiffbeforeafterboth17 }17 }18}18}1920/// @dev inlined interface21contract ERC721TokenEvent {22 event TokenChanged(address indexed collectionId, uint256 tokenId);23}192420/// @title A contract that allows to set and delete token properties and change token property permissions.25/// @title A contract that allows to set and delete token properties and change token property permissions.21/// @dev the ERC-165 identifier for this interface is 0xde0695c226/// @dev the ERC-165 identifier for this interface is 0xde0695c222contract TokenProperties is Dummy, ERC165 {27contract TokenProperties is Dummy, ERC165, ERC721TokenEvent {23 // /// @notice Set permissions for token property.28 // /// @notice Set permissions for token property.24 // /// @dev Throws error if `msg.sender` is not admin or owner of the collection.29 // /// @dev Throws error if `msg.sender` is not admin or owner of the collection.25 // /// @param key Property key.30 // /// @param key Property key.pallets/unique/src/eth/stubs/CollectionHelpers.soldiffbeforeafterboth22 event CollectionCreated(address indexed owner, address indexed collectionId);22 event CollectionCreated(address indexed owner, address indexed collectionId);23 event CollectionDestroyed(address indexed collectionId);23 event CollectionDestroyed(address indexed collectionId);24 event CollectionChanged(address indexed collectionId);24 event CollectionChanged(address indexed collectionId);25 event TokenChanged(address indexed collectionId, uint256 tokenId);26}25}272628/// @title Contract, which allows users to operate with collections27/// @title Contract, which allows users to operate with collectionstests/src/eth/abi/collectionHelpers.jsondiffbeforeafterboth44 "name": "CollectionDestroyed",44 "name": "CollectionDestroyed",45 "type": "event"45 "type": "event"46 },46 },47 {48 "anonymous": false,49 "inputs": [50 {51 "indexed": true,52 "internalType": "address",53 "name": "collectionId",54 "type": "address"55 },56 {57 "indexed": false,58 "internalType": "uint256",59 "name": "tokenId",60 "type": "uint256"61 }62 ],63 "name": "TokenChanged",64 "type": "event"65 },66 {47 {67 "inputs": [48 "inputs": [68 { "internalType": "uint32", "name": "collectionId", "type": "uint32" }49 { "internalType": "uint32", "name": "collectionId", "type": "uint32" }tests/src/eth/abi/nonFungible.jsondiffbeforeafterboth49 "name": "ApprovalForAll",49 "name": "ApprovalForAll",50 "type": "event"50 "type": "event"51 },51 },52 {53 "anonymous": false,54 "inputs": [55 {56 "indexed": true,57 "internalType": "address",58 "name": "collectionId",59 "type": "address"60 },61 {62 "indexed": false,63 "internalType": "uint256",64 "name": "tokenId",65 "type": "uint256"66 }67 ],68 "name": "TokenChanged",69 "type": "event"70 },52 {71 {53 "anonymous": false,72 "anonymous": false,54 "inputs": [73 "inputs": [tests/src/eth/abi/reFungible.jsondiffbeforeafterboth49 "name": "ApprovalForAll",49 "name": "ApprovalForAll",50 "type": "event"50 "type": "event"51 },51 },52 {53 "anonymous": false,54 "inputs": [55 {56 "indexed": true,57 "internalType": "address",58 "name": "collectionId",59 "type": "address"60 },61 {62 "indexed": false,63 "internalType": "uint256",64 "name": "tokenId",65 "type": "uint256"66 }67 ],68 "name": "TokenChanged",69 "type": "event"70 },52 {71 {53 "anonymous": false,72 "anonymous": false,54 "inputs": [73 "inputs": [tests/src/eth/api/CollectionHelpers.soldiffbeforeafterboth17 event CollectionCreated(address indexed owner, address indexed collectionId);17 event CollectionCreated(address indexed owner, address indexed collectionId);18 event CollectionDestroyed(address indexed collectionId);18 event CollectionDestroyed(address indexed collectionId);19 event CollectionChanged(address indexed collectionId);19 event CollectionChanged(address indexed collectionId);20 event TokenChanged(address indexed collectionId, uint256 tokenId);21}20}222123/// @title Contract, which allows users to operate with collections22/// @title Contract, which allows users to operate with collectionstests/src/eth/api/UniqueNFT.soldiffbeforeafterboth12 function supportsInterface(bytes4 interfaceID) external view returns (bool);12 function supportsInterface(bytes4 interfaceID) external view returns (bool);13}13}1415/// @dev inlined interface16interface ERC721TokenEvent {17 event TokenChanged(address indexed collectionId, uint256 tokenId);18}141915/// @title A contract that allows to set and delete token properties and change token property permissions.20/// @title A contract that allows to set and delete token properties and change token property permissions.16/// @dev the ERC-165 identifier for this interface is 0xde0695c221/// @dev the ERC-165 identifier for this interface is 0xde0695c217interface TokenProperties is Dummy, ERC165 {22interface TokenProperties is Dummy, ERC165, ERC721TokenEvent {18 // /// @notice Set permissions for token property.23 // /// @notice Set permissions for token property.19 // /// @dev Throws error if `msg.sender` is not admin or owner of the collection.24 // /// @dev Throws error if `msg.sender` is not admin or owner of the collection.20 // /// @param key Property key.25 // /// @param key Property key.tests/src/eth/api/UniqueRefungible.soldiffbeforeafterboth12 function supportsInterface(bytes4 interfaceID) external view returns (bool);12 function supportsInterface(bytes4 interfaceID) external view returns (bool);13}13}1415/// @dev inlined interface16interface ERC721TokenEvent {17 event TokenChanged(address indexed collectionId, uint256 tokenId);18}141915/// @title A contract that allows to set and delete token properties and change token property permissions.20/// @title A contract that allows to set and delete token properties and change token property permissions.16/// @dev the ERC-165 identifier for this interface is 0xde0695c221/// @dev the ERC-165 identifier for this interface is 0xde0695c217interface TokenProperties is Dummy, ERC165 {22interface TokenProperties is Dummy, ERC165, ERC721TokenEvent {18 // /// @notice Set permissions for token property.23 // /// @notice Set permissions for token property.19 // /// @dev Throws error if `msg.sender` is not admin or owner of the collection.24 // /// @dev Throws error if `msg.sender` is not admin or owner of the collection.20 // /// @param key Property key.25 // /// @param key Property key.tests/src/eth/events.test.tsdiffbeforeafterboth29 });29 });30});30});313132function clearEvents(ethEvents: NormalizedEvent[], subEvents: IEvent[]) {32function clearEvents(ethEvents: NormalizedEvent[] | null, subEvents: IEvent[]) {33 if (ethEvents !== null) {33 ethEvents.splice(0);34 ethEvents.splice(0);35 }34 subEvents.splice(0);36 subEvents.splice(0);35}37}3638374 const owner = await helper.eth.createAccountWithBalance(donor);376 const owner = await helper.eth.createAccountWithBalance(donor);375 const {collectionAddress} = await helper.eth.createCollection(mode, owner, 'A', 'B', 'C');377 const {collectionAddress} = await helper.eth.createCollection(mode, owner, 'A', 'B', 'C');376 const collection = await helper.ethNativeContract.collection(collectionAddress, mode, owner);378 const collection = await helper.ethNativeContract.collection(collectionAddress, mode, owner);377 const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner);378 const result = await collection.methods.mint(owner).send({from: owner});379 const result = await collection.methods.mint(owner).send({from: owner});379 const tokenId = result.events.Transfer.returnValues.tokenId;380 const tokenId = result.events.Transfer.returnValues.tokenId;380 await collection.methods.setTokenPropertyPermissions([381 await collection.methods.setTokenPropertyPermissions([386 ]).send({from: owner});387 ]).send({from: owner});387388388389 const ethEvents: any = [];390 collectionHelper.events.allEvents((_: any, event: any) => {391 ethEvents.push(event);392 });393 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['TokenPropertySet', 'TokenPropertyDeleted']}]);389 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['TokenPropertySet', 'TokenPropertyDeleted']}]);394 {390 {395 await collection.methods.setProperties(tokenId, [{key: 'A', value: [1,2,3]}]).send({from: owner});391 const result = await collection.methods.setProperties(tokenId, [{key: 'A', value: [1,2,3]}]).send({from: owner});396 await helper.wait.newBlocks(1);392 await helper.wait.newBlocks(1);397 expect(ethEvents).to.containSubset([393 expect(result.events.TokenChanged).to.be.like({398 {399 event: 'TokenChanged',394 event: 'TokenChanged',400 returnValues: {395 returnValues: {401 collectionId: collectionAddress,396 collectionId: collectionAddress,397 tokenId: tokenId,402 },398 },403 },399 });404 ]);405 expect(subEvents).to.containSubset([{method: 'TokenPropertySet'}]);400 expect(subEvents).to.containSubset([{method: 'TokenPropertySet'}]);406 clearEvents(ethEvents, subEvents);401 clearEvents(null, subEvents);407 }402 }408 {403 {409 await collection.methods.deleteProperties(tokenId, ['A']).send({from: owner});404 const result = await collection.methods.deleteProperties(tokenId, ['A']).send({from: owner});410 await helper.wait.newBlocks(1);405 await helper.wait.newBlocks(1);411 expect(ethEvents).to.containSubset([406 expect(result.events.TokenChanged).to.be.like({412 {413 event: 'TokenChanged',407 event: 'TokenChanged',414 returnValues: {408 returnValues: {415 collectionId: collectionAddress,409 collectionId: collectionAddress,410 tokenId: tokenId,416 },411 },417 },412 });418 ]);419 expect(subEvents).to.containSubset([{method: 'TokenPropertyDeleted'}]);413 expect(subEvents).to.containSubset([{method: 'TokenPropertyDeleted'}]);420 }414 }421 unsubscribe();415 unsubscribe();