From 7b06a09a660c6017fbb33825a7ebc201b60bde71 Mon Sep 17 00:00:00 2001 From: b00ste Date: Fri, 11 Aug 2023 12:14:46 +0300 Subject: [PATCH] test: add some tests for this behavior --- ...P1UniversalReceiverDelegateUP.behaviour.ts | 196 +++++++++++++++--- ...niversalReceiverDelegateVault.behaviour.ts | 111 +++++++++- 2 files changed, 269 insertions(+), 38 deletions(-) diff --git a/tests/LSP1UniversalReceiver/LSP1UniversalReceiverDelegateUP.behaviour.ts b/tests/LSP1UniversalReceiver/LSP1UniversalReceiverDelegateUP.behaviour.ts index 4bf081b40..401372de9 100644 --- a/tests/LSP1UniversalReceiver/LSP1UniversalReceiverDelegateUP.behaviour.ts +++ b/tests/LSP1UniversalReceiver/LSP1UniversalReceiverDelegateUP.behaviour.ts @@ -106,7 +106,7 @@ export const shouldBehaveLikeLSP1Delegate = ( describe('When testing EOA call to URD through the UR function', () => { describe('when calling with token/vault typeId', () => { - it('should revert with custom error', async () => { + it('should return error message', async () => { const URD_TypeIds = [ LSP1_TYPE_IDS.LSP7Tokens_RecipientNotification, LSP1_TYPE_IDS.LSP7Tokens_SenderNotification, @@ -122,11 +122,20 @@ export const shouldBehaveLikeLSP1Delegate = ( .connect(context.accounts.any) .universalReceiver(URD_TypeIds[i], '0x'), ) - .to.be.revertedWithCustomError( - context.lsp1universalReceiverDelegateUP, - 'CannotRegisterEOAsAsAssets', - ) - .withArgs(context.accounts.any.address); + .to.emit(context.universalProfile1, 'UniversalReceiver') + .withArgs( + context.accounts.any.address, + 0, + URD_TypeIds[i], + '0x', + abiCoder.encode( + ['bytes', 'bytes'], + [ + ethers.utils.solidityPack(['string'], ['LSP1: Cannot register EOAs as assets']), + '0x', + ], + ), + ); } }); }); @@ -1040,19 +1049,26 @@ export const shouldBehaveLikeLSP1Delegate = ( }); it('should revert when trying to transfer some tokens to UP but UP cannot register any more tokens', async () => { - const lsp1DelegateAddress = await context.universalProfile1['getData(bytes32)']( - ERC725YDataKeys.LSP1['LSP1UniversalReceiverDelegate'], - ); - - const lsp1DelegateInstance = await new LSP1UniversalReceiverDelegateUP__factory( - context.accounts.random, - ).attach(lsp1DelegateAddress); - // try to transfer (= mint) some tokens to the UP // this should revert because the UP cannot register any more tokens await expect(token.mint(context.universalProfile1.address, 10_000, false, '0x')) - .to.be.revertedWithCustomError(lsp1DelegateInstance, 'MaxLSP5ReceivedAssetsCountReached') - .withArgs(token.address); + .to.emit(context.universalProfile1, 'UniversalReceiver') + .withArgs( + token.address, + 0, + LSP1_TYPE_IDS.LSP7Tokens_RecipientNotification, + ethers.utils.solidityPack( + ['address', 'address', 'uint256', 'bytes'], + [ethers.constants.AddressZero, context.universalProfile1.address, 10_000, '0x'], + ), + abiCoder.encode( + ['bytes', 'bytes'], + [ + ethers.utils.solidityPack(['string'], ['LSP5: Max received assets count reached']), + '0x', + ], + ), + ); }); }); @@ -1335,7 +1351,7 @@ export const shouldBehaveLikeLSP1Delegate = ( const lsp1ReturnedData = ethers.utils.defaultAbiCoder.encode( ['string', 'bytes'], - ['LSP1: asset data corrupted', '0x'], + ['LSP5: Out of bounds', '0x'], ); await expect(tokenTransferTx) @@ -1576,7 +1592,7 @@ export const shouldBehaveLikeLSP1Delegate = ( it('it should emit UniversalReceiver event', async () => { const lsp1ReturnedData = ethers.utils.defaultAbiCoder.encode( ['string', 'bytes'], - ['LSP1: asset data corrupted', '0x'], + ['LSP10: Out of bounds', '0x'], ); await expect(acceptOwnershipTx) @@ -2462,17 +2478,23 @@ export const shouldBehaveLikeLSP1Delegate = ( // deploy a Vault setting the UP as owner // this should revert because the UP has already the max number of vaults allowed - const lsp1DelegateAddress = await context.universalProfile1['getData(bytes32)']( - ERC725YDataKeys.LSP1['LSP1UniversalReceiverDelegate'], - ); - const lsp1DelegateInstance = await new LSP1UniversalReceiverDelegateUP__factory( - context.accounts.random, - ).attach(lsp1DelegateAddress); + const tx = await new LSP9Vault__factory(context.accounts.random).deploy( + context.universalProfile1.address, + ); - await expect( - new LSP9Vault__factory(context.accounts.random).deploy(context.universalProfile1.address), - ).to.be.revertedWithCustomError(lsp1DelegateInstance, 'MaxLSP10VaultsCountReached'); + await expect(tx.deployTransaction) + .to.emit(context.universalProfile1, 'UniversalReceiver') + .withArgs( + tx.address, + 0, + LSP1_TYPE_IDS.LSP9OwnershipTransferred_RecipientNotification, + '0x', + ethers.utils.defaultAbiCoder.encode( + ['string', 'bytes'], + ['LSP10: Max vaults count reached', '0x'], + ), + ); }); }); }); @@ -2607,6 +2629,7 @@ export const shouldBehaveLikeLSP1Delegate = ( describe("when having a Vault set in LSP10 before it's ownership was transfered", () => { let vault: LSP9Vault; let vaultOwner: SignerWithAddress; + const bytes16Value1 = '0x' + '00'.repeat(15) + '01'; before(async () => { vaultOwner = context.accounts.any; @@ -2620,9 +2643,8 @@ export const shouldBehaveLikeLSP1Delegate = ( ERC725YDataKeys.LSP10['LSP10Vaults[]'].index + '00'.repeat(16), ERC725YDataKeys.LSP10['LSP10VaultsMap'] + vault.address.substring(2), ]; - const lsp10DataValues = [ - abiCoder.encode(['uint256'], ['1']), + bytes16Value1, vault.address, abiCoder.encode(['bytes4', 'uint64'], [INTERFACE_IDS.LSP9Vault, 0]), ]; @@ -2644,7 +2666,7 @@ export const shouldBehaveLikeLSP1Delegate = ( ERC725YDataKeys.LSP10['LSP10Vaults[]'].length, ); - expect(lsp10VaultArrayLengthValue).to.equal(abiCoder.encode(['uint256'], ['1'])); + expect(lsp10VaultArrayLengthValue).to.equal(bytes16Value1); const lsp10VaultArrayIndexValue = await context.universalProfile1['getData(bytes32)']( ERC725YDataKeys.LSP10['LSP10Vaults[]'].index + '00'.repeat(16), @@ -2713,7 +2735,7 @@ export const shouldBehaveLikeLSP1Delegate = ( ERC725YDataKeys.LSP10['LSP10Vaults[]'].length, ); - expect(lsp10VaultArrayLengthValue).to.equal(abiCoder.encode(['uint256'], ['1'])); + expect(lsp10VaultArrayLengthValue).to.equal(bytes16Value1); const lsp10VaultArrayIndexValue = await context.universalProfile1['getData(bytes32)']( ERC725YDataKeys.LSP10['LSP10Vaults[]'].index + '00'.repeat(16), @@ -2731,6 +2753,118 @@ export const shouldBehaveLikeLSP1Delegate = ( ); }); }); + + describe('when URD has no permissions', () => { + before('deploying new URD', async () => { + const newURD = await new LSP1UniversalReceiverDelegateUP__factory( + context.accounts.owner1, + ).deploy(); + + await context.universalProfile1 + .connect(context.accounts.owner1) + .setData(ERC725YDataKeys.LSP1.LSP1UniversalReceiverDelegate, newURD.address); + + await context.universalProfile2 + .connect(context.accounts.owner2) + .setData(ERC725YDataKeys.LSP1.LSP1UniversalReceiverDelegate, newURD.address); + }); + + describe('when receiving LSP7', () => { + it('should not revert', async () => { + // Deploy LSP7 (mint on SC level 1000 tokens) + const LSP7 = await new LSP7MintWhenDeployed__factory(context.accounts.owner1).deploy( + 'MyToken', + 'MTK', + context.universalProfile1.address, + ); + + expect(await LSP7.balanceOf(context.universalProfile1.address)).to.equal(1000); + expect(await LSP7.balanceOf(context.universalProfile2.address)).to.equal(0); + + // Encode LSP7 tokens tarnsfer (UP1 to UP2) + const LSP7_TransferCalldata = LSP7.interface.encodeFunctionData('transfer', [ + context.universalProfile1.address, + context.universalProfile2.address, + 1, + false, + '0x', + ]); + + // Transfer LSP7 tokens + await context.universalProfile1 + .connect(context.accounts.owner1) + .execute(OPERATION_TYPES.CALL, LSP7.address, 0, LSP7_TransferCalldata); + + expect(await LSP7.balanceOf(context.universalProfile1.address)).to.equal(999); + expect(await LSP7.balanceOf(context.universalProfile2.address)).to.equal(1); + }); + }); + + describe('when receiving LSP8', () => { + it('should not revert', async () => { + // Deploy LSP8 + const LSP8 = await new LSP8Tester__factory(context.accounts.owner1).deploy( + 'MyToken', + 'MTK', + context.universalProfile1.address, + ); + // Mint token for UP1 + await LSP8.mint(context.universalProfile1.address, '0x' + '0'.repeat(64), true, '0x'); + + expect(await LSP8.tokenOwnerOf('0x' + '0'.repeat(64))).to.equal( + context.universalProfile1.address, + ); + + // Encode LSP8 token tarnsfer (UP1 to UP2) + const LSP8_TransferCalldata = LSP8.interface.encodeFunctionData('transfer', [ + context.universalProfile1.address, + context.universalProfile2.address, + '0x' + '0'.repeat(64), + false, + '0x', + ]); + + // Transfer LSP8 token + await context.universalProfile1 + .connect(context.accounts.owner1) + .execute(OPERATION_TYPES.CALL, LSP8.address, 0, LSP8_TransferCalldata); + + expect(await LSP8.tokenOwnerOf('0x' + '0'.repeat(64))).to.equal( + context.universalProfile2.address, + ); + }); + }); + + describe('when becoming the owner of the LSP9 Vault', () => { + it('should not revert', async () => { + // Deploy LSP9 (UP1 ownwer) + const LSP9 = await new LSP9Vault__factory(context.accounts.owner1).deploy( + context.universalProfile1.address, + ); + + expect(await LSP9.owner()).to.equal(context.universalProfile1.address); + + // Encode LSP9 transfer & accept ownership (UP1 to UP2) + const LSP9_TransferOwnerhsipCalldata = LSP9.interface.encodeFunctionData( + 'transferOwnership', + [context.universalProfile2.address], + ); + const LSP9_AcceptOwnerhsipCalldata = LSP9.interface.encodeFunctionData('acceptOwnership'); + + // Transfer Ownership of LSP9 + await context.universalProfile1 + .connect(context.accounts.owner1) + .execute(OPERATION_TYPES.CALL, LSP9.address, 0, LSP9_TransferOwnerhsipCalldata); + + // Accept Ownership of LSP9 + await context.universalProfile2 + .connect(context.accounts.owner2) + .execute(OPERATION_TYPES.CALL, LSP9.address, 0, LSP9_AcceptOwnerhsipCalldata); + + expect(await LSP9.owner()).to.equal(context.universalProfile2.address); + }); + }); + }); }; export type LSP1DelegateInitializeTestContext = { diff --git a/tests/LSP1UniversalReceiver/LSP1UniversalReceiverDelegateVault.behaviour.ts b/tests/LSP1UniversalReceiver/LSP1UniversalReceiverDelegateVault.behaviour.ts index d743e55ac..09850772c 100644 --- a/tests/LSP1UniversalReceiver/LSP1UniversalReceiverDelegateVault.behaviour.ts +++ b/tests/LSP1UniversalReceiver/LSP1UniversalReceiverDelegateVault.behaviour.ts @@ -13,6 +13,7 @@ import { LSP1UniversalReceiverDelegateVault, LSP7MintWhenDeployed__factory, LSP7MintWhenDeployed, + LSP1UniversalReceiverDelegateVault__factory, } from '../../types'; import { ARRAY_LENGTH, LSP1_HOOK_PLACEHOLDER, abiCoder } from '../utils/helpers'; @@ -83,7 +84,7 @@ export const shouldBehaveLikeLSP1Delegate = (buildContext: () => Promise { describe('when calling with tokens typeId', () => { - it('should revert with custom error', async () => { + it('should return error message', async () => { const URD_TypeIds = [ LSP1_TYPE_IDS.LSP7Tokens_RecipientNotification, LSP1_TYPE_IDS.LSP7Tokens_SenderNotification, @@ -97,11 +98,17 @@ export const shouldBehaveLikeLSP1Delegate = (buildContext: () => Promise Promise Promise { + before('deploying new URD', async () => { + const newURD = await new LSP1UniversalReceiverDelegateVault__factory( + context.accounts.owner1, + ).deploy(); + + const LSP9_setDataCalldata = context.lsp9Vault1.interface.encodeFunctionData('setData', [ + ERC725YDataKeys.LSP1.LSP1UniversalReceiverDelegate, + newURD.address, + ]); + + await context.universalProfile + .connect(context.accounts.owner1) + .execute(OPERATION_TYPES.CALL, context.lsp9Vault1.address, 0, LSP9_setDataCalldata); + + await context.universalProfile + .connect(context.accounts.owner1) + .execute(OPERATION_TYPES.CALL, context.lsp9Vault2.address, 0, LSP9_setDataCalldata); + }); + + describe('when receiving LSP7', () => { + it('should not revert', async () => { + const LSP7 = await new LSP7MintWhenDeployed__factory(context.accounts.owner1).deploy( + 'MyToken', + 'MTK', + context.lsp9Vault1.address, + ); + + const LSP7_TransferCalldata = LSP7.interface.encodeFunctionData('transfer', [ + context.lsp9Vault1.address, + context.lsp9Vault2.address, + 1, + false, + '0x', + ]); + + const LSP9_ExecuteCalldata = context.lsp9Vault1.interface.encodeFunctionData('execute', [ + OPERATION_TYPES.CALL, + LSP7.address, + 0, + LSP7_TransferCalldata, + ]); + + expect(await LSP7.balanceOf(context.lsp9Vault1.address)).to.equal(1000); + expect(await LSP7.balanceOf(context.lsp9Vault2.address)).to.equal(0); + + await context.universalProfile + .connect(context.accounts.owner1) + .execute(OPERATION_TYPES.CALL, context.lsp9Vault1.address, 0, LSP9_ExecuteCalldata); + + expect(await LSP7.balanceOf(context.lsp9Vault1.address)).to.equal(999); + expect(await LSP7.balanceOf(context.lsp9Vault2.address)).to.equal(1); + }); + }); + + describe('when receiving LSP8', () => { + it('should not revert', async () => { + const LSP8 = await new LSP8Tester__factory(context.accounts.owner1).deploy( + 'MyToken', + 'MTK', + context.lsp9Vault1.address, + ); + await LSP8.mint(context.lsp9Vault1.address, '0x' + '0'.repeat(64), false, '0x'); + + const LSP8_TransferCalldata = LSP8.interface.encodeFunctionData('transfer', [ + context.lsp9Vault1.address, + context.lsp9Vault2.address, + '0x' + '0'.repeat(64), + false, + '0x', + ]); + + const LSP9_ExecuteCalldata = context.lsp9Vault1.interface.encodeFunctionData('execute', [ + OPERATION_TYPES.CALL, + LSP8.address, + 0, + LSP8_TransferCalldata, + ]); + + expect(await LSP8.tokenOwnerOf('0x' + '0'.repeat(64))).to.equal(context.lsp9Vault1.address); + + await context.universalProfile + .connect(context.accounts.owner1) + .execute(OPERATION_TYPES.CALL, context.lsp9Vault1.address, 0, LSP9_ExecuteCalldata); + + expect(await LSP8.tokenOwnerOf('0x' + '0'.repeat(64))).to.equal(context.lsp9Vault2.address); + }); + }); + }); };