git.delta.rocks / unique-network / refs/commits / add913f79e3c

difftreelog

Merge pull request #66 from usetech-llc/feature/NFTPAR-280

Greg Zaitsev2021-01-18parents: #2ace66d #a6f9ec6.patch.diff
in: master
Feature/nftpar 280

3 files changed

modifiedpallets/nft/src/lib.rsdiffbeforeafterboth
--- a/pallets/nft/src/lib.rs
+++ b/pallets/nft/src/lib.rs
@@ -419,6 +419,7 @@
         pub AddressTokens get(fn address_tokens): double_map hasher(identity) CollectionId, hasher(twox_64_concat) T::AccountId => Vec<TokenId>;
 
         /// Tokens transfer baskets
+        pub CreateItemBasket get(fn create_item_basket): map hasher(twox_64_concat) (CollectionId, T::AccountId) => T::BlockNumber;
         pub NftTransferBasket get(fn nft_transfer_basket): double_map hasher(identity) CollectionId, hasher(identity) TokenId => T::BlockNumber;
         pub FungibleTransferBasket get(fn fungible_transfer_basket): double_map hasher(identity) CollectionId, hasher(twox_64_concat) T::AccountId => T::BlockNumber;
         pub ReFungibleTransferBasket get(fn refungible_transfer_basket): double_map hasher(identity) CollectionId, hasher(identity) TokenId => T::BlockNumber;
@@ -2297,9 +2298,26 @@
         let mut sponsor: T::AccountId = match IsSubType::<Call<T>>::is_sub_type(call) {
             Some(Call::create_item(collection_id, _owner, _properties)) => {
 
+                // sponsor timeout
+                let block_number = <system::Module<T>>::block_number() as T::BlockNumber;
+
+                let limit = <Collection<T>>::get(collection_id).limits.sponsor_transfer_timeout;
+                let mut sponsored = true;
+                if <CreateItemBasket<T>>::contains_key((collection_id, &who)) {
+                    let last_tx_block = <CreateItemBasket<T>>::get((collection_id, &who));
+                    let limit_time = last_tx_block + limit.into();
+                    if block_number <= limit_time {
+                        sponsored = false;
+                    }
+                }
+                if sponsored {
+                    <CreateItemBasket<T>>::insert((collection_id, who.clone()), block_number);
+                }
+
                 // check free create limit
                 if (<Collection<T>>::get(collection_id).limits.sponsored_data_size >= (_properties.len() as u32)) &&
-                   (<Collection<T>>::get(collection_id).sponsor_confirmed)
+                   (<Collection<T>>::get(collection_id).sponsor_confirmed) &&
+                   (sponsored)
                 {
                     <Collection<T>>::get(collection_id).sponsor
                 } else {
modifiedruntime/src/lib.rsdiffbeforeafterboth
--- a/runtime/src/lib.rs
+++ b/runtime/src/lib.rs
@@ -143,7 +143,7 @@
     spec_name: create_runtime_str!("nft"),
     impl_name: create_runtime_str!("nft"),
     authoring_version: 1,
-    spec_version: 2,
+    spec_version: 3,
     impl_version: 1,
     apis: RUNTIME_API_VERSIONS,
     transaction_version: 1,
modifiedtests/src/confirmSponsorship.test.tsdiffbeforeafterboth
170 });170 });
171 });171 });
172172
173 it('NFT: Sponsoring is rate limited', async () => {173 it('NFT: Sponsoring of transfers is rate limited', async () => {
174 const collectionId = await createCollectionExpectSuccess();174 const collectionId = await createCollectionExpectSuccess();
175 await setCollectionSponsorExpectSuccess(collectionId, bob.address);175 await setCollectionSponsorExpectSuccess(collectionId, bob.address);
176 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');176 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');
285 });285 });
286 });286 });
287
288 it('NFT: Sponsoring of createItem is rate limited', async () => {
289 const collectionId = await createCollectionExpectSuccess();
290 await setCollectionSponsorExpectSuccess(collectionId, bob.address);
291 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');
292
293 // Enable collection white list
294 await enableWhiteListExpectSuccess(alice, collectionId);
295
296 // Enable public minting
297 await enablePublicMintingExpectSuccess(alice, collectionId);
298
299 await usingApi(async (api) => {
300 // Find unused address
301 const zeroBalance = await findUnusedAddress(api);
302
303 // Add zeroBalance address to white list
304 await addToWhiteListExpectSuccess(alice, collectionId, zeroBalance.address);
305
306 // Mint token using unused address as signer - gets sponsored
307 await createItemExpectSuccess(zeroBalance, collectionId, 'NFT', zeroBalance.address);
308
309 // Second mint should fail
310 const AsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());
311
312 const consoleError = console.error;
313 const consoleLog = console.log;
314 console.error = () => {};
315 console.log = () => {};
316 const badTransaction = async function () {
317 await createItemExpectSuccess(zeroBalance, collectionId, 'NFT', zeroBalance.address);
318 };
319 await expect(badTransaction()).to.be.rejectedWith("Inability to pay some fees");
320 console.error = consoleError;
321 console.log = consoleLog;
322 const BsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());
323
324 // Try again after Zero gets some balance - now it should succeed
325 const balancetx = api.tx.balances.transfer(zeroBalance.address, 1e15);
326 await submitTransactionAsync(alice, balancetx);
327 await createItemExpectSuccess(zeroBalance, collectionId, 'NFT', zeroBalance.address);
328
329 expect(BsponsorBalance.isEqualTo(AsponsorBalance)).to.be.true;
330 });
331 });
287332
288});333});
289334