difftreelog
added `collectionNestingRestrictedCollectionIds()` function in `Collection` interface.
in: master
14 files changed
pallets/common/src/erc.rsdiffbeforeafterboth--- a/pallets/common/src/erc.rs
+++ b/pallets/common/src/erc.rs
@@ -493,6 +493,21 @@
<Pallet<T>>::update_permissions(&caller, self, permissions).map_err(dispatch_to_evm::<T>)
}
+ /// Returns nesting for a collection
+ #[solidity(rename_selector = "collectionNestingRestrictedCollectionIds")]
+ fn collection_nesting_restricted_ids(&self) -> Result<(bool, Vec<uint256>)> {
+ let nesting = self.collection.permissions.nesting();
+
+ Ok((
+ nesting.token_owner,
+ nesting
+ .restricted
+ .clone()
+ .map(|b| b.0.into_inner().iter().map(|id| id.0.into()).collect())
+ .unwrap_or_default(),
+ ))
+ }
+
/// Set the collection access method.
/// @param mode Access mode
/// 0 for Normal
pallets/evm-contract-helpers/src/stubs/ContractHelpers.rawdiffbeforeafterbothbinary blob — no preview
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 0xcc1d80ca
+/// @dev the ERC-165 identifier for this interface is 0xeecfdb34
contract Collection is Dummy, ERC165 {
// /// Set collection property.
// ///
@@ -254,6 +254,15 @@
dummy = 0;
}
+ /// Returns nesting for a collection
+ /// @dev EVM selector for this function is: 0x22d25bfe,
+ /// or in textual repr: collectionNestingRestrictedCollectionIds()
+ function collectionNestingRestrictedCollectionIds() public view returns (Tuple21 memory) {
+ require(false, stub_error);
+ dummy;
+ return Tuple21(false, new uint256[](0));
+ }
+
/// Set the collection access method.
/// @param mode Access mode
/// 0 for Normal
@@ -425,6 +434,12 @@
uint256 sub;
}
+/// @dev anonymous struct
+struct Tuple21 {
+ bool field_0;
+ uint256[] field_1;
+}
+
/// @dev Property struct
struct Property {
string key;
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 0xcc1d80ca
+/// @dev the ERC-165 identifier for this interface is 0xeecfdb34
contract Collection is Dummy, ERC165 {
// /// Set collection property.
// ///
@@ -355,6 +355,15 @@
dummy = 0;
}
+ /// Returns nesting for a collection
+ /// @dev EVM selector for this function is: 0x22d25bfe,
+ /// or in textual repr: collectionNestingRestrictedCollectionIds()
+ function collectionNestingRestrictedCollectionIds() public view returns (Tuple34 memory) {
+ require(false, stub_error);
+ dummy;
+ return Tuple34(false, new uint256[](0));
+ }
+
/// Set the collection access method.
/// @param mode Access mode
/// 0 for Normal
@@ -527,6 +536,12 @@
}
/// @dev anonymous struct
+struct Tuple34 {
+ bool field_0;
+ uint256[] field_1;
+}
+
+/// @dev anonymous struct
struct Tuple30 {
address field_0;
uint256 field_1;
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 0xcc1d80ca
+/// @dev the ERC-165 identifier for this interface is 0xeecfdb34
contract Collection is Dummy, ERC165 {
// /// Set collection property.
// ///
@@ -355,6 +355,15 @@
dummy = 0;
}
+ /// Returns nesting for a collection
+ /// @dev EVM selector for this function is: 0x22d25bfe,
+ /// or in textual repr: collectionNestingRestrictedCollectionIds()
+ function collectionNestingRestrictedCollectionIds() public view returns (Tuple33 memory) {
+ require(false, stub_error);
+ dummy;
+ return Tuple33(false, new uint256[](0));
+ }
+
/// Set the collection access method.
/// @param mode Access mode
/// 0 for Normal
@@ -527,6 +536,12 @@
}
/// @dev anonymous struct
+struct Tuple33 {
+ bool field_0;
+ uint256[] field_1;
+}
+
+/// @dev anonymous struct
struct Tuple29 {
address field_0;
uint256 field_1;
pallets/refungible/src/stubs/UniqueRefungibleToken.rawdiffbeforeafterbothbinary blob — no preview
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": "collectionNestingRestrictedCollectionIds",
+ "outputs": [
+ {
+ "components": [
+ { "internalType": "bool", "name": "field_0", "type": "bool" },
+ {
+ "internalType": "uint256[]",
+ "name": "field_1",
+ "type": "uint256[]"
+ }
+ ],
+ "internalType": "struct Tuple21",
+ "name": "",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
"name": "collectionOwner",
"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": "collectionNestingRestrictedCollectionIds",
+ "outputs": [
+ {
+ "components": [
+ { "internalType": "bool", "name": "field_0", "type": "bool" },
+ {
+ "internalType": "uint256[]",
+ "name": "field_1",
+ "type": "uint256[]"
+ }
+ ],
+ "internalType": "struct Tuple34",
+ "name": "",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
"name": "collectionOwner",
"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": "collectionNestingRestrictedCollectionIds",
+ "outputs": [
+ {
+ "components": [
+ { "internalType": "bool", "name": "field_0", "type": "bool" },
+ {
+ "internalType": "uint256[]",
+ "name": "field_1",
+ "type": "uint256[]"
+ }
+ ],
+ "internalType": "struct Tuple33",
+ "name": "",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
"name": "collectionOwner",
"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 0xcc1d80ca
+/// @dev the ERC-165 identifier for this interface is 0xeecfdb34
interface Collection is Dummy, ERC165 {
// /// Set collection property.
// ///
@@ -166,6 +166,11 @@
/// or in textual repr: setCollectionNesting(bool,address[])
function setCollectionNesting(bool enable, address[] memory collections) external;
+ /// Returns nesting for a collection
+ /// @dev EVM selector for this function is: 0x22d25bfe,
+ /// or in textual repr: collectionNestingRestrictedCollectionIds()
+ function collectionNestingRestrictedCollectionIds() external view returns (Tuple20 memory);
+
/// Set the collection access method.
/// @param mode Access mode
/// 0 for Normal
@@ -278,6 +283,12 @@
uint256 sub;
}
+/// @dev anonymous struct
+struct Tuple20 {
+ bool field_0;
+ uint256[] field_1;
+}
+
/// @dev Property struct
struct Property {
string key;
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 0xcc1d80ca
+/// @dev the ERC-165 identifier for this interface is 0xeecfdb34
interface Collection is Dummy, ERC165 {
// /// Set collection property.
// ///
@@ -233,6 +233,11 @@
/// or in textual repr: setCollectionNesting(bool,address[])
function setCollectionNesting(bool enable, address[] memory collections) external;
+ /// Returns nesting for a collection
+ /// @dev EVM selector for this function is: 0x22d25bfe,
+ /// or in textual repr: collectionNestingRestrictedCollectionIds()
+ function collectionNestingRestrictedCollectionIds() external view returns (Tuple31 memory);
+
/// Set the collection access method.
/// @param mode Access mode
/// 0 for Normal
@@ -346,6 +351,12 @@
}
/// @dev anonymous struct
+struct Tuple31 {
+ bool field_0;
+ uint256[] field_1;
+}
+
+/// @dev anonymous struct
struct Tuple27 {
address 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 0xcc1d80ca
+/// @dev the ERC-165 identifier for this interface is 0xeecfdb34
interface Collection is Dummy, ERC165 {
// /// Set collection property.
// ///
@@ -233,6 +233,11 @@
/// or in textual repr: setCollectionNesting(bool,address[])
function setCollectionNesting(bool enable, address[] memory collections) external;
+ /// Returns nesting for a collection
+ /// @dev EVM selector for this function is: 0x22d25bfe,
+ /// or in textual repr: collectionNestingRestrictedCollectionIds()
+ function collectionNestingRestrictedCollectionIds() external view returns (Tuple30 memory);
+
/// Set the collection access method.
/// @param mode Access mode
/// 0 for Normal
@@ -346,6 +351,12 @@
}
/// @dev anonymous struct
+struct Tuple30 {
+ bool field_0;
+ uint256[] field_1;
+}
+
+/// @dev anonymous struct
struct Tuple26 {
address field_0;
uint256 field_1;
tests/src/eth/nesting/nest.test.tsdiffbeforeafterboth1import {IKeyringPair} from '@polkadot/types/types';2import {Contract} from 'web3-eth-contract';34import {itEth, EthUniqueHelper, usingEthPlaygrounds, expect} from '../util';56const createNestingCollection = async (7 helper: EthUniqueHelper,8 owner: string,9): Promise<{ collectionId: number, collectionAddress: string, contract: Contract }> => {10 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');1112 const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);13 await contract.methods.setCollectionNesting(true).send({from: owner});1415 return {collectionId, collectionAddress, contract};16};171819describe('EVM nesting tests group', () => {20 let donor: IKeyringPair;2122 before(async function() {23 await usingEthPlaygrounds(async (_, privateKey) => {24 donor = await privateKey({filename: __filename});25 });26 });2728 describe('Integration Test: EVM Nesting', () => {29 itEth('NFT: allows an Owner to nest/unnest their token', async ({helper}) => {30 const owner = await helper.eth.createAccountWithBalance(donor);31 const {collectionId, contract} = await createNestingCollection(helper, owner);3233 // Create a token to be nested to34 const mintingTargetNFTTokenIdResult = await contract.methods.mint(owner).send({from: owner});35 const targetNFTTokenId = mintingTargetNFTTokenIdResult.events.Transfer.returnValues.tokenId;36 const targetNftTokenAddress = helper.ethAddress.fromTokenId(collectionId, targetNFTTokenId);3738 // Create a nested token39 const mintingFirstTokenIdResult = await contract.methods.mint(targetNftTokenAddress).send({from: owner});40 const firstTokenId = mintingFirstTokenIdResult.events.Transfer.returnValues.tokenId;41 expect(await contract.methods.ownerOf(firstTokenId).call()).to.be.equal(targetNftTokenAddress);4243 // Create a token to be nested and nest44 const mintingSecondTokenIdResult = await contract.methods.mint(owner).send({from: owner});45 const secondTokenId = mintingSecondTokenIdResult.events.Transfer.returnValues.tokenId;4647 await contract.methods.transfer(targetNftTokenAddress, secondTokenId).send({from: owner});48 expect(await contract.methods.ownerOf(secondTokenId).call()).to.be.equal(targetNftTokenAddress);4950 // Unnest token back51 await contract.methods.transferFrom(targetNftTokenAddress, owner, secondTokenId).send({from: owner});52 expect(await contract.methods.ownerOf(secondTokenId).call()).to.be.equal(owner);53 });5455 itEth('NFT: allows an Owner to nest/unnest their token (Restricted nesting)', async ({helper}) => {56 const owner = await helper.eth.createAccountWithBalance(donor);5758 const {collectionId: collectionIdA, collectionAddress: collectionAddressA, contract: contractA} = await createNestingCollection(helper, owner);59 const {collectionAddress: collectionAddressB, contract: contractB} = await createNestingCollection(helper, owner);60 await contractA.methods.setCollectionNesting(true, [collectionAddressA, collectionAddressB]).send({from: owner});6162 // Create a token to nest into63 const mintingtargetNftTokenIdResult = await contractA.methods.mint(owner).send({from: owner});64 const targetNftTokenId = mintingtargetNftTokenIdResult.events.Transfer.returnValues.tokenId;65 const nftTokenAddressA1 = helper.ethAddress.fromTokenId(collectionIdA, targetNftTokenId);6667 // Create a token for nesting in the same collection as the target68 const mintingTokenIdAResult = await contractA.methods.mint(owner).send({from: owner});69 const nftTokenIdA = mintingTokenIdAResult.events.Transfer.returnValues.tokenId;7071 // Create a token for nesting in a different collection72 const mintingTokenIdBResult = await contractB.methods.mint(owner).send({from: owner});73 const nftTokenIdB = mintingTokenIdBResult.events.Transfer.returnValues.tokenId;7475 // Nest76 await contractA.methods.transfer(nftTokenAddressA1, nftTokenIdA).send({from: owner});77 expect(await contractA.methods.ownerOf(nftTokenIdA).call()).to.be.equal(nftTokenAddressA1);7879 await contractB.methods.transfer(nftTokenAddressA1, nftTokenIdB).send({from: owner});80 expect(await contractB.methods.ownerOf(nftTokenIdB).call()).to.be.equal(nftTokenAddressA1);81 });82 });8384 describe('Negative Test: EVM Nesting', () => {85 itEth('NFT: disallows to nest token if nesting is disabled', async ({helper}) => {86 const owner = await helper.eth.createAccountWithBalance(donor);8788 const {collectionId, contract} = await createNestingCollection(helper, owner);89 await contract.methods.setCollectionNesting(false).send({from: owner});9091 // Create a token to nest into92 const mintingTargetTokenIdResult = await contract.methods.mint(owner).send({from: owner});93 const targetTokenId = mintingTargetTokenIdResult.events.Transfer.returnValues.tokenId;94 const targetNftTokenAddress = helper.ethAddress.fromTokenId(collectionId, targetTokenId);9596 // Create a token to nest97 const mintingNftTokenIdResult = await contract.methods.mint(owner).send({from: owner});98 const nftTokenId = mintingNftTokenIdResult.events.Transfer.returnValues.tokenId;99100 // Try to nest101 await expect(contract.methods102 .transfer(targetNftTokenAddress, nftTokenId)103 .call({from: owner})).to.be.rejectedWith('UserIsNotAllowedToNest');104 });105106 itEth('NFT: disallows a non-Owner to nest someone else\'s token', async ({helper}) => {107 const owner = await helper.eth.createAccountWithBalance(donor);108 const malignant = await helper.eth.createAccountWithBalance(donor);109110 const {collectionId, contract} = await createNestingCollection(helper, owner);111112 // Mint a token113 const mintingTargetTokenIdResult = await contract.methods.mint(owner).send({from: owner});114 const targetTokenId = mintingTargetTokenIdResult.events.Transfer.returnValues.tokenId;115 const targetTokenAddress = helper.ethAddress.fromTokenId(collectionId, targetTokenId);116117 // Mint a token belonging to a different account118 const mintingTokenIdResult = await contract.methods.mint(malignant).send({from: owner});119 const tokenId = mintingTokenIdResult.events.Transfer.returnValues.tokenId;120121 // Try to nest one token in another as a non-owner account122 await expect(contract.methods123 .transfer(targetTokenAddress, tokenId)124 .call({from: malignant})).to.be.rejectedWith('UserIsNotAllowedToNest');125 });126127 itEth('NFT: disallows a non-Owner to nest someone else\'s token (Restricted nesting)', async ({helper}) => {128 const owner = await helper.eth.createAccountWithBalance(donor);129 const malignant = await helper.eth.createAccountWithBalance(donor);130131 const {collectionId: collectionIdA, collectionAddress: collectionAddressA, contract: contractA} = await createNestingCollection(helper, owner);132 const {collectionAddress: collectionAddressB, contract: contractB} = await createNestingCollection(helper, owner);133134 await contractA.methods.setCollectionNesting(true, [collectionAddressA, collectionAddressB]).send({from: owner});135136 // Create a token in one collection137 const mintingTokenIdAResult = await contractA.methods.mint(owner).send({from: owner});138 const nftTokenIdA = mintingTokenIdAResult.events.Transfer.returnValues.tokenId;139 const nftTokenAddressA = helper.ethAddress.fromTokenId(collectionIdA, nftTokenIdA);140141 // Create a token in another collection142 const mintingTokenIdBResult = await contractB.methods.mint(malignant).send({from: owner});143 const nftTokenIdB = mintingTokenIdBResult.events.Transfer.returnValues.tokenId;144145 // Try to drag someone else's token into the other collection and nest146 await expect(contractB.methods147 .transfer(nftTokenAddressA, nftTokenIdB)148 .call({from: malignant})).to.be.rejectedWith('UserIsNotAllowedToNest');149 });150151 itEth('NFT: disallows to nest token in an unlisted collection', async ({helper}) => {152 const owner = await helper.eth.createAccountWithBalance(donor);153154 const {collectionId: collectionIdA, collectionAddress: collectionAddressA, contract: contractA} = await createNestingCollection(helper, owner);155 const {contract: contractB} = await createNestingCollection(helper, owner);156157 await contractA.methods.setCollectionNesting(true, [collectionAddressA]).send({from: owner});158159 // Create a token in one collection160 const mintingTokenIdAResult = await contractA.methods.mint(owner).send({from: owner});161 const nftTokenIdA = mintingTokenIdAResult.events.Transfer.returnValues.tokenId;162 const nftTokenAddressA = helper.ethAddress.fromTokenId(collectionIdA, nftTokenIdA);163164 // Create a token in another collection165 const mintingTokenIdBResult = await contractB.methods.mint(owner).send({from: owner});166 const nftTokenIdB = mintingTokenIdBResult.events.Transfer.returnValues.tokenId;167168169 // Try to nest into a token in the other collection, disallowed in the first170 await expect(contractB.methods171 .transfer(nftTokenAddressA, nftTokenIdB)172 .call()).to.be.rejectedWith('SourceCollectionIsNotAllowedToNest');173 });174 });175});1import {IKeyringPair} from '@polkadot/types/types';2import {Contract} from 'web3-eth-contract';34import {itEth, EthUniqueHelper, usingEthPlaygrounds, expect} from '../util';56const createNestingCollection = async (7 helper: EthUniqueHelper,8 owner: string,9): Promise<{ collectionId: number, collectionAddress: string, contract: Contract }> => {10 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');1112 const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);13 await contract.methods.setCollectionNesting(true).send({from: owner});1415 return {collectionId, collectionAddress, contract};16};171819describe('EVM nesting tests group', () => {20 let donor: IKeyringPair;2122 before(async function() {23 await usingEthPlaygrounds(async (_, privateKey) => {24 donor = await privateKey({filename: __filename});25 });26 });2728 describe('Integration Test: EVM Nesting', () => {29 itEth('NFT: allows an Owner to nest/unnest their token', async ({helper}) => {30 const owner = await helper.eth.createAccountWithBalance(donor);31 const {collectionId, contract} = await createNestingCollection(helper, owner);3233 // Create a token to be nested to34 const mintingTargetNFTTokenIdResult = await contract.methods.mint(owner).send({from: owner});35 const targetNFTTokenId = mintingTargetNFTTokenIdResult.events.Transfer.returnValues.tokenId;36 const targetNftTokenAddress = helper.ethAddress.fromTokenId(collectionId, targetNFTTokenId);3738 // Create a nested token39 const mintingFirstTokenIdResult = await contract.methods.mint(targetNftTokenAddress).send({from: owner});40 const firstTokenId = mintingFirstTokenIdResult.events.Transfer.returnValues.tokenId;41 expect(await contract.methods.ownerOf(firstTokenId).call()).to.be.equal(targetNftTokenAddress);4243 // Create a token to be nested and nest44 const mintingSecondTokenIdResult = await contract.methods.mint(owner).send({from: owner});45 const secondTokenId = mintingSecondTokenIdResult.events.Transfer.returnValues.tokenId;4647 await contract.methods.transfer(targetNftTokenAddress, secondTokenId).send({from: owner});48 expect(await contract.methods.ownerOf(secondTokenId).call()).to.be.equal(targetNftTokenAddress);4950 // Unnest token back51 await contract.methods.transferFrom(targetNftTokenAddress, owner, secondTokenId).send({from: owner});52 expect(await contract.methods.ownerOf(secondTokenId).call()).to.be.equal(owner);53 });54 55 itEth('NFT: collectionNestingRestrictedCollectionIds()', async ({helper}) => {56 const owner = await helper.eth.createAccountWithBalance(donor);57 const {collectionId: unnestedCollsectionId, collectionAddress: unnsetedCollectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');58 const unnestedContract = helper.ethNativeContract.collection(unnsetedCollectionAddress, 'nft', owner);59 expect(await unnestedContract.methods.collectionNestingRestrictedCollectionIds().call({from: owner})).to.be.like([false, []]);60 61 const {contract} = await createNestingCollection(helper, owner);62 expect(await contract.methods.collectionNestingRestrictedCollectionIds().call({from: owner})).to.be.like([true, []]);63 await contract.methods.setCollectionNesting(true, [unnsetedCollectionAddress]).send({from: owner});64 expect(await contract.methods.collectionNestingRestrictedCollectionIds().call({from: owner})).to.be.like([true, [unnestedCollsectionId.toString()]]);65 66 });67 68 itEth('NFT: allows an Owner to nest/unnest their token (Restricted nesting)', async ({helper}) => {69 const owner = await helper.eth.createAccountWithBalance(donor);7071 const {collectionId: collectionIdA, collectionAddress: collectionAddressA, contract: contractA} = await createNestingCollection(helper, owner);72 const {collectionAddress: collectionAddressB, contract: contractB} = await createNestingCollection(helper, owner);73 await contractA.methods.setCollectionNesting(true, [collectionAddressA, collectionAddressB]).send({from: owner});7475 // Create a token to nest into76 const mintingtargetNftTokenIdResult = await contractA.methods.mint(owner).send({from: owner});77 const targetNftTokenId = mintingtargetNftTokenIdResult.events.Transfer.returnValues.tokenId;78 const nftTokenAddressA1 = helper.ethAddress.fromTokenId(collectionIdA, targetNftTokenId);7980 // Create a token for nesting in the same collection as the target81 const mintingTokenIdAResult = await contractA.methods.mint(owner).send({from: owner});82 const nftTokenIdA = mintingTokenIdAResult.events.Transfer.returnValues.tokenId;8384 // Create a token for nesting in a different collection85 const mintingTokenIdBResult = await contractB.methods.mint(owner).send({from: owner});86 const nftTokenIdB = mintingTokenIdBResult.events.Transfer.returnValues.tokenId;8788 // Nest89 await contractA.methods.transfer(nftTokenAddressA1, nftTokenIdA).send({from: owner});90 expect(await contractA.methods.ownerOf(nftTokenIdA).call()).to.be.equal(nftTokenAddressA1);9192 await contractB.methods.transfer(nftTokenAddressA1, nftTokenIdB).send({from: owner});93 expect(await contractB.methods.ownerOf(nftTokenIdB).call()).to.be.equal(nftTokenAddressA1);94 });95 });9697 describe('Negative Test: EVM Nesting', () => {98 itEth('NFT: disallows to nest token if nesting is disabled', async ({helper}) => {99 const owner = await helper.eth.createAccountWithBalance(donor);100101 const {collectionId, contract} = await createNestingCollection(helper, owner);102 await contract.methods.setCollectionNesting(false).send({from: owner});103104 // Create a token to nest into105 const mintingTargetTokenIdResult = await contract.methods.mint(owner).send({from: owner});106 const targetTokenId = mintingTargetTokenIdResult.events.Transfer.returnValues.tokenId;107 const targetNftTokenAddress = helper.ethAddress.fromTokenId(collectionId, targetTokenId);108109 // Create a token to nest110 const mintingNftTokenIdResult = await contract.methods.mint(owner).send({from: owner});111 const nftTokenId = mintingNftTokenIdResult.events.Transfer.returnValues.tokenId;112113 // Try to nest114 await expect(contract.methods115 .transfer(targetNftTokenAddress, nftTokenId)116 .call({from: owner})).to.be.rejectedWith('UserIsNotAllowedToNest');117 });118119 itEth('NFT: disallows a non-Owner to nest someone else\'s token', async ({helper}) => {120 const owner = await helper.eth.createAccountWithBalance(donor);121 const malignant = await helper.eth.createAccountWithBalance(donor);122123 const {collectionId, contract} = await createNestingCollection(helper, owner);124125 // Mint a token126 const mintingTargetTokenIdResult = await contract.methods.mint(owner).send({from: owner});127 const targetTokenId = mintingTargetTokenIdResult.events.Transfer.returnValues.tokenId;128 const targetTokenAddress = helper.ethAddress.fromTokenId(collectionId, targetTokenId);129130 // Mint a token belonging to a different account131 const mintingTokenIdResult = await contract.methods.mint(malignant).send({from: owner});132 const tokenId = mintingTokenIdResult.events.Transfer.returnValues.tokenId;133134 // Try to nest one token in another as a non-owner account135 await expect(contract.methods136 .transfer(targetTokenAddress, tokenId)137 .call({from: malignant})).to.be.rejectedWith('UserIsNotAllowedToNest');138 });139140 itEth('NFT: disallows a non-Owner to nest someone else\'s token (Restricted nesting)', async ({helper}) => {141 const owner = await helper.eth.createAccountWithBalance(donor);142 const malignant = await helper.eth.createAccountWithBalance(donor);143144 const {collectionId: collectionIdA, collectionAddress: collectionAddressA, contract: contractA} = await createNestingCollection(helper, owner);145 const {collectionAddress: collectionAddressB, contract: contractB} = await createNestingCollection(helper, owner);146147 await contractA.methods.setCollectionNesting(true, [collectionAddressA, collectionAddressB]).send({from: owner});148149 // Create a token in one collection150 const mintingTokenIdAResult = await contractA.methods.mint(owner).send({from: owner});151 const nftTokenIdA = mintingTokenIdAResult.events.Transfer.returnValues.tokenId;152 const nftTokenAddressA = helper.ethAddress.fromTokenId(collectionIdA, nftTokenIdA);153154 // Create a token in another collection155 const mintingTokenIdBResult = await contractB.methods.mint(malignant).send({from: owner});156 const nftTokenIdB = mintingTokenIdBResult.events.Transfer.returnValues.tokenId;157158 // Try to drag someone else's token into the other collection and nest159 await expect(contractB.methods160 .transfer(nftTokenAddressA, nftTokenIdB)161 .call({from: malignant})).to.be.rejectedWith('UserIsNotAllowedToNest');162 });163164 itEth('NFT: disallows to nest token in an unlisted collection', async ({helper}) => {165 const owner = await helper.eth.createAccountWithBalance(donor);166167 const {collectionId: collectionIdA, collectionAddress: collectionAddressA, contract: contractA} = await createNestingCollection(helper, owner);168 const {contract: contractB} = await createNestingCollection(helper, owner);169170 await contractA.methods.setCollectionNesting(true, [collectionAddressA]).send({from: owner});171172 // Create a token in one collection173 const mintingTokenIdAResult = await contractA.methods.mint(owner).send({from: owner});174 const nftTokenIdA = mintingTokenIdAResult.events.Transfer.returnValues.tokenId;175 const nftTokenAddressA = helper.ethAddress.fromTokenId(collectionIdA, nftTokenIdA);176177 // Create a token in another collection178 const mintingTokenIdBResult = await contractB.methods.mint(owner).send({from: owner});179 const nftTokenIdB = mintingTokenIdBResult.events.Transfer.returnValues.tokenId;180181182 // Try to nest into a token in the other collection, disallowed in the first183 await expect(contractB.methods184 .transfer(nftTokenAddressA, nftTokenIdB)185 .call()).to.be.rejectedWith('SourceCollectionIsNotAllowedToNest');186 });187 });188});