difftreelog
added `collectionNestingPermissions` funtion in `Collection` interface
in: master
13 files changed
pallets/common/src/erc.rsdiffbeforeafterboth--- a/pallets/common/src/erc.rs
+++ b/pallets/common/src/erc.rs
@@ -26,7 +26,7 @@
weight,
};
use pallet_evm_coder_substrate::dispatch_to_evm;
-use sp_std::vec::Vec;
+use sp_std::{vec, vec::Vec};
use up_data_structs::{
AccessMode, CollectionMode, CollectionPermissions, OwnerRestrictedSet, Property,
SponsoringRateLimit, SponsorshipState,
@@ -35,7 +35,9 @@
use crate::{
Pallet, CollectionHandle, Config, CollectionProperties, SelfWeightOf,
- eth::{EthCrossAccount, convert_cross_account_to_uint256},
+ eth::{
+ EthCrossAccount, convert_cross_account_to_uint256, CollectionPermissions as EvmPermissions,
+ },
weights::WeightInfo,
};
@@ -508,6 +510,14 @@
))
}
+ /// Returns permissions for a collection
+ fn collection_nesting_permissions(&self) -> Result<Vec<(EvmPermissions, bool)>> {
+ let nesting = self.collection.permissions.nesting();
+ Ok(vec![
+ (EvmPermissions::CollectionAdmin, nesting.collection_admin),
+ (EvmPermissions::TokenOwner, nesting.token_owner),
+ ])
+ }
/// Set the collection access method.
/// @param mode Access mode
/// 0 for Normal
pallets/common/src/eth.rsdiffbeforeafterboth1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617//! The module contains a number of functions for converting and checking ethereum identifiers.1819use evm_coder::{20 AbiCoder,21 types::{uint256, address},22};23pub use pallet_evm::{Config, account::CrossAccountId};24use sp_core::H160;25use up_data_structs::CollectionId;2627// 0x17c4e6453Cc49AAAaEACA894e6D9683e00000001 - collection 128// TODO: Unhardcode prefix29const ETH_COLLECTION_PREFIX: [u8; 16] = [30 0x17, 0xc4, 0xe6, 0x45, 0x3c, 0xc4, 0x9a, 0xaa, 0xae, 0xac, 0xa8, 0x94, 0xe6, 0xd9, 0x68, 0x3e,31];3233/// Maps the ethereum address of the collection in substrate.34pub fn map_eth_to_id(eth: &H160) -> Option<CollectionId> {35 if eth[0..16] != ETH_COLLECTION_PREFIX {36 return None;37 }38 let mut id_bytes = [0; 4];39 id_bytes.copy_from_slice(ð[16..20]);40 Some(CollectionId(u32::from_be_bytes(id_bytes)))41}4243/// Maps the substrate collection id in ethereum.44pub fn collection_id_to_address(id: CollectionId) -> H160 {45 let mut out = [0; 20];46 out[0..16].copy_from_slice(Ð_COLLECTION_PREFIX);47 out[16..20].copy_from_slice(&u32::to_be_bytes(id.0));48 H160(out)49}5051/// Check if the ethereum address is a collection.52pub fn is_collection(address: &H160) -> bool {53 address[0..16] == ETH_COLLECTION_PREFIX54}5556/// Convert `CrossAccountId` to `uint256`.57pub fn convert_cross_account_to_uint256<T: Config>(from: &T::CrossAccountId) -> uint25658where59 T::AccountId: AsRef<[u8; 32]>,60{61 let slice = from.as_sub().as_ref();62 uint256::from_big_endian(slice)63}6465/// Convert `uint256` to `CrossAccountId`.66pub fn convert_uint256_to_cross_account<T: Config>(from: uint256) -> T::CrossAccountId67where68 T::AccountId: From<[u8; 32]>,69{70 let mut new_admin_arr = [0_u8; 32];71 from.to_big_endian(&mut new_admin_arr);72 let account_id = T::AccountId::from(new_admin_arr);73 T::CrossAccountId::from_sub(account_id)74}7576/// Convert `CrossAccountId` to `(address, uint256)`.77pub fn convert_cross_account_to_tuple<T: Config>(78 cross_account_id: &T::CrossAccountId,79) -> (address, uint256)80where81 T::AccountId: AsRef<[u8; 32]>,82{83 if cross_account_id.is_canonical_substrate() {84 let sub = convert_cross_account_to_uint256::<T>(cross_account_id);85 (Default::default(), sub)86 } else {87 let eth = *cross_account_id.as_eth();88 (eth, Default::default())89 }90}9192/// Convert tuple `(address, uint256)` to `CrossAccountId`.93///94/// If `address` in the tuple has *default* value, then the canonical form is substrate,95/// if `uint256` has *default* value, then the ethereum form is canonical,96/// if both values are *default* or *non default*, then this is considered an invalid address and `Error` is returned.97pub fn convert_tuple_to_cross_account<T: Config>(98 eth_cross_account_id: (address, uint256),99) -> evm_coder::execution::Result<T::CrossAccountId>100where101 T::AccountId: From<[u8; 32]>,102{103 if eth_cross_account_id == Default::default() {104 Err("All fields of cross account is zeroed".into())105 } else if eth_cross_account_id.0 == Default::default() {106 Ok(convert_uint256_to_cross_account::<T>(107 eth_cross_account_id.1,108 ))109 } else if eth_cross_account_id.1 == Default::default() {110 Ok(T::CrossAccountId::from_eth(eth_cross_account_id.0))111 } else {112 Err("All fields of cross account is non zeroed".into())113 }114}115116/// Cross account struct117#[derive(Debug, Default, AbiCoder)]118pub struct EthCrossAccount {119 pub(crate) eth: address,120 pub(crate) sub: uint256,121}122123impl EthCrossAccount {124 pub fn from_sub_cross_account<T>(cross_account_id: &T::CrossAccountId) -> Self125 where126 T: pallet_evm::Config,127 T::AccountId: AsRef<[u8; 32]>,128 {129 if cross_account_id.is_canonical_substrate() {130 Self {131 eth: Default::default(),132 sub: convert_cross_account_to_uint256::<T>(cross_account_id),133 }134 } else {135 Self {136 eth: *cross_account_id.as_eth(),137 sub: Default::default(),138 }139 }140 }141142 pub fn into_sub_cross_account<T>(&self) -> evm_coder::execution::Result<T::CrossAccountId>143 where144 T: pallet_evm::Config,145 T::AccountId: From<[u8; 32]>,146 {147 if self.eth == Default::default() && self.sub == Default::default() {148 Err("All fields of cross account is zeroed".into())149 } else if self.eth == Default::default() {150 Ok(convert_uint256_to_cross_account::<T>(self.sub))151 } else if self.sub == Default::default() {152 Ok(T::CrossAccountId::from_eth(self.eth))153 } else {154 Err("All fields of cross account is non zeroed".into())155 }156 }157}pallets/fungible/src/stubs/UniqueFungible.rawdiffbeforeafterbothbinary blob — no preview
pallets/fungible/src/stubs/UniqueFungible.soldiffbeforeafterboth--- a/pallets/fungible/src/stubs/UniqueFungible.sol
+++ b/pallets/fungible/src/stubs/UniqueFungible.sol
@@ -18,7 +18,7 @@
}
/// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0xeecfdb34
+/// @dev the ERC-165 identifier for this interface is 0xb5e1747f
contract Collection is Dummy, ERC165 {
// /// Set collection property.
// ///
@@ -263,6 +263,15 @@
return Tuple21(false, new uint256[](0));
}
+ /// Returns permissions for a collection
+ /// @dev EVM selector for this function is: 0x5b2eaf4b,
+ /// or in textual repr: collectionNestingPermissions()
+ function collectionNestingPermissions() public view returns (Tuple24[] memory) {
+ require(false, stub_error);
+ dummy;
+ return new Tuple24[](0);
+ }
+
/// Set the collection access method.
/// @param mode Access mode
/// 0 for Normal
@@ -434,6 +443,17 @@
uint256 sub;
}
+enum CollectionPermissions {
+ CollectionAdmin,
+ TokenOwner
+}
+
+/// @dev anonymous struct
+struct Tuple24 {
+ CollectionPermissions field_0;
+ bool field_1;
+}
+
/// @dev anonymous struct
struct Tuple21 {
bool field_0;
pallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth--- a/pallets/nonfungible/src/stubs/UniqueNFT.sol
+++ b/pallets/nonfungible/src/stubs/UniqueNFT.sol
@@ -119,7 +119,7 @@
}
/// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0xeecfdb34
+/// @dev the ERC-165 identifier for this interface is 0xb5e1747f
contract Collection is Dummy, ERC165 {
// /// Set collection property.
// ///
@@ -364,6 +364,15 @@
return Tuple34(false, new uint256[](0));
}
+ /// Returns permissions for a collection
+ /// @dev EVM selector for this function is: 0x5b2eaf4b,
+ /// or in textual repr: collectionNestingPermissions()
+ function collectionNestingPermissions() public view returns (Tuple37[] memory) {
+ require(false, stub_error);
+ dummy;
+ return new Tuple37[](0);
+ }
+
/// Set the collection access method.
/// @param mode Access mode
/// 0 for Normal
@@ -535,6 +544,17 @@
uint256 sub;
}
+enum CollectionPermissions {
+ CollectionAdmin,
+ TokenOwner
+}
+
+/// @dev anonymous struct
+struct Tuple37 {
+ CollectionPermissions field_0;
+ bool field_1;
+}
+
/// @dev anonymous struct
struct Tuple34 {
bool field_0;
pallets/refungible/src/stubs/UniqueRefungible.soldiffbeforeafterboth--- a/pallets/refungible/src/stubs/UniqueRefungible.sol
+++ b/pallets/refungible/src/stubs/UniqueRefungible.sol
@@ -119,7 +119,7 @@
}
/// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0xeecfdb34
+/// @dev the ERC-165 identifier for this interface is 0xb5e1747f
contract Collection is Dummy, ERC165 {
// /// Set collection property.
// ///
@@ -364,6 +364,15 @@
return Tuple33(false, new uint256[](0));
}
+ /// Returns permissions for a collection
+ /// @dev EVM selector for this function is: 0x5b2eaf4b,
+ /// or in textual repr: collectionNestingPermissions()
+ function collectionNestingPermissions() public view returns (Tuple36[] memory) {
+ require(false, stub_error);
+ dummy;
+ return new Tuple36[](0);
+ }
+
/// Set the collection access method.
/// @param mode Access mode
/// 0 for Normal
@@ -535,6 +544,17 @@
uint256 sub;
}
+enum CollectionPermissions {
+ CollectionAdmin,
+ TokenOwner
+}
+
+/// @dev anonymous struct
+struct Tuple36 {
+ CollectionPermissions field_0;
+ bool field_1;
+}
+
/// @dev anonymous struct
struct Tuple33 {
bool field_0;
tests/src/eth/abi/fungible.jsondiffbeforeafterboth--- a/tests/src/eth/abi/fungible.json
+++ b/tests/src/eth/abi/fungible.json
@@ -208,6 +208,27 @@
},
{
"inputs": [],
+ "name": "collectionNestingPermissions",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "enum CollectionPermissions",
+ "name": "field_0",
+ "type": "uint8"
+ },
+ { "internalType": "bool", "name": "field_1", "type": "bool" }
+ ],
+ "internalType": "struct Tuple24[]",
+ "name": "",
+ "type": "tuple[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
"name": "collectionNestingRestrictedCollectionIds",
"outputs": [
{
tests/src/eth/abi/nonFungible.jsondiffbeforeafterboth--- a/tests/src/eth/abi/nonFungible.json
+++ b/tests/src/eth/abi/nonFungible.json
@@ -238,6 +238,27 @@
},
{
"inputs": [],
+ "name": "collectionNestingPermissions",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "enum CollectionPermissions",
+ "name": "field_0",
+ "type": "uint8"
+ },
+ { "internalType": "bool", "name": "field_1", "type": "bool" }
+ ],
+ "internalType": "struct Tuple37[]",
+ "name": "",
+ "type": "tuple[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
"name": "collectionNestingRestrictedCollectionIds",
"outputs": [
{
tests/src/eth/abi/reFungible.jsondiffbeforeafterboth--- a/tests/src/eth/abi/reFungible.json
+++ b/tests/src/eth/abi/reFungible.json
@@ -220,6 +220,27 @@
},
{
"inputs": [],
+ "name": "collectionNestingPermissions",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "enum CollectionPermissions",
+ "name": "field_0",
+ "type": "uint8"
+ },
+ { "internalType": "bool", "name": "field_1", "type": "bool" }
+ ],
+ "internalType": "struct Tuple36[]",
+ "name": "",
+ "type": "tuple[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
"name": "collectionNestingRestrictedCollectionIds",
"outputs": [
{
tests/src/eth/api/UniqueFungible.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueFungible.sol
+++ b/tests/src/eth/api/UniqueFungible.sol
@@ -13,7 +13,7 @@
}
/// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0xeecfdb34
+/// @dev the ERC-165 identifier for this interface is 0xb5e1747f
interface Collection is Dummy, ERC165 {
// /// Set collection property.
// ///
@@ -171,6 +171,11 @@
/// or in textual repr: collectionNestingRestrictedCollectionIds()
function collectionNestingRestrictedCollectionIds() external view returns (Tuple20 memory);
+ /// Returns permissions for a collection
+ /// @dev EVM selector for this function is: 0x5b2eaf4b,
+ /// or in textual repr: collectionNestingPermissions()
+ function collectionNestingPermissions() external view returns (Tuple23[] memory);
+
/// Set the collection access method.
/// @param mode Access mode
/// 0 for Normal
@@ -284,6 +289,17 @@
}
/// @dev anonymous struct
+struct Tuple23 {
+ CollectionPermissions field_0;
+ bool field_1;
+}
+
+enum CollectionPermissions {
+ CollectionAdmin,
+ TokenOwner
+}
+
+/// @dev anonymous struct
struct Tuple20 {
bool field_0;
uint256[] field_1;
tests/src/eth/api/UniqueNFT.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueNFT.sol
+++ b/tests/src/eth/api/UniqueNFT.sol
@@ -80,7 +80,7 @@
}
/// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0xeecfdb34
+/// @dev the ERC-165 identifier for this interface is 0xb5e1747f
interface Collection is Dummy, ERC165 {
// /// Set collection property.
// ///
@@ -238,6 +238,11 @@
/// or in textual repr: collectionNestingRestrictedCollectionIds()
function collectionNestingRestrictedCollectionIds() external view returns (Tuple31 memory);
+ /// Returns permissions for a collection
+ /// @dev EVM selector for this function is: 0x5b2eaf4b,
+ /// or in textual repr: collectionNestingPermissions()
+ function collectionNestingPermissions() external view returns (Tuple34[] memory);
+
/// Set the collection access method.
/// @param mode Access mode
/// 0 for Normal
@@ -351,6 +356,17 @@
}
/// @dev anonymous struct
+struct Tuple34 {
+ CollectionPermissions field_0;
+ bool field_1;
+}
+
+enum CollectionPermissions {
+ CollectionAdmin,
+ TokenOwner
+}
+
+/// @dev anonymous struct
struct Tuple31 {
bool field_0;
uint256[] field_1;
tests/src/eth/api/UniqueRefungible.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueRefungible.sol
+++ b/tests/src/eth/api/UniqueRefungible.sol
@@ -80,7 +80,7 @@
}
/// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0xeecfdb34
+/// @dev the ERC-165 identifier for this interface is 0xb5e1747f
interface Collection is Dummy, ERC165 {
// /// Set collection property.
// ///
@@ -238,6 +238,11 @@
/// or in textual repr: collectionNestingRestrictedCollectionIds()
function collectionNestingRestrictedCollectionIds() external view returns (Tuple30 memory);
+ /// Returns permissions for a collection
+ /// @dev EVM selector for this function is: 0x5b2eaf4b,
+ /// or in textual repr: collectionNestingPermissions()
+ function collectionNestingPermissions() external view returns (Tuple33[] memory);
+
/// Set the collection access method.
/// @param mode Access mode
/// 0 for Normal
@@ -351,6 +356,17 @@
}
/// @dev anonymous struct
+struct Tuple33 {
+ CollectionPermissions field_0;
+ bool field_1;
+}
+
+enum CollectionPermissions {
+ CollectionAdmin,
+ TokenOwner
+}
+
+/// @dev anonymous struct
struct Tuple30 {
bool field_0;
uint256[] field_1;
tests/src/eth/nesting/nest.test.tsdiffbeforeafterboth--- a/tests/src/eth/nesting/nest.test.ts
+++ b/tests/src/eth/nesting/nest.test.ts
@@ -52,7 +52,7 @@
expect(await contract.methods.ownerOf(secondTokenId).call()).to.be.equal(owner);
});
- itEth('NFT: collectionNestingRestrictedCollectionIds()', async ({helper}) => {
+ itEth('NFT: collectionNestingRestrictedCollectionIds() & collectionNestingPermissions', async ({helper}) => {
const owner = await helper.eth.createAccountWithBalance(donor);
const {collectionId: unnestedCollsectionId, collectionAddress: unnsetedCollectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');
const unnestedContract = helper.ethNativeContract.collection(unnsetedCollectionAddress, 'nft', owner);
@@ -62,7 +62,9 @@
expect(await contract.methods.collectionNestingRestrictedCollectionIds().call({from: owner})).to.be.like([true, []]);
await contract.methods.setCollectionNesting(true, [unnsetedCollectionAddress]).send({from: owner});
expect(await contract.methods.collectionNestingRestrictedCollectionIds().call({from: owner})).to.be.like([true, [unnestedCollsectionId.toString()]]);
-
+ expect(await contract.methods.collectionNestingPermissions().call({from: owner})).to.be.like([['0', false], ['1', true]]);
+ await contract.methods.setCollectionNesting(false).send({from: owner});
+ expect(await contract.methods.collectionNestingPermissions().call({from: owner})).to.be.like([['0', false], ['1', false]]);
});
itEth('NFT: allows an Owner to nest/unnest their token (Restricted nesting)', async ({helper}) => {