difftreelog
fix PR
in: master
4 files changed
pallets/nonfungible/src/erc.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/erc.rs
+++ b/pallets/nonfungible/src/erc.rs
@@ -90,6 +90,7 @@
/// @notice Set permissions for token property.
/// @dev Throws error if `msg.sender` is not admin or owner of the collection.
/// @param permissions Permissions for keys.
+ #[weight(<SelfWeightOf<T>>::set_token_property_permissions(permissions.len() as u32))]
fn set_token_property_permissions(
&mut self,
caller: caller,
@@ -98,7 +99,7 @@
let caller = T::CrossAccountId::from_eth(caller);
const PERMISSIONS_FIELDS_COUNT: usize = 3;
- let mut perms = <Vec<_>>::new();
+ let mut perms = Vec::new();
for (key, pp) in permissions {
if pp.len() > PERMISSIONS_FIELDS_COUNT {
@@ -112,11 +113,7 @@
.into());
}
- let mut token_permission = PropertyPermission {
- mutable: false,
- collection_admin: false,
- token_owner: false,
- };
+ let mut token_permission = PropertyPermission::default();
for (perm, value) in pp {
match perm {
@@ -129,9 +126,7 @@
}
perms.push(PropertyKeyPermission {
- key: <Vec<u8>>::from(key)
- .try_into()
- .map_err(|_| "too long key")?,
+ key: key.into_bytes().try_into().map_err(|_| "too long key")?,
permission: token_permission,
});
}
@@ -144,17 +139,19 @@
fn token_property_permissions(
&self,
) -> Result<Vec<(string, Vec<(EthTokenPermissions, bool)>)>> {
- let mut res = <Vec<_>>::new();
- for (key, pp) in <Pallet<T>>::token_property_permission(self.id) {
- let key = string::from_utf8(key.into_inner()).unwrap();
- let pp = vec![
- (EthTokenPermissions::Mutable, pp.mutable),
- (EthTokenPermissions::TokenOwner, pp.token_owner),
- (EthTokenPermissions::CollectionAdmin, pp.collection_admin),
- ];
- res.push((key, pp));
- }
- Ok(res)
+ let perms = <Pallet<T>>::token_property_permission(self.id);
+ Ok(perms
+ .into_iter()
+ .map(|(key, pp)| {
+ let key = string::from_utf8(key.into_inner()).expect("Stored key must be valid");
+ let pp = vec![
+ (EthTokenPermissions::Mutable, pp.mutable),
+ (EthTokenPermissions::TokenOwner, pp.token_owner),
+ (EthTokenPermissions::CollectionAdmin, pp.collection_admin),
+ ];
+ (key, pp)
+ })
+ .collect())
}
/// @notice Set token property value.
pallets/refungible/src/erc.rsdiffbeforeafterboth93 /// @notice Set permissions for token property.93 /// @notice Set permissions for token property.94 /// @dev Throws error if `msg.sender` is not admin or owner of the collection.94 /// @dev Throws error if `msg.sender` is not admin or owner of the collection.95 /// @param permissions Permissions for keys.95 /// @param permissions Permissions for keys.96 #[weight(<SelfWeightOf<T>>::set_token_property_permissions(permissions.len() as u32))]96 fn set_token_property_permissions(97 fn set_token_property_permissions(97 &mut self,98 &mut self,98 caller: caller,99 caller: caller,101 let caller = T::CrossAccountId::from_eth(caller);102 let caller = T::CrossAccountId::from_eth(caller);102 const PERMISSIONS_FIELDS_COUNT: usize = 3;103 const PERMISSIONS_FIELDS_COUNT: usize = 3;103104104 let mut perms = <Vec<_>>::new();105 let mut perms = Vec::new();105106106 for (key, pp) in permissions {107 for (key, pp) in permissions {107 if pp.len() > PERMISSIONS_FIELDS_COUNT {108 if pp.len() > PERMISSIONS_FIELDS_COUNT {132 }133 }133134134 perms.push(PropertyKeyPermission {135 perms.push(PropertyKeyPermission {135 key: <Vec<u8>>::from(key)136 key: key.into_bytes().try_into().map_err(|_| "too long key")?,136 .try_into()137 .map_err(|_| "too long key")?,138 permission: token_permission,137 permission: token_permission,147 fn token_property_permissions(146 fn token_property_permissions(148 &self,147 &self,149 ) -> Result<Vec<(string, Vec<(EthTokenPermissions, bool)>)>> {148 ) -> Result<Vec<(string, Vec<(EthTokenPermissions, bool)>)>> {150 let mut res = <Vec<_>>::new();149 let perms = <Pallet<T>>::token_property_permission(self.id);150 Ok(perms151 .into_iter()151 for (key, pp) in <Pallet<T>>::token_property_permission(self.id) {152 .map(|(key, pp)| {152 let key = string::from_utf8(key.into_inner()).unwrap();153 let key = string::from_utf8(key.into_inner()).expect("Stored key must be valid");153 let pp = [154 let pp = vec![154 (EthTokenPermissions::Mutable, pp.mutable),155 (EthTokenPermissions::Mutable, pp.mutable),155 (EthTokenPermissions::TokenOwner, pp.token_owner),156 (EthTokenPermissions::TokenOwner, pp.token_owner),156 (EthTokenPermissions::CollectionAdmin, pp.collection_admin),157 (EthTokenPermissions::CollectionAdmin, pp.collection_admin),157 ]158 ];158 .into();159 res.push((key, pp));159 (key, pp)160 }160 })161 Ok(res)161 .collect())162 }162 }163163164 /// @notice Set token property value.164 /// @notice Set token property value.primitives/data-structs/src/lib.rsdiffbeforeafterboth--- a/primitives/data-structs/src/lib.rs
+++ b/primitives/data-structs/src/lib.rs
@@ -1010,7 +1010,7 @@
pub type PropertyValue = BoundedBytes<ConstU32<MAX_PROPERTY_VALUE_LENGTH>>;
/// Property permission.
-#[derive(Encode, Decode, TypeInfo, Debug, MaxEncodedLen, PartialEq, Clone)]
+#[derive(Encode, Decode, TypeInfo, Debug, MaxEncodedLen, PartialEq, Clone, Default)]
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
pub struct PropertyPermission {
/// Permission to change the property and property permission.
tests/src/eth/tokenProperties.test.tsdiffbeforeafterboth--- a/tests/src/eth/tokenProperties.test.ts
+++ b/tests/src/eth/tokenProperties.test.ts
@@ -69,6 +69,134 @@
}));
[
+ {mode: 'nft' as const, requiredPallets: []},
+ {mode: 'rft' as const, requiredPallets: [Pallets.ReFungible]},
+ ].map(testCase =>
+ itEth.ifWithPallets(`[${testCase.mode}] Set and get multiple token property permissions as owner`, testCase.requiredPallets, async({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+
+ const {collectionId, collectionAddress} = await helper.eth.createCollection(testCase.mode, owner, 'A', 'B', 'C');
+ const collection = await helper.ethNativeContract.collection(collectionAddress, testCase.mode, owner);
+
+ await collection.methods.setTokenPropertyPermissions([
+ ['testKey_0', [
+ [EthTokenPermissions.Mutable, true],
+ [EthTokenPermissions.TokenOwner, true],
+ [EthTokenPermissions.CollectionAdmin, true]],
+ ],
+ ['testKey_1', [
+ [EthTokenPermissions.Mutable, true],
+ [EthTokenPermissions.TokenOwner, false],
+ [EthTokenPermissions.CollectionAdmin, true]],
+ ],
+ ['testKey_2', [
+ [EthTokenPermissions.Mutable, false],
+ [EthTokenPermissions.TokenOwner, true],
+ [EthTokenPermissions.CollectionAdmin, false]],
+ ],
+ ]).send({from: owner});
+
+ expect(await helper[testCase.mode].getPropertyPermissions(collectionId)).to.be.deep.equal([
+ {
+ key: 'testKey_0',
+ permission: {mutable: true, tokenOwner: true, collectionAdmin: true},
+ },
+ {
+ key: 'testKey_1',
+ permission: {mutable: true, tokenOwner: false, collectionAdmin: true},
+ },
+ {
+ key: 'testKey_2',
+ permission: {mutable: false, tokenOwner: true, collectionAdmin: false},
+ },
+ ]);
+
+ expect(await collection.methods.tokenPropertyPermissions().call({from: owner})).to.be.like([
+ ['testKey_0', [
+ [EthTokenPermissions.Mutable.toString(), true],
+ [EthTokenPermissions.TokenOwner.toString(), true],
+ [EthTokenPermissions.CollectionAdmin.toString(), true]],
+ ],
+ ['testKey_1', [
+ [EthTokenPermissions.Mutable.toString(), true],
+ [EthTokenPermissions.TokenOwner.toString(), false],
+ [EthTokenPermissions.CollectionAdmin.toString(), true]],
+ ],
+ ['testKey_2', [
+ [EthTokenPermissions.Mutable.toString(), false],
+ [EthTokenPermissions.TokenOwner.toString(), true],
+ [EthTokenPermissions.CollectionAdmin.toString(), false]],
+ ],
+ ]);
+
+ }));
+
+ [
+ {mode: 'nft' as const, requiredPallets: []},
+ {mode: 'rft' as const, requiredPallets: [Pallets.ReFungible]},
+ ].map(testCase =>
+ itEth.ifWithPallets(`[${testCase.mode}] Set and get multiple token property permissions as admin`, testCase.requiredPallets, async({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const caller = await helper.ethCrossAccount.createAccountWithBalance(donor);
+
+ const {collectionId, collectionAddress} = await helper.eth.createCollection(testCase.mode, owner, 'A', 'B', 'C');
+ const collection = await helper.ethNativeContract.collection(collectionAddress, testCase.mode, owner);
+ await collection.methods.addCollectionAdminCross(caller).send({from: owner});
+
+ await collection.methods.setTokenPropertyPermissions([
+ ['testKey_0', [
+ [EthTokenPermissions.Mutable, true],
+ [EthTokenPermissions.TokenOwner, true],
+ [EthTokenPermissions.CollectionAdmin, true]],
+ ],
+ ['testKey_1', [
+ [EthTokenPermissions.Mutable, true],
+ [EthTokenPermissions.TokenOwner, false],
+ [EthTokenPermissions.CollectionAdmin, true]],
+ ],
+ ['testKey_2', [
+ [EthTokenPermissions.Mutable, false],
+ [EthTokenPermissions.TokenOwner, true],
+ [EthTokenPermissions.CollectionAdmin, false]],
+ ],
+ ]).send({from: caller.eth});
+
+ expect(await helper[testCase.mode].getPropertyPermissions(collectionId)).to.be.deep.equal([
+ {
+ key: 'testKey_0',
+ permission: {mutable: true, tokenOwner: true, collectionAdmin: true},
+ },
+ {
+ key: 'testKey_1',
+ permission: {mutable: true, tokenOwner: false, collectionAdmin: true},
+ },
+ {
+ key: 'testKey_2',
+ permission: {mutable: false, tokenOwner: true, collectionAdmin: false},
+ },
+ ]);
+
+ expect(await collection.methods.tokenPropertyPermissions().call({from: caller.eth})).to.be.like([
+ ['testKey_0', [
+ [EthTokenPermissions.Mutable.toString(), true],
+ [EthTokenPermissions.TokenOwner.toString(), true],
+ [EthTokenPermissions.CollectionAdmin.toString(), true]],
+ ],
+ ['testKey_1', [
+ [EthTokenPermissions.Mutable.toString(), true],
+ [EthTokenPermissions.TokenOwner.toString(), false],
+ [EthTokenPermissions.CollectionAdmin.toString(), true]],
+ ],
+ ['testKey_2', [
+ [EthTokenPermissions.Mutable.toString(), false],
+ [EthTokenPermissions.TokenOwner.toString(), true],
+ [EthTokenPermissions.CollectionAdmin.toString(), false]],
+ ],
+ ]);
+
+ }));
+
+ [
{
method: 'setProperties',
methodParams: [[{key: 'testKey1', value: Buffer.from('testValue1')}, {key: 'testKey2', value: Buffer.from('testValue2')}]],
@@ -319,6 +447,47 @@
const actualProps = await collectionEvm.methods.properties(token.tokenId, []).call();
expect(actualProps).to.deep.eq(expectedProps);
}));
+
+ [
+ {mode: 'nft' as const, requiredPallets: []},
+ {mode: 'rft' as const, requiredPallets: [Pallets.ReFungible]},
+ ].map(testCase =>
+ itEth.ifWithPallets(`[${testCase.mode}] Cant set token property permissions as non owner or admin`, testCase.requiredPallets, async({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const caller = await helper.eth.createAccountWithBalance(donor);
+
+ const {collectionAddress} = await helper.eth.createCollection(testCase.mode, owner, 'A', 'B', 'C');
+ const collection = await helper.ethNativeContract.collection(collectionAddress, testCase.mode, owner);
+
+ await expect(collection.methods.setTokenPropertyPermissions([
+ ['testKey_0', [
+ [EthTokenPermissions.Mutable, true],
+ [EthTokenPermissions.TokenOwner, true],
+ [EthTokenPermissions.CollectionAdmin, true]],
+ ],
+ ]).call({from: caller})).to.be.rejectedWith('NoPermission');
+ }));
+
+ [
+ {mode: 'nft' as const, requiredPallets: []},
+ {mode: 'rft' as const, requiredPallets: [Pallets.ReFungible]},
+ ].map(testCase =>
+ itEth.ifWithPallets(`[${testCase.mode}] Cant set token property permissions with invalid character`, testCase.requiredPallets, async({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+
+ const {collectionAddress} = await helper.eth.createCollection(testCase.mode, owner, 'A', 'B', 'C');
+ const collection = await helper.ethNativeContract.collection(collectionAddress, testCase.mode, owner);
+
+ await expect(collection.methods.setTokenPropertyPermissions([
+ // "Space" is invalid character
+ ['testKey 0', [
+ [EthTokenPermissions.Mutable, true],
+ [EthTokenPermissions.TokenOwner, true],
+ [EthTokenPermissions.CollectionAdmin, true]],
+ ],
+ ]).call({from: owner})).to.be.rejectedWith('InvalidCharacterInPropertyKey');
+ }));
+
});