difftreelog
Merge pull request #826 from UniqueNetwork/fix/deprecate-eth-methods
in: master
Deprecate ethereum methods
9 files changed
tests/src/eth/abi/fungibleDeprecated.jsondiffbeforeafterboth--- a/tests/src/eth/abi/fungibleDeprecated.json
+++ b/tests/src/eth/abi/fungibleDeprecated.json
@@ -88,14 +88,5 @@
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
- },
- {
- "inputs": [
- { "internalType": "address", "name": "newOwner", "type": "address" }
- ],
- "name": "changeCollectionOwner",
- "outputs": [],
- "stateMutability": "nonpayable",
- "type": "function"
}
]
tests/src/eth/abi/nonFungible.jsondiffbeforeafterboth--- a/tests/src/eth/abi/nonFungible.json
+++ b/tests/src/eth/abi/nonFungible.json
@@ -51,12 +51,6 @@
},
{
"anonymous": false,
- "inputs": [],
- "name": "MintingFinished",
- "type": "event"
- },
- {
- "anonymous": false,
"inputs": [
{
"indexed": true,
@@ -420,13 +414,6 @@
"name": "description",
"outputs": [{ "internalType": "string", "name": "", "type": "string" }],
"stateMutability": "view",
- "type": "function"
- },
- {
- "inputs": [],
- "name": "finishMinting",
- "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
- "stateMutability": "nonpayable",
"type": "function"
},
{
@@ -513,13 +500,6 @@
"name": "mintWithTokenURI",
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
"stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "inputs": [],
- "name": "mintingFinished",
- "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
- "stateMutability": "view",
"type": "function"
},
{
tests/src/eth/abi/reFungible.jsondiffbeforeafterboth--- a/tests/src/eth/abi/reFungible.json
+++ b/tests/src/eth/abi/reFungible.json
@@ -51,12 +51,6 @@
},
{
"anonymous": false,
- "inputs": [],
- "name": "MintingFinished",
- "type": "event"
- },
- {
- "anonymous": false,
"inputs": [
{
"indexed": true,
@@ -402,13 +396,6 @@
"name": "description",
"outputs": [{ "internalType": "string", "name": "", "type": "string" }],
"stateMutability": "view",
- "type": "function"
- },
- {
- "inputs": [],
- "name": "finishMinting",
- "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
- "stateMutability": "nonpayable",
"type": "function"
},
{
@@ -495,13 +482,6 @@
"name": "mintWithTokenURI",
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
"stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "inputs": [],
- "name": "mintingFinished",
- "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
- "stateMutability": "view",
"type": "function"
},
{
tests/src/eth/abi/reFungibleDeprecated.jsondiffbeforeafterboth--- a/tests/src/eth/abi/reFungibleDeprecated.json
+++ b/tests/src/eth/abi/reFungibleDeprecated.json
@@ -82,6 +82,17 @@
},
{
"inputs": [
+ { "internalType": "uint256", "name": "tokenId", "type": "uint256" },
+ { "internalType": "string", "name": "key", "type": "string" },
+ { "internalType": "bytes", "name": "value", "type": "bytes" }
+ ],
+ "name": "setProperty",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
{ "internalType": "address", "name": "newOwner", "type": "address" }
],
"name": "changeCollectionOwner",
tests/src/eth/abi/reFungibleToken.jsondiffbeforeafterboth--- a/tests/src/eth/abi/reFungibleToken.json
+++ b/tests/src/eth/abi/reFungibleToken.json
@@ -98,16 +98,6 @@
},
{
"inputs": [
- { "internalType": "address", "name": "from", "type": "address" },
- { "internalType": "uint256", "name": "amount", "type": "uint256" }
- ],
- "name": "burnFrom",
- "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "inputs": [
{
"components": [
{ "internalType": "address", "name": "eth", "type": "address" },
tests/src/eth/abi/reFungibleTokenDeprecated.jsondiffbeforeafterboth--- /dev/null
+++ b/tests/src/eth/abi/reFungibleTokenDeprecated.json
@@ -0,0 +1,12 @@
+[
+ {
+ "inputs": [
+ { "internalType": "address", "name": "from", "type": "address" },
+ { "internalType": "uint256", "name": "amount", "type": "uint256" }
+ ],
+ "name": "burnFrom",
+ "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ }
+]
tests/src/eth/reFungible.test.tsdiffbeforeafterboth1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617import {Pallets, requirePalletsOrSkip} from '../util';18import {expect, itEth, usingEthPlaygrounds} from './util';19import {IKeyringPair} from '@polkadot/types/types';20import {ITokenPropertyPermission} from '../util/playgrounds/types';2122describe('Refungible: Information getting', () => {23 let donor: IKeyringPair;2425 before(async function() {26 await usingEthPlaygrounds(async (helper, privateKey) => {27 requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);2829 donor = await privateKey({filename: __filename});30 });31 });3233 itEth('totalSupply', async ({helper}) => {34 const caller = await helper.eth.createAccountWithBalance(donor);35 const {collectionAddress} = await helper.eth.createRFTCollection(caller, 'TotalSupply', '6', '6');36 const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', caller);3738 await contract.methods.mint(caller).send();3940 const totalSupply = await contract.methods.totalSupply().call();41 expect(totalSupply).to.equal('1');42 });4344 itEth('balanceOf', async ({helper}) => {45 const caller = await helper.eth.createAccountWithBalance(donor);46 const {collectionAddress} = await helper.eth.createRFTCollection(caller, 'BalanceOf', '6', '6');47 const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', caller);4849 await contract.methods.mint(caller).send();50 await contract.methods.mint(caller).send();51 await contract.methods.mint(caller).send();5253 const balance = await contract.methods.balanceOf(caller).call();54 expect(balance).to.equal('3');55 });5657 itEth('ownerOf', async ({helper}) => {58 const caller = await helper.eth.createAccountWithBalance(donor);59 const {collectionAddress} = await helper.eth.createRFTCollection(caller, 'OwnerOf', '6', '6');60 const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', caller);6162 const result = await contract.methods.mint(caller).send();63 const tokenId = result.events.Transfer.returnValues.tokenId;6465 const owner = await contract.methods.ownerOf(tokenId).call();66 expect(owner).to.equal(caller);67 });6869 itEth('ownerOf after burn', async ({helper}) => {70 const caller = await helper.eth.createAccountWithBalance(donor);71 const receiver = helper.eth.createAccount();72 const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(caller, 'OwnerOf-AfterBurn', '6', '6');73 const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', caller);7475 const result = await contract.methods.mint(caller).send();76 const tokenId = result.events.Transfer.returnValues.tokenId;77 const tokenContract = await helper.ethNativeContract.rftTokenById(collectionId, tokenId, caller);7879 await tokenContract.methods.repartition(2).send();80 await tokenContract.methods.transfer(receiver, 1).send();8182 await tokenContract.methods.burnFrom(caller, 1).send();8384 const owner = await contract.methods.ownerOf(tokenId).call();85 expect(owner).to.equal(receiver);86 });8788 itEth('ownerOf for partial ownership', async ({helper}) => {89 const caller = await helper.eth.createAccountWithBalance(donor);90 const receiver = helper.eth.createAccount();91 const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(caller, 'Partial-OwnerOf', '6', '6');92 const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', caller);9394 const result = await contract.methods.mint(caller).send();95 const tokenId = result.events.Transfer.returnValues.tokenId;96 const tokenContract = await helper.ethNativeContract.rftTokenById(collectionId, tokenId, caller);9798 await tokenContract.methods.repartition(2).send();99 await tokenContract.methods.transfer(receiver, 1).send();100101 const owner = await contract.methods.ownerOf(tokenId).call();102 expect(owner).to.equal('0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF');103 });104});105106describe('Refungible: Plain calls', () => {107 let donor: IKeyringPair;108 let minter: IKeyringPair;109 let bob: IKeyringPair;110 let charlie: IKeyringPair;111112 before(async function() {113 await usingEthPlaygrounds(async (helper, privateKey) => {114 requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);115116 donor = await privateKey({filename: __filename});117 [minter, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);118 });119 });120121 itEth('Can perform mint() & crossOwnerOf()', async ({helper}) => {122 const owner = await helper.eth.createAccountWithBalance(donor);123 const receiver = helper.eth.createAccount();124 const {collectionAddress} = await helper.eth.createERC721MetadataCompatibleRFTCollection(owner, 'Minty', '6', '6', '');125 const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', owner);126127 const result = await contract.methods.mintWithTokenURI(receiver, 'Test URI').send();128129 const event = result.events.Transfer;130 expect(event.address).to.equal(collectionAddress);131 expect(event.returnValues.from).to.equal('0x0000000000000000000000000000000000000000');132 expect(event.returnValues.to).to.equal(receiver);133 const tokenId = event.returnValues.tokenId;134 expect(tokenId).to.be.equal('1');135136 expect(await contract.methods.crossOwnerOf(tokenId).call()).to.be.like([receiver, '0']);137 expect(await contract.methods.tokenURI(tokenId).call()).to.be.equal('Test URI');138 });139140 [141 'substrate' as const,142 'ethereum' as const,143 ].map(testCase => {144 itEth(`Can perform mintCross() for ${testCase} address`, async ({helper}) => {145 const collectionAdmin = await helper.eth.createAccountWithBalance(donor);146147 const receiverEth = helper.eth.createAccount();148 const receiverCrossEth = helper.ethCrossAccount.fromAddress(receiverEth);149 const receiverSub = bob;150 const receiverCrossSub = helper.ethCrossAccount.fromKeyringPair(receiverSub);151152 const properties = Array(5).fill(0).map((_, i) => { return {key: `key_${i}`, value: Buffer.from(`value_${i}`)}; });153 const permissions: ITokenPropertyPermission[] = properties.map(p => { return {key: p.key, permission: {154 tokenOwner: false,155 collectionAdmin: true,156 mutable: false}};157 });158159160 const collection = await helper.rft.mintCollection(minter, {161 tokenPrefix: 'ethp',162 tokenPropertyPermissions: permissions,163 });164 await collection.addAdmin(minter, {Ethereum: collectionAdmin});165166 const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);167 const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', collectionAdmin, true);168 let expectedTokenId = await contract.methods.nextTokenId().call();169 let result = await contract.methods.mintCross(testCase === 'ethereum' ? receiverCrossEth : receiverCrossSub, []).send();170 let tokenId = result.events.Transfer.returnValues.tokenId;171 expect(tokenId).to.be.equal(expectedTokenId);172173 let event = result.events.Transfer;174 expect(event.address).to.be.equal(collectionAddress);175 expect(event.returnValues.from).to.be.equal('0x0000000000000000000000000000000000000000');176 expect(event.returnValues.to).to.be.equal(testCase === 'ethereum' ? receiverEth : helper.address.substrateToEth(bob.address));177 expect(await contract.methods.properties(tokenId, []).call()).to.be.like([]);178179 expectedTokenId = await contract.methods.nextTokenId().call();180 result = await contract.methods.mintCross(testCase === 'ethereum' ? receiverCrossEth : receiverCrossSub, properties).send();181 event = result.events.Transfer;182 expect(event.address).to.be.equal(collectionAddress);183 expect(event.returnValues.from).to.be.equal('0x0000000000000000000000000000000000000000');184 expect(event.returnValues.to).to.be.equal(testCase === 'ethereum' ? receiverEth : helper.address.substrateToEth(bob.address));185 expect(await contract.methods.properties(tokenId, []).call()).to.be.like([]);186187 tokenId = result.events.Transfer.returnValues.tokenId;188189 expect(tokenId).to.be.equal(expectedTokenId);190191 expect(await contract.methods.properties(tokenId, []).call()).to.be.like(properties192 .map(p => { return helper.ethProperty.property(p.key, p.value.toString()); }));193194 expect(await helper.nft.getTokenOwner(collection.collectionId, tokenId))195 .to.deep.eq(testCase === 'ethereum' ? {Ethereum: receiverEth.toLowerCase()} : {Substrate: receiverSub.address});196 });197 });198199 itEth.skip('Can perform mintBulk()', async ({helper}) => {200 const owner = await helper.eth.createAccountWithBalance(donor);201 const receiver = helper.eth.createAccount();202 const {collectionAddress} = await helper.eth.createERC721MetadataCompatibleRFTCollection(owner, 'MintBulky', '6', '6', '');203 const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', owner);204205 {206 const nextTokenId = await contract.methods.nextTokenId().call();207 expect(nextTokenId).to.be.equal('1');208 const result = await contract.methods.mintBulkWithTokenURI(209 receiver,210 [211 [nextTokenId, 'Test URI 0'],212 [+nextTokenId + 1, 'Test URI 1'],213 [+nextTokenId + 2, 'Test URI 2'],214 ],215 ).send();216217 const events = result.events.Transfer;218 for (let i = 0; i < 2; i++) {219 const event = events[i];220 expect(event.address).to.equal(collectionAddress);221 expect(event.returnValues.from).to.equal('0x0000000000000000000000000000000000000000');222 expect(event.returnValues.to).to.equal(receiver);223 expect(event.returnValues.tokenId).to.equal(String(+nextTokenId + i));224 }225226 expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI 0');227 expect(await contract.methods.tokenURI(+nextTokenId + 1).call()).to.be.equal('Test URI 1');228 expect(await contract.methods.tokenURI(+nextTokenId + 2).call()).to.be.equal('Test URI 2');229 }230 });231232 itEth('Can perform setApprovalForAll()', async ({helper}) => {233 const owner = await helper.eth.createAccountWithBalance(donor);234 const operator = helper.eth.createAccount();235236 const collection = await helper.rft.mintCollection(minter, {});237238 const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);239 const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', owner);240241 const approvedBefore = await contract.methods.isApprovedForAll(owner, operator).call();242 expect(approvedBefore).to.be.equal(false);243244 {245 const result = await contract.methods.setApprovalForAll(operator, true).send({from: owner});246247 expect(result.events.ApprovalForAll).to.be.like({248 address: collectionAddress,249 event: 'ApprovalForAll',250 returnValues: {251 owner,252 operator,253 approved: true,254 },255 });256257 const approvedAfter = await contract.methods.isApprovedForAll(owner, operator).call();258 expect(approvedAfter).to.be.equal(true);259 }260261 {262 const result = await contract.methods.setApprovalForAll(operator, false).send({from: owner});263264 expect(result.events.ApprovalForAll).to.be.like({265 address: collectionAddress,266 event: 'ApprovalForAll',267 returnValues: {268 owner,269 operator,270 approved: false,271 },272 });273274 const approvedAfter = await contract.methods.isApprovedForAll(owner, operator).call();275 expect(approvedAfter).to.be.equal(false);276 }277 });278279 itEth('Can perform burn with ApprovalForAll', async ({helper}) => {280 const collection = await helper.rft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});281282 const owner = await helper.eth.createAccountWithBalance(donor);283 const operator = await helper.eth.createAccountWithBalance(donor, 100n);284285 const token = await collection.mintToken(minter, 100n, {Ethereum: owner});286287 const address = helper.ethAddress.fromCollectionId(collection.collectionId);288 const contract = await helper.ethNativeContract.collection(address, 'rft');289290 {291 await contract.methods.setApprovalForAll(operator, true).send({from: owner});292 const ownerCross = helper.ethCrossAccount.fromAddress(owner);293 const result = await contract.methods.burnFromCross(ownerCross, token.tokenId).send({from: operator});294 const events = result.events.Transfer;295296 expect(events).to.be.like({297 address,298 event: 'Transfer',299 returnValues: {300 from: owner,301 to: '0x0000000000000000000000000000000000000000',302 tokenId: token.tokenId.toString(),303 },304 });305 }306 });307308 itEth('Can perform burn with approve and approvalForAll', async ({helper}) => {309 const collection = await helper.rft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});310311 const owner = await helper.eth.createAccountWithBalance(donor);312 const operator = await helper.eth.createAccountWithBalance(donor, 100n);313314 const token = await collection.mintToken(minter, 100n, {Ethereum: owner});315316 const address = helper.ethAddress.fromCollectionId(collection.collectionId);317 const contract = await helper.ethNativeContract.collection(address, 'rft');318319 const rftToken = await helper.ethNativeContract.rftTokenById(token.collectionId, token.tokenId, owner);320321 {322 await rftToken.methods.approve(operator, 15n).send({from: owner});323 await contract.methods.setApprovalForAll(operator, true).send({from: owner});324 await rftToken.methods.burnFrom(owner, 10n).send({from: operator});325 const allowance = await rftToken.methods.allowance(owner, operator).call();326 expect(allowance).to.be.equal('5');327 }328 });329330 itEth('Can perform transfer with ApprovalForAll', async ({helper}) => {331 const collection = await helper.rft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});332333 const owner = await helper.eth.createAccountWithBalance(donor);334 const operator = await helper.eth.createAccountWithBalance(donor);335 const receiver = charlie;336337 const token = await collection.mintToken(minter, 100n, {Ethereum: owner});338339 const address = helper.ethAddress.fromCollectionId(collection.collectionId);340 const contract = await helper.ethNativeContract.collection(address, 'rft');341342 {343 await contract.methods.setApprovalForAll(operator, true).send({from: owner});344 const ownerCross = helper.ethCrossAccount.fromAddress(owner);345 const recieverCross = helper.ethCrossAccount.fromKeyringPair(receiver);346 const result = await contract.methods.transferFromCross(ownerCross, recieverCross, token.tokenId).send({from: operator});347 const event = result.events.Transfer;348 expect(event).to.be.like({349 address: helper.ethAddress.fromCollectionId(collection.collectionId),350 event: 'Transfer',351 returnValues: {352 from: owner,353 to: helper.address.substrateToEth(receiver.address),354 tokenId: token.tokenId.toString(),355 },356 });357 }358359 expect(await token.getTop10Owners()).to.be.like([{Substrate: receiver.address}]);360 });361362 itEth('Can perform burn()', async ({helper}) => {363 const caller = await helper.eth.createAccountWithBalance(donor);364 const {collectionAddress} = await helper.eth.createRFTCollection(caller, 'Burny', '6', '6');365 const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', caller);366367 const result = await contract.methods.mint(caller).send();368 const tokenId = result.events.Transfer.returnValues.tokenId;369 {370 const result = await contract.methods.burn(tokenId).send();371 const event = result.events.Transfer;372 expect(event.address).to.equal(collectionAddress);373 expect(event.returnValues.from).to.equal(caller);374 expect(event.returnValues.to).to.equal('0x0000000000000000000000000000000000000000');375 expect(event.returnValues.tokenId).to.equal(tokenId.toString());376 }377 });378379 itEth('Can perform transferFrom()', async ({helper}) => {380 const caller = await helper.eth.createAccountWithBalance(donor);381 const receiver = helper.eth.createAccount();382 const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(caller, 'TransferFromy', '6', '6');383 const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', caller);384385 const result = await contract.methods.mint(caller).send();386 const tokenId = result.events.Transfer.returnValues.tokenId;387388 const tokenAddress = helper.ethAddress.fromTokenId(collectionId, tokenId);389390 const tokenContract = await helper.ethNativeContract.rftToken(tokenAddress, caller);391 await tokenContract.methods.repartition(15).send();392393 {394 const tokenEvents: any = [];395 tokenContract.events.allEvents((_: any, event: any) => {396 tokenEvents.push(event);397 });398 const result = await contract.methods.transferFrom(caller, receiver, tokenId).send();399 if (tokenEvents.length == 0) await helper.wait.newBlocks(1);400401 let event = result.events.Transfer;402 expect(event.address).to.equal(collectionAddress);403 expect(event.returnValues.from).to.equal(caller);404 expect(event.returnValues.to).to.equal(receiver);405 expect(event.returnValues.tokenId).to.equal(tokenId.toString());406407 event = tokenEvents[0];408 expect(event.address).to.equal(tokenAddress);409 expect(event.returnValues.from).to.equal(caller);410 expect(event.returnValues.to).to.equal(receiver);411 expect(event.returnValues.value).to.equal('15');412 }413414 {415 const balance = await contract.methods.balanceOf(receiver).call();416 expect(+balance).to.equal(1);417 }418419 {420 const balance = await contract.methods.balanceOf(caller).call();421 expect(+balance).to.equal(0);422 }423 });424425 // Soft-deprecated426 itEth('Can perform burnFrom()', async ({helper}) => {427 const collection = await helper.rft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});428429 const owner = await helper.eth.createAccountWithBalance(donor, 100n);430 const spender = await helper.eth.createAccountWithBalance(donor, 100n);431432 const token = await collection.mintToken(minter, 100n, {Ethereum: owner});433434 const address = helper.ethAddress.fromCollectionId(collection.collectionId);435 const contract = await helper.ethNativeContract.collection(address, 'rft', spender, true);436437 const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, token.tokenId);438 const tokenContract = await helper.ethNativeContract.rftToken(tokenAddress, owner);439 await tokenContract.methods.repartition(15).send();440 await tokenContract.methods.approve(spender, 15).send();441442 {443 const result = await contract.methods.burnFrom(owner, token.tokenId).send();444 const event = result.events.Transfer;445 expect(event).to.be.like({446 address: helper.ethAddress.fromCollectionId(collection.collectionId),447 event: 'Transfer',448 returnValues: {449 from: owner,450 to: '0x0000000000000000000000000000000000000000',451 tokenId: token.tokenId.toString(),452 },453 });454 }455456 expect(await collection.getTokenBalance(token.tokenId, {Ethereum: owner})).to.be.eq(0n);457 });458459 itEth('Can perform burnFromCross()', async ({helper}) => {460 const collection = await helper.rft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});461462 const owner = bob;463 const spender = await helper.eth.createAccountWithBalance(donor, 100n);464465 const token = await collection.mintToken(minter, 100n, {Substrate: owner.address});466467 const address = helper.ethAddress.fromCollectionId(collection.collectionId);468 const contract = await helper.ethNativeContract.collection(address, 'rft');469470 await token.repartition(owner, 15n);471 await token.approve(owner, {Ethereum: spender}, 15n);472473 {474 const ownerCross = helper.ethCrossAccount.fromKeyringPair(owner);475 const result = await contract.methods.burnFromCross(ownerCross, token.tokenId).send({from: spender});476 const event = result.events.Transfer;477 expect(event).to.be.like({478 address: helper.ethAddress.fromCollectionId(collection.collectionId),479 event: 'Transfer',480 returnValues: {481 from: helper.address.substrateToEth(owner.address),482 to: '0x0000000000000000000000000000000000000000',483 tokenId: token.tokenId.toString(),484 },485 });486 }487488 expect(await collection.getTokenBalance(token.tokenId, {Substrate: owner.address})).to.be.eq(0n);489 });490491 itEth('Can perform transferFromCross()', async ({helper}) => {492 const collection = await helper.rft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});493494 const owner = bob;495 const spender = await helper.eth.createAccountWithBalance(donor, 100n);496 const receiver = charlie;497498 const token = await collection.mintToken(minter, 100n, {Substrate: owner.address});499500 const address = helper.ethAddress.fromCollectionId(collection.collectionId);501 const contract = await helper.ethNativeContract.collection(address, 'rft');502503 await token.repartition(owner, 15n);504 await token.approve(owner, {Ethereum: spender}, 15n);505506 {507 const ownerCross = helper.ethCrossAccount.fromKeyringPair(owner);508 const recieverCross = helper.ethCrossAccount.fromKeyringPair(receiver);509 const result = await contract.methods.transferFromCross(ownerCross, recieverCross, token.tokenId).send({from: spender});510 const event = result.events.Transfer;511 expect(event).to.be.like({512 address: helper.ethAddress.fromCollectionId(collection.collectionId),513 event: 'Transfer',514 returnValues: {515 from: helper.address.substrateToEth(owner.address),516 to: helper.address.substrateToEth(receiver.address),517 tokenId: token.tokenId.toString(),518 },519 });520 }521522 expect(await token.getTop10Owners()).to.be.like([{Substrate: receiver.address}]);523 });524525 itEth('Can perform transfer()', async ({helper}) => {526 const caller = await helper.eth.createAccountWithBalance(donor);527 const receiver = helper.eth.createAccount();528 const {collectionAddress} = await helper.eth.createRFTCollection(caller, 'Transferry', '6', '6');529 const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', caller);530531 const result = await contract.methods.mint(caller).send();532 const tokenId = result.events.Transfer.returnValues.tokenId;533534 {535 const result = await contract.methods.transfer(receiver, tokenId).send();536537 const event = result.events.Transfer;538 expect(event.address).to.equal(collectionAddress);539 expect(event.returnValues.from).to.equal(caller);540 expect(event.returnValues.to).to.equal(receiver);541 expect(event.returnValues.tokenId).to.equal(tokenId.toString());542 }543544 {545 const balance = await contract.methods.balanceOf(caller).call();546 expect(+balance).to.equal(0);547 }548549 {550 const balance = await contract.methods.balanceOf(receiver).call();551 expect(+balance).to.equal(1);552 }553 });554555 itEth('Can perform transferCross()', async ({helper}) => {556 const sender = await helper.eth.createAccountWithBalance(donor);557 const receiverEth = await helper.eth.createAccountWithBalance(donor);558 const receiverCrossEth = helper.ethCrossAccount.fromAddress(receiverEth);559 const receiverCrossSub = helper.ethCrossAccount.fromKeyringPair(minter);560561 const collection = await helper.rft.mintCollection(minter, {});562 const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);563 const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'rft', sender);564565 const token = await collection.mintToken(minter, 50n, {Ethereum: sender});566567 {568 // Can transferCross to ethereum address:569 const result = await collectionEvm.methods.transferCross(receiverCrossEth, token.tokenId).send({from: sender});570 // Check events:571 const event = result.events.Transfer;572 expect(event.address).to.equal(collectionAddress);573 expect(event.returnValues.from).to.equal(sender);574 expect(event.returnValues.to).to.equal(receiverEth);575 expect(event.returnValues.tokenId).to.equal(token.tokenId.toString());576 // Sender's balance decreased:577 const senderBalance = await collectionEvm.methods.balanceOf(sender).call();578 expect(+senderBalance).to.equal(0);579 expect(await token.getBalance({Ethereum: sender})).to.eq(0n);580 // Receiver's balance increased:581 const receiverBalance = await collectionEvm.methods.balanceOf(receiverEth).call();582 expect(+receiverBalance).to.equal(1);583 expect(await token.getBalance({Ethereum: receiverEth})).to.eq(50n);584 }585586 {587 // Can transferCross to substrate address:588 const substrateResult = await collectionEvm.methods.transferCross(receiverCrossSub, token.tokenId).send({from: receiverEth});589 // Check events:590 const event = substrateResult.events.Transfer;591 expect(event.address).to.be.equal(collectionAddress);592 expect(event.returnValues.from).to.be.equal(receiverEth);593 expect(event.returnValues.to).to.be.equal(helper.address.substrateToEth(minter.address));594 expect(event.returnValues.tokenId).to.be.equal(`${token.tokenId}`);595 // Sender's balance decreased:596 const senderBalance = await collectionEvm.methods.balanceOf(receiverEth).call();597 expect(+senderBalance).to.equal(0);598 expect(await token.getBalance({Ethereum: receiverEth})).to.eq(0n);599 // Receiver's balance increased:600 const receiverBalance = await helper.nft.getTokensByAddress(collection.collectionId, {Substrate: minter.address});601 expect(receiverBalance).to.contain(token.tokenId);602 expect(await token.getBalance({Substrate: minter.address})).to.eq(50n);603 }604 });605606 ['transfer', 'transferCross'].map(testCase => itEth(`Cannot ${testCase} non-owned token`, async ({helper}) => {607 const sender = await helper.eth.createAccountWithBalance(donor);608 const tokenOwner = await helper.eth.createAccountWithBalance(donor);609 const receiverSub = minter;610 const receiverCrossSub = helper.ethCrossAccount.fromKeyringPair(minter);611612 const collection = await helper.rft.mintCollection(minter, {});613 const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);614 const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'rft', sender);615616 await collection.mintToken(minter, 50n, {Ethereum: sender});617 const nonSendersToken = await collection.mintToken(minter, 50n, {Ethereum: tokenOwner});618619 // Cannot transferCross someone else's token:620 const receiver = testCase === 'transfer' ? helper.address.substrateToEth(receiverSub.address) : receiverCrossSub;621 await expect(collectionEvm.methods[testCase](receiver, nonSendersToken.tokenId).send({from: sender})).to.be.rejected;622 // Cannot transfer token if it does not exist:623 await expect(collectionEvm.methods[testCase](receiver, 999999).send({from: sender})).to.be.rejected;624 }));625626 itEth('transfer event on transfer from partial ownership to full ownership', async ({helper}) => {627 const caller = await helper.eth.createAccountWithBalance(donor);628 const receiver = helper.eth.createAccount();629 const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(caller, 'Transferry-Partial-to-Full', '6', '6');630 const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', caller);631632 const result = await contract.methods.mint(caller).send();633 const tokenId = result.events.Transfer.returnValues.tokenId;634635 const tokenContract = await helper.ethNativeContract.rftTokenById(collectionId, tokenId, caller);636637 await tokenContract.methods.repartition(2).send();638 await tokenContract.methods.transfer(receiver, 1).send();639640 const events: any = [];641 contract.events.allEvents((_: any, event: any) => {642 events.push(event);643 });644645 await tokenContract.methods.transfer(receiver, 1).send();646 if (events.length == 0) await helper.wait.newBlocks(1);647 const event = events[0];648649 expect(event.address).to.equal(collectionAddress);650 expect(event.returnValues.from).to.equal('0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF');651 expect(event.returnValues.to).to.equal(receiver);652 expect(event.returnValues.tokenId).to.equal(tokenId.toString());653 });654655 itEth('transfer event on transfer from full ownership to partial ownership', async ({helper}) => {656 const caller = await helper.eth.createAccountWithBalance(donor);657 const receiver = helper.eth.createAccount();658 const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(caller, 'Transferry-Full-to-Partial', '6', '6');659 const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', caller);660661 const result = await contract.methods.mint(caller).send();662 const tokenId = result.events.Transfer.returnValues.tokenId;663664 const tokenContract = await helper.ethNativeContract.rftTokenById(collectionId, tokenId, caller);665666 await tokenContract.methods.repartition(2).send();667668 const events: any = [];669 contract.events.allEvents((_: any, event: any) => {670 events.push(event);671 });672673 await tokenContract.methods.transfer(receiver, 1).send();674 if (events.length == 0) await helper.wait.newBlocks(1);675 const event = events[0];676677 expect(event.address).to.equal(collectionAddress);678 expect(event.returnValues.from).to.equal(caller);679 expect(event.returnValues.to).to.equal('0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF');680 expect(event.returnValues.tokenId).to.equal(tokenId.toString());681 });682});683684describe('RFT: Fees', () => {685 let donor: IKeyringPair;686687 before(async function() {688 await usingEthPlaygrounds(async (helper, privateKey) => {689 requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);690691 donor = await privateKey({filename: __filename});692 });693 });694695 itEth('transferFrom() call fee is less than 0.2UNQ', async ({helper}) => {696 const caller = await helper.eth.createAccountWithBalance(donor);697 const receiver = helper.eth.createAccount();698 const {collectionAddress} = await helper.eth.createRFTCollection(caller, 'Feeful-Transfer-From', '6', '6');699 const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', caller);700701 const result = await contract.methods.mint(caller).send();702 const tokenId = result.events.Transfer.returnValues.tokenId;703704 const cost = await helper.eth.recordCallFee(caller, () => contract.methods.transferFrom(caller, receiver, tokenId).send());705 expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));706 expect(cost > 0n);707 });708709 itEth('transfer() call fee is less than 0.2UNQ', async ({helper}) => {710 const caller = await helper.eth.createAccountWithBalance(donor);711 const receiver = helper.eth.createAccount();712 const {collectionAddress} = await helper.eth.createRFTCollection(caller, 'Feeful-Transfer', '6', '6');713 const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', caller);714715 const result = await contract.methods.mint(caller).send();716 const tokenId = result.events.Transfer.returnValues.tokenId;717718 const cost = await helper.eth.recordCallFee(caller, () => contract.methods.transfer(receiver, tokenId).send());719 expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));720 expect(cost > 0n);721 });722});723724describe('Common metadata', () => {725 let donor: IKeyringPair;726 let alice: IKeyringPair;727728 before(async function() {729 await usingEthPlaygrounds(async (helper, privateKey) => {730 requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);731732 donor = await privateKey({filename: __filename});733 [alice] = await helper.arrange.createAccounts([20n], donor);734 });735 });736737 itEth('Returns collection name', async ({helper}) => {738 const caller = helper.eth.createAccount();739 const tokenPropertyPermissions = [{740 key: 'URI',741 permission: {742 mutable: true,743 collectionAdmin: true,744 tokenOwner: false,745 },746 }];747 const collection = await helper.rft.mintCollection(748 alice,749 {750 name: 'Leviathan',751 tokenPrefix: '11',752 properties: [{key: 'ERC721Metadata', value: '1'}],753 tokenPropertyPermissions,754 },755 );756757 const contract = await helper.ethNativeContract.collectionById(collection.collectionId, 'rft', caller);758 const name = await contract.methods.name().call();759 expect(name).to.equal('Leviathan');760 });761762 itEth('Returns symbol name', async ({helper}) => {763 const caller = await helper.eth.createAccountWithBalance(donor);764 const tokenPropertyPermissions = [{765 key: 'URI',766 permission: {767 mutable: true,768 collectionAdmin: true,769 tokenOwner: false,770 },771 }];772 const {collectionId} = await helper.rft.mintCollection(773 alice,774 {775 name: 'Leviathan',776 tokenPrefix: '12',777 properties: [{key: 'ERC721Metadata', value: '1'}],778 tokenPropertyPermissions,779 },780 );781782 const contract = await helper.ethNativeContract.collectionById(collectionId, 'rft', caller);783 const symbol = await contract.methods.symbol().call();784 expect(symbol).to.equal('12');785 });786});787788describe('Negative tests', () => {789 let donor: IKeyringPair;790 let minter: IKeyringPair;791 let alice: IKeyringPair;792793 before(async function() {794 await usingEthPlaygrounds(async (helper, privateKey) => {795 requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);796797 donor = await privateKey({filename: __filename});798 [minter, alice] = await helper.arrange.createAccounts([100n, 100n], donor);799 });800 });801802 itEth('[negative] Cant perform burn without approval', async ({helper}) => {803 const collection = await helper.rft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});804805 const owner = await helper.eth.createAccountWithBalance(donor, 100n);806 const spender = await helper.eth.createAccountWithBalance(donor, 100n);807808 const token = await collection.mintToken(minter, 100n, {Ethereum: owner});809810 const address = helper.ethAddress.fromCollectionId(collection.collectionId);811 const contract = await helper.ethNativeContract.collection(address, 'rft');812813 const ownerCross = helper.ethCrossAccount.fromAddress(owner);814815 await expect(contract.methods.burnFromCross(ownerCross, token.tokenId).send({from: spender})).to.be.rejected;816817 await contract.methods.setApprovalForAll(spender, true).send({from: owner});818 await contract.methods.setApprovalForAll(spender, false).send({from: owner});819820 await expect(contract.methods.burnFromCross(ownerCross, token.tokenId).send({from: spender})).to.be.rejected;821 });822823 itEth('[negative] Cant perform transfer without approval', async ({helper}) => {824 const collection = await helper.rft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});825 const owner = await helper.eth.createAccountWithBalance(donor, 100n);826 const receiver = alice;827828 const spender = await helper.eth.createAccountWithBalance(donor, 100n);829830 const token = await collection.mintToken(minter, 100n, {Ethereum: owner});831832 const address = helper.ethAddress.fromCollectionId(collection.collectionId);833 const contract = await helper.ethNativeContract.collection(address, 'rft');834835 const ownerCross = helper.ethCrossAccount.fromAddress(owner);836 const recieverCross = helper.ethCrossAccount.fromKeyringPair(receiver);837838 await expect(contract.methods.transferFromCross(ownerCross, recieverCross, token.tokenId).send({from: spender})).to.be.rejected;839840 await contract.methods.setApprovalForAll(spender, true).send({from: owner});841 await contract.methods.setApprovalForAll(spender, false).send({from: owner});842843 await expect(contract.methods.transferFromCross(ownerCross, recieverCross, token.tokenId).send({from: spender})).to.be.rejected;844 });845});tests/src/eth/reFungibleToken.test.tsdiffbeforeafterboth--- a/tests/src/eth/reFungibleToken.test.ts
+++ b/tests/src/eth/reFungibleToken.test.ts
@@ -458,7 +458,7 @@
const result = await contract.methods.mint(caller).send();
const tokenId = result.events.Transfer.returnValues.tokenId;
const tokenAddress = helper.ethAddress.fromTokenId(collectionId, tokenId);
- const tokenContract = await helper.ethNativeContract.rftToken(tokenAddress, caller);
+ const tokenContract = await helper.ethNativeContract.rftToken(tokenAddress, caller, true);
await tokenContract.methods.repartition(2).send();
await tokenContract.methods.transfer(receiver, 1).send();
tests/src/eth/util/playgrounds/unique.dev.tsdiffbeforeafterboth--- a/tests/src/eth/util/playgrounds/unique.dev.ts
+++ b/tests/src/eth/util/playgrounds/unique.dev.ts
@@ -29,6 +29,7 @@
import refungibleAbi from '../../abi/reFungible.json';
import refungibleDeprecatedAbi from '../../abi/reFungibleDeprecated.json';
import refungibleTokenAbi from '../../abi/reFungibleToken.json';
+import refungibleTokenDeprecatedAbi from '../../abi/reFungibleTokenDeprecated.json';
import contractHelpersAbi from '../../abi/contractHelpers.json';
import {ICrossAccountId, TEthereumAccount} from '../../../util/playgrounds/types';
import {TCollectionMode} from '../../../util/playgrounds/types';
@@ -187,17 +188,18 @@
return this.collection(this.helper.ethAddress.fromCollectionId(collectionId), mode, caller, mergeDeprecated);
}
- async rftToken(address: string, caller?: string) {
+ async rftToken(address: string, caller?: string, mergeDeprecated = false) {
const web3 = this.helper.getWeb3();
- return unlimitedMoneyHack(new web3.eth.Contract(refungibleTokenAbi as any, address, {
+ const abi = mergeDeprecated ? [...refungibleTokenAbi, ...refungibleTokenDeprecatedAbi] : refungibleTokenAbi;
+ return unlimitedMoneyHack(new web3.eth.Contract(abi as any, address, {
gas: this.helper.eth.DEFAULT_GAS,
gasPrice: await this.getGasPrice(),
...(caller ? {from: caller} : {}),
}));
}
- rftTokenById(collectionId: number, tokenId: number, caller?: string) {
- return this.rftToken(this.helper.ethAddress.fromTokenId(collectionId, tokenId), caller);
+ rftTokenById(collectionId: number, tokenId: number, caller?: string, mergeDeprecated = false) {
+ return this.rftToken(this.helper.ethAddress.fromTokenId(collectionId, tokenId), caller, mergeDeprecated);
}
}