git.delta.rocks / unique-network / refs/commits / 752e2b099754

difftreelog

fix update weighting for mintBulkCross and forbid multiple owners + multipe tokens

Grigoriy Simonov2023-09-22parent: #0c121c7.patch.diff
in: master

2 files changed

modifiedpallets/refungible/src/erc.rsdiffbeforeafterboth
--- a/pallets/refungible/src/erc.rs
+++ b/pallets/refungible/src/erc.rs
@@ -1041,7 +1041,11 @@
 
 	/// @notice Function to mint a token.
 	/// @param tokenProperties Properties of minted token
-	#[weight(<SelfWeightOf<T>>::create_multiple_items(token_properties.len() as u32) + <SelfWeightOf<T>>::set_token_properties(token_properties.len() as u32))]
+	#[weight(if token_properties.len() == 1 {
+		<SelfWeightOf<T>>::create_multiple_items_ex_multiple_owners(token_properties.iter().next().unwrap().owners.len() as u32)
+	} else {
+		<SelfWeightOf<T>>::create_multiple_items_ex_multiple_items(token_properties.len() as u32)
+	} + <SelfWeightOf<T>>::set_token_properties(token_properties.len() as u32))]
 	fn mint_bulk_cross(
 		&mut self,
 		caller: Caller,
@@ -1051,9 +1055,17 @@
 		let budget = self
 			.recorder
 			.weight_calls_budget(<StructureWeight<T>>::find_parent());
+		let has_multiple_tokens = token_properties.len() > 1;
 
 		let mut create_rft_data = Vec::with_capacity(token_properties.len());
 		for MintTokenData { owners, properties } in token_properties {
+			let has_multiple_owners = owners.len() > 1;
+			if has_multiple_tokens & has_multiple_owners {
+				return Err(
+					"creation of multiple tokens supported only if they have single owner each"
+						.into(),
+				);
+			}
 			let users: BoundedBTreeMap<_, _, _> = owners
 				.into_iter()
 				.map(|data| Ok((data.owner.into_sub_cross_account::<T>()?, data.pieces)))
modifiedtests/src/eth/reFungible.test.tsdiffbeforeafterboth
126 }126 }
127 });127 });
128128
129 itEth('Can perform mintBulkCross()', async ({helper}) => {129 itEth('Can perform mintBulkCross() with multiple tokens', async ({helper}) => {
130 const caller = await helper.eth.createAccountWithBalance(donor);130 const caller = await helper.eth.createAccountWithBalance(donor);
131 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);
136134
137 const permissions = [135 const permissions = [
138 {code: TokenPermissionField.Mutable, value: true},136 {code: TokenPermissionField.Mutable, value: true},
160 ).send();158 ).send();
161159
162 const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', caller);160 const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', caller);
163 {
164 const nextTokenId = await contract.methods.nextTokenId().call();161 const nextTokenId = await contract.methods.nextTokenId().call();
165 expect(nextTokenId).to.be.equal('1');162 expect(nextTokenId).to.be.equal('1');
166 const result = await contract.methods.mintBulkCross([163 const result = await contract.methods.mintBulkCross([
188 {
189 owner: receiverCross,185 owner: receiverCross,
190 pieces: 1,186 pieces: 1,
191 },187 }],
192 {
193 owner: receiver2Cross,
194 pieces: 2,
195 },
196 ],
197 properties: [188 properties: [
198 {key: 'key_2_0', value: Buffer.from('value_2_0')},189 {key: 'key_2_0', value: Buffer.from('value_2_0')},
207 const event = events[i];198 const event = events[i];
208 expect(event.address).to.equal(collectionAddress);199 expect(event.address).to.equal(collectionAddress);
209 expect(event.returnValues.from).to.equal('0x0000000000000000000000000000000000000000');200 expect(event.returnValues.from).to.equal('0x0000000000000000000000000000000000000000');
210 if(i == 0 || i == 1)
211 expect(event.returnValues.to).to.equal(receiver);201 expect(event.returnValues.to).to.equal(receiver);
212 else
213 expect(event.returnValues.to).to.equal('0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF');
214
215 expect(event.returnValues.tokenId).to.equal(`${+nextTokenId + i}`);202 expect(event.returnValues.tokenId).to.equal(`${+nextTokenId + i}`);
216 }203 }
234 ['key_2_2', helper.getWeb3().utils.toHex('value_2_2')],221 ['key_2_2', helper.getWeb3().utils.toHex('value_2_2')],
235 ],222 ],
236 ]);223 ]);
237 }
238 });224 });
225
226 itEth('Can perform mintBulkCross() with multiple owners', async ({helper}) => {
227 const caller = await helper.eth.createAccountWithBalance(donor);
228 const callerCross = helper.ethCrossAccount.fromAddress(caller);
229 const receiver = helper.eth.createAccount();
230 const receiverCross = helper.ethCrossAccount.fromAddress(receiver);
231 const receiver2 = helper.eth.createAccount();
232 const receiver2Cross = helper.ethCrossAccount.fromAddress(receiver2);
233
234 const permissions = [
235 {code: TokenPermissionField.Mutable, value: true},
236 {code: TokenPermissionField.TokenOwner, value: true},
237 {code: TokenPermissionField.CollectionAdmin, value: true},
238 ];
239 const {collectionAddress} = await helper.eth.createCollection(
240 caller,
241 {
242 ...CREATE_COLLECTION_DATA_DEFAULTS,
243 name: 'A',
244 description: 'B',
245 tokenPrefix: 'C',
246 collectionMode: 'rft',
247 adminList: [callerCross],
248 tokenPropertyPermissions: [
249 {key: 'key_2_0', permissions},
250 {key: 'key_2_1', permissions},
251 {key: 'key_2_2', permissions},
252 ],
253 },
254 ).send();
255
256 const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', caller);
257 const nextTokenId = await contract.methods.nextTokenId().call();
258 expect(nextTokenId).to.be.equal('1');
259 const result = await contract.methods.mintBulkCross([{
260 owners: [
261 {
262 owner: receiverCross,
263 pieces: 1,
264 },
265 {
266 owner: receiver2Cross,
267 pieces: 2,
268 },
269 ],
270 properties: [
271 {key: 'key_2_0', value: Buffer.from('value_2_0')},
272 {key: 'key_2_1', value: Buffer.from('value_2_1')},
273 {key: 'key_2_2', value: Buffer.from('value_2_2')},
274 ],
275 }]).send({from: caller});
276 const event = result.events.Transfer;
277 expect(event.address).to.equal(collectionAddress);
278 expect(event.returnValues.from).to.equal('0x0000000000000000000000000000000000000000');
279 expect(event.returnValues.to).to.equal('0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF');
280 expect(event.returnValues.tokenId).to.equal(`${+nextTokenId}`);
281
282 const properties = [
283 await contract.methods.properties(+nextTokenId, []).call(),
284 ];
285 expect(properties).to.be.deep.equal([[
286 ['key_2_0', helper.getWeb3().utils.toHex('value_2_0')],
287 ['key_2_1', helper.getWeb3().utils.toHex('value_2_1')],
288 ['key_2_2', helper.getWeb3().utils.toHex('value_2_2')],
289 ]]);
290 });
239291
240 itEth('Can perform setApprovalForAll()', async ({helper}) => {292 itEth('Can perform setApprovalForAll()', async ({helper}) => {
241 const owner = await helper.eth.createAccountWithBalance(donor);293 const owner = await helper.eth.createAccountWithBalance(donor);
899 await expect(contract.methods.transferFromCross(ownerCross, recieverCross, token.tokenId).send({from: spender})).to.be.rejected;951 await expect(contract.methods.transferFromCross(ownerCross, recieverCross, token.tokenId).send({from: spender})).to.be.rejected;
900 });952 });
953
954 itEth('[negative] Can perform mintBulkCross() with multiple owners and multiple tokens', async ({helper}) => {
955 const caller = await helper.eth.createAccountWithBalance(donor);
956 const callerCross = helper.ethCrossAccount.fromAddress(caller);
957 const receiver = helper.eth.createAccount();
958 const receiverCross = helper.ethCrossAccount.fromAddress(receiver);
959 const receiver2 = helper.eth.createAccount();
960 const receiver2Cross = helper.ethCrossAccount.fromAddress(receiver2);
961
962 const permissions = [
963 {code: TokenPermissionField.Mutable, value: true},
964 {code: TokenPermissionField.TokenOwner, value: true},
965 {code: TokenPermissionField.CollectionAdmin, value: true},
966 ];
967 const {collectionAddress} = await helper.eth.createCollection(
968 caller,
969 {
970 ...CREATE_COLLECTION_DATA_DEFAULTS,
971 name: 'A',
972 description: 'B',
973 tokenPrefix: 'C',
974 collectionMode: 'rft',
975 adminList: [callerCross],
976 tokenPropertyPermissions: [
977 {key: 'key_0_0', permissions},
978 {key: 'key_2_0', permissions},
979 {key: 'key_2_1', permissions},
980 {key: 'key_2_2', permissions},
981 ],
982 },
983 ).send();
984
985 const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', caller);
986 const nextTokenId = await contract.methods.nextTokenId().call();
987 expect(nextTokenId).to.be.equal('1');
988 const createData = [
989 {
990 owners: [{
991 owner: receiverCross,
992 pieces: 1,
993 }],
994 properties: [
995 {key: 'key_0_0', value: Buffer.from('value_0_0')},
996 ],
997 },
998 {
999 owners: [
1000 {
1001 owner: receiverCross,
1002 pieces: 1,
1003 },
1004 {
1005 owner: receiver2Cross,
1006 pieces: 2,
1007 },
1008 ],
1009 properties: [
1010 {key: 'key_2_0', value: Buffer.from('value_2_0')},
1011 {key: 'key_2_1', value: Buffer.from('value_2_1')},
1012 {key: 'key_2_2', value: Buffer.from('value_2_2')},
1013 ],
1014 },
1015 ];
1016
1017 await expect(contract.methods.mintBulkCross(createData).call({from: caller})).to.be.rejectedWith('creation of multiple tokens supported only if they have single owner each');
1018 });
901});1019});
9021020