difftreelog
fix update weighting for mintBulkCross and forbid multiple owners + multipe tokens
in: master
2 files changed
pallets/refungible/src/erc.rsdiffbeforeafterboth104110411042 /// @notice Function to mint a token.1042 /// @notice Function to mint a token.1043 /// @param tokenProperties Properties of minted token1043 /// @param tokenProperties Properties of minted token1044 #[weight(<SelfWeightOf<T>>::create_multiple_items(token_properties.len() as u32) + <SelfWeightOf<T>>::set_token_properties(token_properties.len() as u32))]1044 #[weight(if token_properties.len() == 1 {1045 <SelfWeightOf<T>>::create_multiple_items_ex_multiple_owners(token_properties.iter().next().unwrap().owners.len() as u32)1046 } else {1047 <SelfWeightOf<T>>::create_multiple_items_ex_multiple_items(token_properties.len() as u32)1048 } + <SelfWeightOf<T>>::set_token_properties(token_properties.len() as u32))]1045 fn mint_bulk_cross(1049 fn mint_bulk_cross(1046 &mut self,1050 &mut self,1047 caller: Caller,1051 caller: Caller,1051 let budget = self1055 let budget = self1052 .recorder1056 .recorder1053 .weight_calls_budget(<StructureWeight<T>>::find_parent());1057 .weight_calls_budget(<StructureWeight<T>>::find_parent());1058 let has_multiple_tokens = token_properties.len() > 1;105410591055 let mut create_rft_data = Vec::with_capacity(token_properties.len());1060 let mut create_rft_data = Vec::with_capacity(token_properties.len());1056 for MintTokenData { owners, properties } in token_properties {1061 for MintTokenData { owners, properties } in token_properties {1062 let has_multiple_owners = owners.len() > 1;1063 if has_multiple_tokens & has_multiple_owners {1064 return Err(1065 "creation of multiple tokens supported only if they have single owner each"1066 .into(),1067 );1068 }1057 let users: BoundedBTreeMap<_, _, _> = owners1069 let users: BoundedBTreeMap<_, _, _> = owners1058 .into_iter()1070 .into_iter()1059 .map(|data| Ok((data.owner.into_sub_cross_account::<T>()?, data.pieces)))1071 .map(|data| Ok((data.owner.into_sub_cross_account::<T>()?, data.pieces)))tests/src/eth/reFungible.test.tsdiffbeforeafterboth--- a/tests/src/eth/reFungible.test.ts
+++ b/tests/src/eth/reFungible.test.ts
@@ -126,13 +126,11 @@
}
});
- itEth('Can perform mintBulkCross()', async ({helper}) => {
+ itEth('Can perform mintBulkCross() with multiple tokens', async ({helper}) => {
const caller = await helper.eth.createAccountWithBalance(donor);
const callerCross = helper.ethCrossAccount.fromAddress(caller);
const receiver = helper.eth.createAccount();
const receiverCross = helper.ethCrossAccount.fromAddress(receiver);
- const receiver2 = helper.eth.createAccount();
- const receiver2Cross = helper.ethCrossAccount.fromAddress(receiver2);
const permissions = [
{code: TokenPermissionField.Mutable, value: true},
@@ -160,81 +158,135 @@
).send();
const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', caller);
- {
- const nextTokenId = await contract.methods.nextTokenId().call();
- expect(nextTokenId).to.be.equal('1');
- const result = await contract.methods.mintBulkCross([
+ const nextTokenId = await contract.methods.nextTokenId().call();
+ expect(nextTokenId).to.be.equal('1');
+ const result = await contract.methods.mintBulkCross([
+ {
+ owners: [{
+ owner: receiverCross,
+ pieces: 1,
+ }],
+ properties: [
+ {key: 'key_0_0', value: Buffer.from('value_0_0')},
+ ],
+ },
+ {
+ owners: [{
+ owner: receiverCross,
+ pieces: 2,
+ }],
+ properties: [
+ {key: 'key_1_0', value: Buffer.from('value_1_0')},
+ {key: 'key_1_1', value: Buffer.from('value_1_1')},
+ ],
+ },
+ {
+ owners: [{
+ owner: receiverCross,
+ pieces: 1,
+ }],
+ properties: [
+ {key: 'key_2_0', value: Buffer.from('value_2_0')},
+ {key: 'key_2_1', value: Buffer.from('value_2_1')},
+ {key: 'key_2_2', value: Buffer.from('value_2_2')},
+ ],
+ },
+ ]).send({from: caller});
+ const events = result.events.Transfer.sort((a: any, b: any) => +a.returnValues.tokenId - b.returnValues.tokenId);
+ const bulkSize = 3;
+ for(let i = 0; i < bulkSize; i++) {
+ const event = events[i];
+ expect(event.address).to.equal(collectionAddress);
+ expect(event.returnValues.from).to.equal('0x0000000000000000000000000000000000000000');
+ expect(event.returnValues.to).to.equal(receiver);
+ expect(event.returnValues.tokenId).to.equal(`${+nextTokenId + i}`);
+ }
+
+ const properties = [
+ await contract.methods.properties(+nextTokenId, []).call(),
+ await contract.methods.properties(+nextTokenId + 1, []).call(),
+ await contract.methods.properties(+nextTokenId + 2, []).call(),
+ ];
+ expect(properties).to.be.deep.equal([
+ [
+ ['key_0_0', helper.getWeb3().utils.toHex('value_0_0')],
+ ],
+ [
+ ['key_1_0', helper.getWeb3().utils.toHex('value_1_0')],
+ ['key_1_1', helper.getWeb3().utils.toHex('value_1_1')],
+ ],
+ [
+ ['key_2_0', helper.getWeb3().utils.toHex('value_2_0')],
+ ['key_2_1', helper.getWeb3().utils.toHex('value_2_1')],
+ ['key_2_2', helper.getWeb3().utils.toHex('value_2_2')],
+ ],
+ ]);
+ });
+
+ itEth('Can perform mintBulkCross() with multiple owners', async ({helper}) => {
+ const caller = await helper.eth.createAccountWithBalance(donor);
+ const callerCross = helper.ethCrossAccount.fromAddress(caller);
+ const receiver = helper.eth.createAccount();
+ const receiverCross = helper.ethCrossAccount.fromAddress(receiver);
+ const receiver2 = helper.eth.createAccount();
+ const receiver2Cross = helper.ethCrossAccount.fromAddress(receiver2);
+
+ const permissions = [
+ {code: TokenPermissionField.Mutable, value: true},
+ {code: TokenPermissionField.TokenOwner, value: true},
+ {code: TokenPermissionField.CollectionAdmin, value: true},
+ ];
+ const {collectionAddress} = await helper.eth.createCollection(
+ caller,
+ {
+ ...CREATE_COLLECTION_DATA_DEFAULTS,
+ name: 'A',
+ description: 'B',
+ tokenPrefix: 'C',
+ collectionMode: 'rft',
+ adminList: [callerCross],
+ tokenPropertyPermissions: [
+ {key: 'key_2_0', permissions},
+ {key: 'key_2_1', permissions},
+ {key: 'key_2_2', permissions},
+ ],
+ },
+ ).send();
+
+ const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', caller);
+ const nextTokenId = await contract.methods.nextTokenId().call();
+ expect(nextTokenId).to.be.equal('1');
+ const result = await contract.methods.mintBulkCross([{
+ owners: [
{
- owners: [{
- owner: receiverCross,
- pieces: 1,
- }],
- properties: [
- {key: 'key_0_0', value: Buffer.from('value_0_0')},
- ],
+ owner: receiverCross,
+ pieces: 1,
},
{
- owners: [{
- owner: receiverCross,
- pieces: 2,
- }],
- properties: [
- {key: 'key_1_0', value: Buffer.from('value_1_0')},
- {key: 'key_1_1', value: Buffer.from('value_1_1')},
- ],
+ owner: receiver2Cross,
+ pieces: 2,
},
- {
- owners: [
- {
- owner: receiverCross,
- pieces: 1,
- },
- {
- owner: receiver2Cross,
- pieces: 2,
- },
- ],
- properties: [
- {key: 'key_2_0', value: Buffer.from('value_2_0')},
- {key: 'key_2_1', value: Buffer.from('value_2_1')},
- {key: 'key_2_2', value: Buffer.from('value_2_2')},
- ],
- },
- ]).send({from: caller});
- const events = result.events.Transfer.sort((a: any, b: any) => +a.returnValues.tokenId - b.returnValues.tokenId);
- const bulkSize = 3;
- for(let i = 0; i < bulkSize; i++) {
- const event = events[i];
- expect(event.address).to.equal(collectionAddress);
- expect(event.returnValues.from).to.equal('0x0000000000000000000000000000000000000000');
- if(i == 0 || i == 1)
- expect(event.returnValues.to).to.equal(receiver);
- else
- expect(event.returnValues.to).to.equal('0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF');
-
- expect(event.returnValues.tokenId).to.equal(`${+nextTokenId + i}`);
- }
+ ],
+ properties: [
+ {key: 'key_2_0', value: Buffer.from('value_2_0')},
+ {key: 'key_2_1', value: Buffer.from('value_2_1')},
+ {key: 'key_2_2', value: Buffer.from('value_2_2')},
+ ],
+ }]).send({from: caller});
+ const event = result.events.Transfer;
+ expect(event.address).to.equal(collectionAddress);
+ expect(event.returnValues.from).to.equal('0x0000000000000000000000000000000000000000');
+ expect(event.returnValues.to).to.equal('0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF');
+ expect(event.returnValues.tokenId).to.equal(`${+nextTokenId}`);
- const properties = [
- await contract.methods.properties(+nextTokenId, []).call(),
- await contract.methods.properties(+nextTokenId + 1, []).call(),
- await contract.methods.properties(+nextTokenId + 2, []).call(),
- ];
- expect(properties).to.be.deep.equal([
- [
- ['key_0_0', helper.getWeb3().utils.toHex('value_0_0')],
- ],
- [
- ['key_1_0', helper.getWeb3().utils.toHex('value_1_0')],
- ['key_1_1', helper.getWeb3().utils.toHex('value_1_1')],
- ],
- [
- ['key_2_0', helper.getWeb3().utils.toHex('value_2_0')],
- ['key_2_1', helper.getWeb3().utils.toHex('value_2_1')],
- ['key_2_2', helper.getWeb3().utils.toHex('value_2_2')],
- ],
- ]);
- }
+ const properties = [
+ await contract.methods.properties(+nextTokenId, []).call(),
+ ];
+ expect(properties).to.be.deep.equal([[
+ ['key_2_0', helper.getWeb3().utils.toHex('value_2_0')],
+ ['key_2_1', helper.getWeb3().utils.toHex('value_2_1')],
+ ['key_2_2', helper.getWeb3().utils.toHex('value_2_2')],
+ ]]);
});
itEth('Can perform setApprovalForAll()', async ({helper}) => {
@@ -898,4 +950,70 @@
await expect(contract.methods.transferFromCross(ownerCross, recieverCross, token.tokenId).send({from: spender})).to.be.rejected;
});
+
+ itEth('[negative] Can perform mintBulkCross() with multiple owners and multiple tokens', async ({helper}) => {
+ const caller = await helper.eth.createAccountWithBalance(donor);
+ const callerCross = helper.ethCrossAccount.fromAddress(caller);
+ const receiver = helper.eth.createAccount();
+ const receiverCross = helper.ethCrossAccount.fromAddress(receiver);
+ const receiver2 = helper.eth.createAccount();
+ const receiver2Cross = helper.ethCrossAccount.fromAddress(receiver2);
+
+ const permissions = [
+ {code: TokenPermissionField.Mutable, value: true},
+ {code: TokenPermissionField.TokenOwner, value: true},
+ {code: TokenPermissionField.CollectionAdmin, value: true},
+ ];
+ const {collectionAddress} = await helper.eth.createCollection(
+ caller,
+ {
+ ...CREATE_COLLECTION_DATA_DEFAULTS,
+ name: 'A',
+ description: 'B',
+ tokenPrefix: 'C',
+ collectionMode: 'rft',
+ adminList: [callerCross],
+ tokenPropertyPermissions: [
+ {key: 'key_0_0', permissions},
+ {key: 'key_2_0', permissions},
+ {key: 'key_2_1', permissions},
+ {key: 'key_2_2', permissions},
+ ],
+ },
+ ).send();
+
+ const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', caller);
+ const nextTokenId = await contract.methods.nextTokenId().call();
+ expect(nextTokenId).to.be.equal('1');
+ const createData = [
+ {
+ owners: [{
+ owner: receiverCross,
+ pieces: 1,
+ }],
+ properties: [
+ {key: 'key_0_0', value: Buffer.from('value_0_0')},
+ ],
+ },
+ {
+ owners: [
+ {
+ owner: receiverCross,
+ pieces: 1,
+ },
+ {
+ owner: receiver2Cross,
+ pieces: 2,
+ },
+ ],
+ properties: [
+ {key: 'key_2_0', value: Buffer.from('value_2_0')},
+ {key: 'key_2_1', value: Buffer.from('value_2_1')},
+ {key: 'key_2_2', value: Buffer.from('value_2_2')},
+ ],
+ },
+ ];
+
+ await expect(contract.methods.mintBulkCross(createData).call({from: caller})).to.be.rejectedWith('creation of multiple tokens supported only if they have single owner each');
+ });
});