--- a/tests/src/eth/fungible.test.ts +++ b/tests/src/eth/fungible.test.ts @@ -186,6 +186,68 @@ } }); + itEth('Can perform approveCross()', async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); + const spender = helper.eth.createAccount(); + const spenderSub = (await helper.arrange.createAccounts([1n], donor))[0]; + const spenderCrossEth = helper.ethCrossAccount.fromAddress(spender); + const spenderCrossSub = helper.ethCrossAccount.fromKeyringPair(spenderSub); + + + const collection = await helper.ft.mintCollection(alice); + await collection.mint(alice, 200n, {Ethereum: owner}); + + const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); + const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner); + + { + const result = await contract.methods.approveCross(spenderCrossEth, 100).send({from: owner}); + const event = result.events.Approval; + expect(event.address).to.be.equal(collectionAddress); + expect(event.returnValues.owner).to.be.equal(owner); + expect(event.returnValues.spender).to.be.equal(spender); + expect(event.returnValues.value).to.be.equal('100'); + } + + { + const allowance = await contract.methods.allowance(owner, spender).call(); + expect(+allowance).to.equal(100); + } + + + { + const result = await contract.methods.approveCross(spenderCrossSub, 100).send({from: owner}); + const event = result.events.Approval; + expect(event.address).to.be.equal(collectionAddress); + expect(event.returnValues.owner).to.be.equal(owner); + expect(event.returnValues.spender).to.be.equal(helper.address.substrateToEth(spenderSub.address)); + expect(event.returnValues.value).to.be.equal('100'); + } + + { + const allowance = await collection.getApprovedTokens({Ethereum: owner}, {Substrate: spenderSub.address}); + expect(allowance).to.equal(100n); + } + + { + //TO-DO expect with future allowanceCross(owner, spenderCrossEth).call() + } + }); + + itEth('Non-owner and non admin cannot approveCross', async ({helper}) => { + const nonOwner = await helper.eth.createAccountWithBalance(donor); + const nonOwnerCross = helper.ethCrossAccount.fromAddress(nonOwner); + const owner = await helper.eth.createAccountWithBalance(donor); + const collection = await helper.ft.mintCollection(alice, {name: 'A', description: 'B', tokenPrefix: 'C'}); + await collection.mint(alice, 100n, {Ethereum: owner}); + + const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); + const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'ft', owner); + + await expect(collectionEvm.methods.approveCross(nonOwnerCross, 20).call({from: nonOwner})).to.be.rejectedWith('CantApproveMoreThanOwned'); + }); + + itEth('Can perform burnFromCross()', async ({helper}) => { const sender = await helper.eth.createAccountWithBalance(donor, 100n); --- a/tests/src/eth/nonFungible.test.ts +++ b/tests/src/eth/nonFungible.test.ts @@ -194,9 +194,9 @@ .map(p => { return { key: p.key, permission: { - tokenOwner: true, + tokenOwner: false, collectionAdmin: true, - mutable: true, + mutable: false, }, }; }); @@ -482,6 +482,7 @@ expect(await token2.doesExist()).to.be.false; }); + // TODO combine all approve tests in one place itEth('Can perform approveCross()', async ({helper}) => { // arrange: create accounts const owner = await helper.eth.createAccountWithBalance(donor, 100n); @@ -530,6 +531,17 @@ expect(await helper.nft.getTokenOwner(collection.collectionId, token2.tokenId)).to.deep.eq({Ethereum: receiverEth.toLowerCase()}); }); + itEth('Non-owner and non admin cannot approveCross', async ({helper}) => { + const nonOwner = await helper.eth.createAccountWithBalance(donor); + const nonOwnerCross = helper.ethCrossAccount.fromAddress(nonOwner); + const owner = await helper.eth.createAccountWithBalance(donor); + const collection = await helper.nft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'}); + const collectionEvm = helper.ethNativeContract.collection(helper.ethAddress.fromCollectionId(collection.collectionId), 'nft'); + const token = await collection.mintToken(minter, {Ethereum: owner}); + + await expect(collectionEvm.methods.approveCross(nonOwnerCross, token.tokenId).call({from: nonOwner})).to.be.rejectedWith('CantApproveMoreThanOwned'); + }); + itEth('Can reaffirm approved address', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor, 100n); const ownerCrossEth = helper.ethCrossAccount.fromAddress(owner); --- a/tests/src/eth/reFungible.test.ts +++ b/tests/src/eth/reFungible.test.ts @@ -150,9 +150,11 @@ const receiverCrossSub = helper.ethCrossAccount.fromKeyringPair(receiverSub); const properties = Array(5).fill(0).map((_, i) => { return {key: `key_${i}`, value: Buffer.from(`value_${i}`)}; }); - const permissions: ITokenPropertyPermission[] = properties.map(p => { return {key: p.key, permission: {tokenOwner: true, + const permissions: ITokenPropertyPermission[] = properties.map(p => { return {key: p.key, permission: { + tokenOwner: false, collectionAdmin: true, - mutable: true}}; }); + mutable: false}}; + }); const collection = await helper.rft.mintCollection(minter, { --- a/tests/src/eth/reFungibleToken.test.ts +++ b/tests/src/eth/reFungibleToken.test.ts @@ -207,7 +207,20 @@ //TO-DO expect with future allowanceCross(owner, spenderCrossEth).call() } }); - + + itEth('Non-owner and non admin cannot approveCross', async ({helper}) => { + const nonOwner = await helper.eth.createAccountWithBalance(donor); + const nonOwnerCross = helper.ethCrossAccount.fromAddress(nonOwner); + const owner = await helper.eth.createAccountWithBalance(donor); + const collection = await helper.rft.mintCollection(alice, {name: 'A', description: 'B', tokenPrefix: 'C'}); + const token = await collection.mintToken(alice, 100n, {Ethereum: owner}); + + const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, token.tokenId); + const tokenEvm = helper.ethNativeContract.rftToken(tokenAddress, owner); + + await expect(tokenEvm.methods.approveCross(nonOwnerCross, 20).call({from: nonOwner})).to.be.rejectedWith('CantApproveMoreThanOwned'); + }); + [ 'transferFrom', 'transferFromCross',