From db9bb0dc40cd5f11dd6f9cd8dbbb804c821f9041 Mon Sep 17 00:00:00 2001 From: CJ42 Date: Mon, 2 Oct 2023 13:48:58 +0100 Subject: [PATCH] test: update tests with new permission logic --- .../LSP6KeyManager/LSP6KeyManager.md | 28 +- .../SetPermissions/SetAllowedCalls.test.ts | 767 ++++++++------ .../SetAllowedERC725YDataKeys.test.ts | 385 +++---- .../SetPermissions/SetAllowedCalls.test.ts | 991 +++++++++--------- .../SetAllowedERC725YDataKeys.test.ts | 494 +++++---- 5 files changed, 1423 insertions(+), 1242 deletions(-) diff --git a/docs/contracts/LSP6KeyManager/LSP6KeyManager.md b/docs/contracts/LSP6KeyManager/LSP6KeyManager.md index 024890611..f8e7f9274 100644 --- a/docs/contracts/LSP6KeyManager/LSP6KeyManager.md +++ b/docs/contracts/LSP6KeyManager/LSP6KeyManager.md @@ -614,22 +614,22 @@ function _getPermissionToSetAllowedCalls( ) internal view returns (bytes32); ``` -retrieve the permission required to set some AllowedCalls for a controller. +Retrieve the permission required to set some AllowedCalls for a controller. #### Parameters | Name | Type | Description | | ---------------------------------------- | :-------: | ------------------------------------------------------------------------------------------- | -| `controlledContract` | `address` | the address of the ERC725Y contract where the data key is verified. | -| `dataKey` | `bytes32` | `AddressPermissions:AllowedCalls:`. | -| `dataValue` | `bytes` | the updated value for the `dataKey`. MUST be a bytes28[CompactBytesArray] of Allowed Calls. | +| `controlledContract` | `address` | The address of the ERC725Y contract from which to fetch the value of `dataKey`. | +| `dataKey` | `bytes32` | A data key ion the format `AddressPermissions:AllowedCalls:`. | +| `dataValue` | `bytes` | The updated value for the `dataKey`. MUST be a bytes32[CompactBytesArray] of Allowed Calls. | | `hasBothAddControllerAndEditPermissions` | `bool` | - | #### Returns -| Name | Type | Description | -| ---- | :-------: | --------------------------------- | -| `0` | `bytes32` | either ADD or CHANGE PERMISSIONS. | +| Name | Type | Description | +| ---- | :-------: | ------------------------------- | +| `0` | `bytes32` | Either ADD or EDIT PERMISSIONS. |
@@ -644,22 +644,22 @@ function _getPermissionToSetAllowedERC725YDataKeys( ) internal view returns (bytes32); ``` -retrieve the permission required to set some Allowed ERC725Y Data Keys for a controller. +Retrieve the permission required to set some Allowed ERC725Y Data Keys for a controller. #### Parameters | Name | Type | Description | | ---------------------------------------- | :-------: | ----------------------------------------------------------------------------------------------------- | -| `controlledContract` | `address` | the address of the ERC725Y contract where the data key is verified. | -| `dataKey` | `bytes32` | or `AddressPermissions:AllowedERC725YDataKeys:`. | -| `dataValue` | `bytes` | the updated value for the `dataKey`. MUST be a bytes[CompactBytesArray] of Allowed ERC725Y Data Keys. | +| `controlledContract` | `address` | the address of the ERC725Y contract from which to fetch the value of `dataKey`. | +| `dataKey` | `bytes32` | A data key in the format `AddressPermissions:AllowedERC725YDataKeys:`. | +| `dataValue` | `bytes` | The updated value for the `dataKey`. MUST be a bytes[CompactBytesArray] of Allowed ERC725Y Data Keys. | | `hasBothAddControllerAndEditPermissions` | `bool` | - | #### Returns -| Name | Type | Description | -| ---- | :-------: | --------------------------------- | -| `0` | `bytes32` | either ADD or CHANGE PERMISSIONS. | +| Name | Type | Description | +| ---- | :-------: | ------------------------------- | +| `0` | `bytes32` | Either ADD or EDIT PERMISSIONS. |
diff --git a/tests/LSP20CallVerification/LSP6/SetPermissions/SetAllowedCalls.test.ts b/tests/LSP20CallVerification/LSP6/SetPermissions/SetAllowedCalls.test.ts index 233cb7f17..7a77517f0 100644 --- a/tests/LSP20CallVerification/LSP6/SetPermissions/SetAllowedCalls.test.ts +++ b/tests/LSP20CallVerification/LSP6/SetPermissions/SetAllowedCalls.test.ts @@ -18,9 +18,10 @@ export const shouldBehaveLikeSetAllowedCalls = (buildContext: () => Promise { let canOnlyAddController: SignerWithAddress, canOnlyEditPermissions: SignerWithAddress; - let beneficiary: SignerWithAddress; - let invalidBytes: SignerWithAddress; - let noBytes: SignerWithAddress; + let beneficiaryWithPermissions: SignerWithAddress, + beneficiaryNoPermissions: SignerWithAddress, + invalidBytes: SignerWithAddress, + noBytes: SignerWithAddress; before(async () => { context = await buildContext(); @@ -28,18 +29,20 @@ export const shouldBehaveLikeSetAllowedCalls = (buildContext: () => Promise Promise Promise Promise { - it('should revert and not be allowed to clear the list of allowed calls for an address', async () => { - const dataKey = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + - beneficiary.address.substring(2); - const dataValue = '0x'; + describe('when controller / beneficiary has some permissions', () => { + it('should revert and not be allowed to clear the list of allowed calls for an address', async () => { + const dataKey = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + + beneficiaryWithPermissions.address.substring(2); + const dataValue = '0x'; - await expect( - context.universalProfile.connect(canOnlyAddController).setData(dataKey, dataValue), - ) - .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') - .withArgs(canOnlyAddController.address, 'EDITPERMISSIONS'); + await expect( + context.universalProfile.connect(canOnlyAddController).setData(dataKey, dataValue), + ) + .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') + .withArgs(canOnlyAddController.address, 'EDITPERMISSIONS'); + }); + }); + + describe('when controller / beneficiary has no permissions', () => { + it('should pass and set the list of allowed calls for an address', async () => { + const dataKey = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + + beneficiaryNoPermissions.address.substring(2); + const dataValue = '0x'; + + await context.universalProfile.connect(canOnlyAddController).setData(dataKey, dataValue); + + expect(await context.universalProfile.getData(dataKey)).to.equal(dataValue); + }); }); }); - describe('when caller has CHANGE permission', () => { - it('should allow to clear the list of allowed calls for an address', async () => { - const dataKey = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + - beneficiary.address.substring(2); - const dataValue = '0x'; + describe('when caller has EDIT permission', () => { + describe('when controller / beneficiary has some permissions', () => { + it('should allow to clear the list of allowed calls for an address', async () => { + const dataKey = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + + beneficiaryWithPermissions.address.substring(2); + const dataValue = '0x'; + + await context.universalProfile + .connect(canOnlyEditPermissions) + .setData(dataKey, dataValue); - await context.universalProfile.connect(canOnlyEditPermissions).setData(dataKey, dataValue); + const result = await context.universalProfile.getData(dataKey); + expect(result).to.equal(dataValue); + }); + }); + + describe('when controller / beneficiary has no permissions', () => { + it("should revert with error `NotAuthorised('EDITPERMISSIONS')` when trying to clear the list of allowed calls for an address", async () => { + const dataKey = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + + beneficiaryNoPermissions.address.substring(2); + const dataValue = '0x'; - const result = await context.universalProfile.getData(dataKey); - expect(result).to.equal(dataValue); + await expect( + context.universalProfile.connect(canOnlyEditPermissions).setData(dataKey, dataValue), + ) + .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') + .withArgs(canOnlyEditPermissions.address, 'ADDCONTROLLER'); + }); }); }); }); @@ -115,14 +167,16 @@ export const shouldBehaveLikeSetAllowedCalls = (buildContext: () => Promise Promise Promise Promise Promise Promise { - it('should fail when trying to edit existing allowed functions for an address', async () => { - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + - beneficiary.address.substring(2); - - const value = combineAllowedCalls( - // allow beneficiary to make a CALL to only function selectors 0xcafecafe and 0xf00df00d - [CALLTYPE.CALL, CALLTYPE.CALL], - [ - '0xffffffffffffffffffffffffffffffffffffffff', - '0xffffffffffffffffffffffffffffffffffffffff', - ], - ['0xffffffff', '0xffffffff'], - ['0xcafecafe', '0xf00df00d'], - ); - - await expect(context.universalProfile.connect(canOnlyAddController).setData(key, value)) - .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') - .withArgs(canOnlyAddController.address, 'EDITPERMISSIONS'); - }); - - it('should fail with NotAuthorised -> when beneficiary address had an invalid bytes28[CompactBytesArray] initially', async () => { - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + - invalidBeneficiary.address.substring(2); - - const value = combineAllowedCalls( - // allow beneficiary to make a CALL to only function selectors 0xcafecafe and 0xf00df00d - [CALLTYPE.CALL, CALLTYPE.CALL], - [ - '0xffffffffffffffffffffffffffffffffffffffff', - '0xffffffffffffffffffffffffffffffffffffffff', - ], - ['0xffffffff', '0xffffffff'], - ['0xcafecafe', '0xf00df00d'], - ); - - await expect(context.universalProfile.connect(canOnlyAddController).setData(key, value)) - .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') - .withArgs(canOnlyAddController.address, 'EDITPERMISSIONS'); - }); - - // Even if the controller had some 00 bytes set as allowed calls, it is not considered as it does not have any allowed calls set - // but rather that its allowed calls are "disabled" - describe('when beneficiary (= controller) had 00 bytes set initially as allowed calls (e.g: allowed calls disabled)', () => { - it('should fail with NotAuthorised -> when beneficiary had 32 x 0 bytes set initially as allowed calls', async () => { + describe('when controller to edit Allowed Calls for has some permissions set', () => { + it('should fail when trying to edit existing allowed functions for an address', async () => { const key = ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + - zero32Bytes.address.substring(2); + beneficiary.address.substring(2); const value = combineAllowedCalls( - [CALLTYPE.VALUE, CALLTYPE.VALUE], - ['0xffffffff', '0xffffffff'], - ['0xcafecafe', '0xca11ca11'], + // allow beneficiary to make a CALL to only function selectors 0xcafecafe and 0xf00df00d + [CALLTYPE.CALL, CALLTYPE.CALL], [ '0xffffffffffffffffffffffffffffffffffffffff', '0xffffffffffffffffffffffffffffffffffffffff', ], + ['0xffffffff', '0xffffffff'], + ['0xcafecafe', '0xf00df00d'], ); await expect(context.universalProfile.connect(canOnlyAddController).setData(key, value)) @@ -556,49 +579,95 @@ export const shouldBehaveLikeSetAllowedCalls = (buildContext: () => Promise when beneficiary had 40 x 0 bytes set initially as allowed calls', async () => { + it('should fail with NotAuthorised -> when beneficiary address had an invalid bytes28[CompactBytesArray] initially', async () => { const key = ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + - zero40Bytes.address.substring(2); + invalidBeneficiary.address.substring(2); const value = combineAllowedCalls( + // allow beneficiary to make a CALL to only function selectors 0xcafecafe and 0xf00df00d [CALLTYPE.CALL, CALLTYPE.CALL], [ '0xffffffffffffffffffffffffffffffffffffffff', '0xffffffffffffffffffffffffffffffffffffffff', ], ['0xffffffff', '0xffffffff'], - ['0xcafecafe', '0xca11ca11'], + ['0xcafecafe', '0xf00df00d'], ); await expect(context.universalProfile.connect(canOnlyAddController).setData(key, value)) .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') .withArgs(canOnlyAddController.address, 'EDITPERMISSIONS'); }); - }); - it('should pass when beneficiary had no values set under AddressPermissions:AllowedCalls:... + setting a valid bytes28[CompactBytesArray]', async () => { - const newController = ethers.Wallet.createRandom(); + // Even if the controller had some 00 bytes set as allowed calls, it is not considered as it does not have any allowed calls set + // but rather that its allowed calls are "disabled" + describe('when beneficiary (= controller) had 00 bytes set initially as allowed calls (e.g: allowed calls disabled)', () => { + it('should fail with NotAuthorised -> when beneficiary had 32 x 0 bytes set initially as allowed calls', async () => { + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + + zero32Bytes.address.substring(2); + + const value = combineAllowedCalls( + [CALLTYPE.VALUE, CALLTYPE.VALUE], + ['0xffffffff', '0xffffffff'], + ['0xcafecafe', '0xca11ca11'], + [ + '0xffffffffffffffffffffffffffffffffffffffff', + '0xffffffffffffffffffffffffffffffffffffffff', + ], + ); + + await expect(context.universalProfile.connect(canOnlyAddController).setData(key, value)) + .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') + .withArgs(canOnlyAddController.address, 'EDITPERMISSIONS'); + }); + + it('should fail with NotAuthorised -> when beneficiary had 40 x 0 bytes set initially as allowed calls', async () => { + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + + zero40Bytes.address.substring(2); + + const value = combineAllowedCalls( + [CALLTYPE.CALL, CALLTYPE.CALL], + [ + '0xffffffffffffffffffffffffffffffffffffffff', + '0xffffffffffffffffffffffffffffffffffffffff', + ], + ['0xffffffff', '0xffffffff'], + ['0xcafecafe', '0xca11ca11'], + ); + + await expect(context.universalProfile.connect(canOnlyAddController).setData(key, value)) + .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') + .withArgs(canOnlyAddController.address, 'EDITPERMISSIONS'); + }); + }); - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + newController.address.substr(2); + it('should pass when beneficiary had no values set under AddressPermissions:AllowedCalls:... + setting a valid bytes28[CompactBytesArray]', async () => { + const newController = ethers.Wallet.createRandom(); - const value = combineAllowedCalls( - // allow beneficiary to CALL only function selectors 0xcafecafe and 0xf00df00d - [CALLTYPE.CALL, CALLTYPE.CALL], - [ - '0xffffffffffffffffffffffffffffffffffffffff', - '0xffffffffffffffffffffffffffffffffffffffff', - ], - ['0xffffffff', '0xffffffff'], - ['0xcafecafe', '0xf00df00d'], - ); + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + + newController.address.substr(2); - await context.universalProfile.connect(canOnlyAddController).setData(key, value); + const value = combineAllowedCalls( + // allow beneficiary to CALL only function selectors 0xcafecafe and 0xf00df00d + [CALLTYPE.CALL, CALLTYPE.CALL], + [ + '0xffffffffffffffffffffffffffffffffffffffff', + '0xffffffffffffffffffffffffffffffffffffffff', + ], + ['0xffffffff', '0xffffffff'], + ['0xcafecafe', '0xf00df00d'], + ); - // prettier-ignore - const result = await context.universalProfile.getData(key); - expect(result).to.equal(value); + await context.universalProfile.connect(canOnlyAddController).setData(key, value); + + // prettier-ignore + const result = await context.universalProfile.getData(key); + expect(result).to.equal(value); + }); }); describe('when setting an invalid bytes28[CompactBytesArray] for a new beneficiary', () => { @@ -633,83 +702,37 @@ export const shouldBehaveLikeSetAllowedCalls = (buildContext: () => Promise { - it('should fail when beneficiary had no values set under AddressPermissions:AllowedCalls:...', async () => { - const newController = ethers.Wallet.createRandom(); - - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + newController.address.substr(2); - - const value = combineAllowedCalls( - // allow beneficiary to CALL only function selectors 0xcafecafe and 0xbeefbeef - [CALLTYPE.CALL, CALLTYPE.CALL], - [ - '0xffffffffffffffffffffffffffffffffffffffff', - '0xffffffffffffffffffffffffffffffffffffffff', - ], - ['0xffffffff', '0xffffffff'], - ['0xcafecafe', '0xbeefbeef'], - ); - - await expect(context.universalProfile.connect(canOnlyEditPermissions).setData(key, value)) - .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') - .withArgs(canOnlyEditPermissions.address, 'ADDCONTROLLER'); - }); - - it('should pass when trying to edit existing allowed bytes4 selectors under ANY:ANY:', async () => { - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + - beneficiary.address.substring(2); - - const value = combineAllowedCalls( - // allow beneficiary to CALL only function selectors 0xcafecafe and 0xbeefbeef - [CALLTYPE.CALL, CALLTYPE.CALL], - [ - '0xffffffffffffffffffffffffffffffffffffffff', - '0xffffffffffffffffffffffffffffffffffffffff', - ], - ['0xffffffff', '0xffffffff'], - ['0xcafecafe', '0xbeefbeef'], - ); - - await context.universalProfile.connect(canOnlyEditPermissions).setData(key, value); - - // prettier-ignore - const result = await context.universalProfile.getData(key); - expect(result).to.equal(value); - }); - - it('should pass when address had an invalid bytes28[CompactBytesArray] initially', async () => { - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + - invalidBeneficiary.address.substring(2); + describe('when controller to edit Allowed Calls for has some permissions set', () => { + it('should fail when beneficiary had no values set under AddressPermissions:AllowedCalls:...', async () => { + const newController = ethers.Wallet.createRandom(); - const value = combineAllowedCalls( - // allow beneficiary to CALL only function selectors 0xcafecafe and 0xbeefbeef - [CALLTYPE.CALL, CALLTYPE.CALL], - [ - '0xffffffffffffffffffffffffffffffffffffffff', - '0xffffffffffffffffffffffffffffffffffffffff', - ], - ['0xffffffff', '0xffffffff'], - ['0xcafecafe', '0xbeefbeef'], - ); + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + + newController.address.substr(2); - await context.universalProfile.connect(canOnlyEditPermissions).setData(key, value); + const value = combineAllowedCalls( + // allow beneficiary to CALL only function selectors 0xcafecafe and 0xbeefbeef + [CALLTYPE.CALL, CALLTYPE.CALL], + [ + '0xffffffffffffffffffffffffffffffffffffffff', + '0xffffffffffffffffffffffffffffffffffffffff', + ], + ['0xffffffff', '0xffffffff'], + ['0xcafecafe', '0xbeefbeef'], + ); - // prettier-ignore - const result = await context.universalProfile.getData(key); - expect(result).to.equal(value); - }); + await expect(context.universalProfile.connect(canOnlyEditPermissions).setData(key, value)) + .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') + .withArgs(canOnlyEditPermissions.address, 'ADDCONTROLLER'); + }); - // Even if the controller had some 00 bytes set as allowed calls, it is not considered as it does not have any allowed calls set - // but rather that its allowed calls are "disabled" - describe('when beneficiary (= controller) had 00 bytes set initially as allowed calls (e.g: allowed calls disabled)', () => { - it('should pass when address had 32 x 0 bytes set initially as allowed calls', async () => { + it('should pass when trying to edit existing allowed bytes4 selectors under ANY:ANY:', async () => { const key = ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + - zero32Bytes.address.substring(2); + beneficiary.address.substring(2); const value = combineAllowedCalls( + // allow beneficiary to CALL only function selectors 0xcafecafe and 0xbeefbeef [CALLTYPE.CALL, CALLTYPE.CALL], [ '0xffffffffffffffffffffffffffffffffffffffff', @@ -726,12 +749,13 @@ export const shouldBehaveLikeSetAllowedCalls = (buildContext: () => Promise { + it('should pass when address had an invalid bytes28[CompactBytesArray] initially', async () => { const key = ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + - zero40Bytes.address.substring(2); + invalidBeneficiary.address.substring(2); const value = combineAllowedCalls( + // allow beneficiary to CALL only function selectors 0xcafecafe and 0xbeefbeef [CALLTYPE.CALL, CALLTYPE.CALL], [ '0xffffffffffffffffffffffffffffffffffffffff', @@ -747,6 +771,52 @@ export const shouldBehaveLikeSetAllowedCalls = (buildContext: () => Promise { + it('should pass when address had 32 x 0 bytes set initially as allowed calls', async () => { + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + + zero32Bytes.address.substring(2); + + const value = combineAllowedCalls( + [CALLTYPE.CALL, CALLTYPE.CALL], + [ + '0xffffffffffffffffffffffffffffffffffffffff', + '0xffffffffffffffffffffffffffffffffffffffff', + ], + ['0xffffffff', '0xffffffff'], + ['0xcafecafe', '0xbeefbeef'], + ); + + await context.universalProfile.connect(canOnlyEditPermissions).setData(key, value); + + // prettier-ignore + const result = await context.universalProfile.getData(key); + expect(result).to.equal(value); + }); + + it('should pass when address had 40 x 0 bytes set initially as allowed functions', async () => { + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + + zero40Bytes.address.substring(2); + + const value = combineAllowedCalls( + [CALLTYPE.CALL, CALLTYPE.CALL], + [ + '0xffffffffffffffffffffffffffffffffffffffff', + '0xffffffffffffffffffffffffffffffffffffffff', + ], + ['0xffffffff', '0xffffffff'], + ['0xcafecafe', '0xbeefbeef'], + ); + + await context.universalProfile.connect(canOnlyEditPermissions).setData(key, value); + + // prettier-ignore + const result = await context.universalProfile.getData(key); + expect(result).to.equal(value); + }); + }); }); describe('when changing the list of selectors in allowed calls from existing ANY:ANY: to an invalid value', () => { @@ -796,14 +866,16 @@ export const shouldBehaveLikeSetAllowedCalls = (buildContext: () => Promise Promise Promise { - it('should fail when trying to edit existing allowed standards for an address', async () => { - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + - beneficiary.address.substring(2); - - const value = combineAllowedCalls( - [CALLTYPE.CALL, CALLTYPE.CALL, CALLTYPE.CALL, CALLTYPE.CALL], - [ - '0xffffffffffffffffffffffffffffffffffffffff', - '0xffffffffffffffffffffffffffffffffffffffff', - '0xffffffffffffffffffffffffffffffffffffffff', - '0xffffffffffffffffffffffffffffffffffffffff', - ], - [ - INTERFACE_IDS.LSP7DigitalAsset, - INTERFACE_IDS.ERC20, - // add NFT standards (new LSP8 + old ERC721) - // in the list of allowed calls for the beneficiary controller - // (in addition to token contracts LSP7 + ERC20) - INTERFACE_IDS.LSP8IdentifiableDigitalAsset, - INTERFACE_IDS.ERC721, - ], - ['0xffffffff', '0xffffffff', '0xffffffff', '0xffffffff'], - ); - - await expect(context.universalProfile.connect(canOnlyAddController).setData(key, value)) - .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') - .withArgs(canOnlyAddController.address, 'EDITPERMISSIONS'); - }); - - it('should fail with NotAuthorised -> when beneficiary address had an invalid bytes28[CompactBytesArray] initially', async () => { - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + - invalidBeneficiary.address.substring(2); - - const value = combineAllowedCalls( - [CALLTYPE.CALL, CALLTYPE.CALL, CALLTYPE.CALL, CALLTYPE.CALL], - [ - '0xffffffffffffffffffffffffffffffffffffffff', - '0xffffffffffffffffffffffffffffffffffffffff', - '0xffffffffffffffffffffffffffffffffffffffff', - '0xffffffffffffffffffffffffffffffffffffffff', - ], - [ - INTERFACE_IDS.LSP7DigitalAsset, - INTERFACE_IDS.ERC20, - // add NFT standards (new LSP8 + old ERC721) - // in the list of allowed calls for the beneficiary controller - // (in addition to token standards LSP7 + ERC20) - INTERFACE_IDS.LSP8IdentifiableDigitalAsset, - INTERFACE_IDS.ERC721, - ], - ['0xffffffff', '0xffffffff', '0xffffffff', '0xffffffff'], - ); - - await expect(context.universalProfile.connect(canOnlyAddController).setData(key, value)) - .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') - .withArgs(canOnlyAddController.address, 'EDITPERMISSIONS'); - }); - - // Even if the controller had some 00 bytes set as allowed calls, it is not considered as it does not have any allowed calls set - // but rather that its allowed calls are "disabled" - describe('when beneficiary (= controller) had 00 bytes set initially as allowed calls (e.g: allowed calls disabled)', () => { - it('should fail with NotAuthorised -> when beneficiary had 32 x 0 bytes set initially as allowed calls', async () => { + describe('when controller / beneficiary has some allowed calls set', () => { + it('should fail when trying to edit existing allowed standards for an address', async () => { const key = ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + - zero32Bytes.address.substring(2); + beneficiary.address.substring(2); const value = combineAllowedCalls( [CALLTYPE.CALL, CALLTYPE.CALL, CALLTYPE.CALL, CALLTYPE.CALL], @@ -910,6 +924,9 @@ export const shouldBehaveLikeSetAllowedCalls = (buildContext: () => Promise Promise when beneficiary had 40 x 0 bytes set initially as allowed calls', async () => { + it('should fail with NotAuthorised -> when beneficiary address had an invalid bytes28[CompactBytesArray] initially', async () => { const key = ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + - zero40Bytes.address.substring(2); + invalidBeneficiary.address.substring(2); const value = combineAllowedCalls( [CALLTYPE.CALL, CALLTYPE.CALL, CALLTYPE.CALL, CALLTYPE.CALL], @@ -937,6 +954,9 @@ export const shouldBehaveLikeSetAllowedCalls = (buildContext: () => Promise Promise { + it('should fail with NotAuthorised -> when beneficiary had 32 x 0 bytes set initially as allowed calls', async () => { + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + + zero32Bytes.address.substring(2); + + const value = combineAllowedCalls( + [CALLTYPE.CALL, CALLTYPE.CALL, CALLTYPE.CALL, CALLTYPE.CALL], + [ + '0xffffffffffffffffffffffffffffffffffffffff', + '0xffffffffffffffffffffffffffffffffffffffff', + '0xffffffffffffffffffffffffffffffffffffffff', + '0xffffffffffffffffffffffffffffffffffffffff', + ], + [ + INTERFACE_IDS.LSP7DigitalAsset, + INTERFACE_IDS.ERC20, + INTERFACE_IDS.LSP8IdentifiableDigitalAsset, + INTERFACE_IDS.ERC721, + ], + ['0xffffffff', '0xffffffff', '0xffffffff', '0xffffffff'], + ); + + await expect(context.universalProfile.connect(canOnlyAddController).setData(key, value)) + .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') + .withArgs(canOnlyAddController.address, 'EDITPERMISSIONS'); + }); + + it('should fail with NotAuthorised -> when beneficiary had 40 x 0 bytes set initially as allowed calls', async () => { + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + + zero40Bytes.address.substring(2); + + const value = combineAllowedCalls( + [CALLTYPE.CALL, CALLTYPE.CALL, CALLTYPE.CALL, CALLTYPE.CALL], + [ + '0xffffffffffffffffffffffffffffffffffffffff', + '0xffffffffffffffffffffffffffffffffffffffff', + '0xffffffffffffffffffffffffffffffffffffffff', + '0xffffffffffffffffffffffffffffffffffffffff', + ], + [ + INTERFACE_IDS.LSP7DigitalAsset, + INTERFACE_IDS.ERC20, + INTERFACE_IDS.LSP8IdentifiableDigitalAsset, + INTERFACE_IDS.ERC721, + ], + ['0xffffffff', '0xffffffff', '0xffffffff', '0xffffffff'], + ); + + await expect(context.universalProfile.connect(canOnlyAddController).setData(key, value)) + .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') + .withArgs(canOnlyAddController.address, 'EDITPERMISSIONS'); + }); + }); }); it('should pass when beneficiary had no values set under AddressPermissions:AllowedCalls:... + setting a valid bytes28[CompactBytesArray]', async () => { @@ -1014,91 +1092,13 @@ export const shouldBehaveLikeSetAllowedCalls = (buildContext: () => Promise { - it('should fail when beneficiary had no values set under AddressPermissions:AllowedCalls:...', async () => { - const newController = ethers.Wallet.createRandom(); - - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + newController.address.substr(2); - - const value = combineAllowedCalls( - [CALLTYPE.CALL, CALLTYPE.CALL], - [ - '0xffffffffffffffffffffffffffffffffffffffff', - '0xffffffffffffffffffffffffffffffffffffffff', - ], - // try to add in the list of allowed calls for the beneficiary controller - // the rights to CALL any LSP7 or ERC20 token contract - // (NB: just the AllowedCalls, not the permission CALL) - [INTERFACE_IDS.LSP7DigitalAsset, INTERFACE_IDS.ERC20], - ['0xffffffff', '0xffffffff'], - ); - - await expect(context.universalProfile.connect(canOnlyEditPermissions).setData(key, value)) - .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') - .withArgs(canOnlyEditPermissions.address, 'ADDCONTROLLER'); - }); - - it('should pass when trying to edit existing allowed standards for an address', async () => { - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + - beneficiary.address.substring(2); - - const value = combineAllowedCalls( - [CALLTYPE.CALL, CALLTYPE.CALL, CALLTYPE.CALL, CALLTYPE.CALL], - [ - '0xffffffffffffffffffffffffffffffffffffffff', - '0xffffffffffffffffffffffffffffffffffffffff', - '0xffffffffffffffffffffffffffffffffffffffff', - '0xffffffffffffffffffffffffffffffffffffffff', - ], - [ - INTERFACE_IDS.LSP7DigitalAsset, - INTERFACE_IDS.ERC20, - // add NFT standards (new LSP8 + old ERC721) - // in the list of allowed calls for the beneficiary controller - // (in addition to token standards LSP7 + ERC20) - INTERFACE_IDS.LSP8IdentifiableDigitalAsset, - INTERFACE_IDS.ERC721, - ], - ['0xffffffff', '0xffffffff', '0xffffffff', '0xffffffff'], - ); - - await context.universalProfile.connect(canOnlyEditPermissions).setData(key, value); - - // prettier-ignore - const result = await context.universalProfile.getData(key); - expect(result).to.equal(value); - }); - - it('should pass when address had an invalid bytes28[CompactBytesArray] initially', async () => { - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + - invalidBeneficiary.address.substring(2); - - const value = combineAllowedCalls( - [CALLTYPE.CALL, CALLTYPE.CALL], - [ - '0xffffffffffffffffffffffffffffffffffffffff', - '0xffffffffffffffffffffffffffffffffffffffff', - ], - [INTERFACE_IDS.LSP7DigitalAsset, INTERFACE_IDS.ERC20], - ['0xffffffff', '0xffffffff'], - ); - - await context.universalProfile.connect(canOnlyEditPermissions).setData(key, value); - - // prettier-ignore - const result = await context.universalProfile.getData(key); - expect(result).to.equal(value); - }); + describe('when controller / beneificary had some allowed calls set', () => { + it('should fail when beneficiary had no values set under AddressPermissions:AllowedCalls:...', async () => { + const newController = ethers.Wallet.createRandom(); - // Even if the controller had some 00 bytes set as allowed calls, it is not considered as it does not have any allowed calls set - // but rather that its allowed calls are "disabled" - describe('when beneficiary (= controller) had 00 bytes set initially as allowed calls (e.g: allowed calls disabled)', () => { - it('should pass when address had 32 x 0 bytes set initially as allowed calls', async () => { const key = ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + - zero32Bytes.address.substring(2); + newController.address.substr(2); const value = combineAllowedCalls( [CALLTYPE.CALL, CALLTYPE.CALL], @@ -1106,10 +1106,43 @@ export const shouldBehaveLikeSetAllowedCalls = (buildContext: () => Promise { + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + + beneficiary.address.substring(2); + + const value = combineAllowedCalls( + [CALLTYPE.CALL, CALLTYPE.CALL, CALLTYPE.CALL, CALLTYPE.CALL], + [ + '0xffffffffffffffffffffffffffffffffffffffff', + '0xffffffffffffffffffffffffffffffffffffffff', + '0xffffffffffffffffffffffffffffffffffffffff', + '0xffffffffffffffffffffffffffffffffffffffff', + ], + [ + INTERFACE_IDS.LSP7DigitalAsset, + INTERFACE_IDS.ERC20, + // add NFT standards (new LSP8 + old ERC721) + // in the list of allowed calls for the beneficiary controller + // (in addition to token standards LSP7 + ERC20) + INTERFACE_IDS.LSP8IdentifiableDigitalAsset, + INTERFACE_IDS.ERC721, + ], + ['0xffffffff', '0xffffffff', '0xffffffff', '0xffffffff'], + ); + await context.universalProfile.connect(canOnlyEditPermissions).setData(key, value); // prettier-ignore @@ -1117,10 +1150,10 @@ export const shouldBehaveLikeSetAllowedCalls = (buildContext: () => Promise { + it('should pass when address had an invalid bytes28[CompactBytesArray] initially', async () => { const key = ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + - zero40Bytes.address.substring(2); + invalidBeneficiary.address.substring(2); const value = combineAllowedCalls( [CALLTYPE.CALL, CALLTYPE.CALL], @@ -1138,6 +1171,52 @@ export const shouldBehaveLikeSetAllowedCalls = (buildContext: () => Promise { + it('should pass when address had 32 x 0 bytes set initially as allowed calls', async () => { + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + + zero32Bytes.address.substring(2); + + const value = combineAllowedCalls( + [CALLTYPE.CALL, CALLTYPE.CALL], + [ + '0xffffffffffffffffffffffffffffffffffffffff', + '0xffffffffffffffffffffffffffffffffffffffff', + ], + [INTERFACE_IDS.LSP7DigitalAsset, INTERFACE_IDS.ERC20], + ['0xffffffff', '0xffffffff'], + ); + + await context.universalProfile.connect(canOnlyEditPermissions).setData(key, value); + + // prettier-ignore + const result = await context.universalProfile.getData(key); + expect(result).to.equal(value); + }); + + it('should pass when address had 40 x 0 bytes set initially as allowed calls', async () => { + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + + zero40Bytes.address.substring(2); + + const value = combineAllowedCalls( + [CALLTYPE.CALL, CALLTYPE.CALL], + [ + '0xffffffffffffffffffffffffffffffffffffffff', + '0xffffffffffffffffffffffffffffffffffffffff', + ], + [INTERFACE_IDS.LSP7DigitalAsset, INTERFACE_IDS.ERC20], + ['0xffffffff', '0xffffffff'], + ); + + await context.universalProfile.connect(canOnlyEditPermissions).setData(key, value); + + // prettier-ignore + const result = await context.universalProfile.getData(key); + expect(result).to.equal(value); + }); + }); }); describe('when changing the list of interface IDs in allowed calls :ANY:ANY to an invalid value', () => { diff --git a/tests/LSP20CallVerification/LSP6/SetPermissions/SetAllowedERC725YDataKeys.test.ts b/tests/LSP20CallVerification/LSP6/SetPermissions/SetAllowedERC725YDataKeys.test.ts index 5bc43bc5b..cfbe6cc53 100644 --- a/tests/LSP20CallVerification/LSP6/SetPermissions/SetAllowedERC725YDataKeys.test.ts +++ b/tests/LSP20CallVerification/LSP6/SetPermissions/SetAllowedERC725YDataKeys.test.ts @@ -36,24 +36,27 @@ export const shouldBehaveLikeSetAllowedERC725YDataKeys = ( zero32Bytes = context.accounts[5]; zero40Bytes = context.accounts[6]; + // prettier-ignore const permissionKeys = [ - ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + - canOnlyAddController.address.substring(2), - ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + - canOnlyEditPermissions.address.substring(2), - ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + - beneficiary.address.substring(2), - ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + - invalidBeneficiary.address.substring(2), - ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + - zero32Bytes.address.substring(2), - ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + - zero40Bytes.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + canOnlyAddController.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + canOnlyEditPermissions.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + beneficiary.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + invalidBeneficiary.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + zero32Bytes.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + zero40Bytes.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + beneficiary.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + invalidBeneficiary.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + zero32Bytes.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + zero40Bytes.address.substring(2), ]; const permissionValues = [ PERMISSIONS.ADDCONTROLLER, PERMISSIONS.EDITPERMISSIONS, + PERMISSIONS.SETDATA, + PERMISSIONS.SETDATA, + PERMISSIONS.SETDATA, + PERMISSIONS.SETDATA, encodeCompactBytesArray([ ERC725YDataKeys.LSP3['LSP3Profile'], // prettier-ignore @@ -68,205 +71,211 @@ export const shouldBehaveLikeSetAllowedERC725YDataKeys = ( }); describe('when caller has ADDCONTROLLER', () => { - describe('when beneficiary had some ERC725Y data keys set under AddressPermissions:AllowedERC725YDataKeys:...', () => { - it('should fail when adding an extra allowed ERC725Y data key', async () => { - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + - beneficiary.address.substring(2); - - const value = encodeCompactBytesArray([ - ERC725YDataKeys.LSP3['LSP3Profile'], - // prettier-ignore - ethers.utils.keccak256(ethers.utils.toUtf8Bytes("Some Custom Profile Data Key")), - // prettier-ignore - ethers.utils.keccak256(ethers.utils.toUtf8Bytes("Another Custom Data Key")), - ]); - - await expect(context.universalProfile.connect(canOnlyAddController).setData(key, value)) - .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') - .withArgs(canOnlyAddController.address, 'EDITPERMISSIONS'); - }); - - it('should fail when removing an allowed ERC725Y data key', async () => { - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + - beneficiary.address.substring(2); - - const value = encodeCompactBytesArray([ERC725YDataKeys.LSP3['LSP3Profile']]); - - await expect(context.universalProfile.connect(canOnlyAddController).setData(key, value)) - .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') - .withArgs(canOnlyAddController.address, 'EDITPERMISSIONS'); - }); - - it('should fail when trying to clear the CompactedBytesArray completely', async () => { - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + - beneficiary.address.substring(2); - - const value = '0x'; - - await expect(context.universalProfile.connect(canOnlyAddController).setData(key, value)) - .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') - .withArgs(canOnlyAddController.address, 'EDITPERMISSIONS'); + describe('when controller / beneficiary had some permissions set', () => { + describe('when beneficiary had some ERC725Y data keys set under AddressPermissions:AllowedERC725YDataKeys:...', () => { + it('should fail when adding an extra allowed ERC725Y data key', async () => { + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + + beneficiary.address.substring(2); + + const value = encodeCompactBytesArray([ + ERC725YDataKeys.LSP3['LSP3Profile'], + // prettier-ignore + ethers.utils.keccak256(ethers.utils.toUtf8Bytes("Some Custom Profile Data Key")), + // prettier-ignore + ethers.utils.keccak256(ethers.utils.toUtf8Bytes("Another Custom Data Key")), + ]); + + await expect(context.universalProfile.connect(canOnlyAddController).setData(key, value)) + .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') + .withArgs(canOnlyAddController.address, 'EDITPERMISSIONS'); + }); + + it('should fail when removing an allowed ERC725Y data key', async () => { + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + + beneficiary.address.substring(2); + + const value = encodeCompactBytesArray([ERC725YDataKeys.LSP3['LSP3Profile']]); + + await expect(context.universalProfile.connect(canOnlyAddController).setData(key, value)) + .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') + .withArgs(canOnlyAddController.address, 'EDITPERMISSIONS'); + }); + + it('should fail when trying to clear the CompactedBytesArray completely', async () => { + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + + beneficiary.address.substring(2); + + const value = '0x'; + + await expect(context.universalProfile.connect(canOnlyAddController).setData(key, value)) + .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') + .withArgs(canOnlyAddController.address, 'EDITPERMISSIONS'); + }); + + it('should fail when setting an invalid CompactedBytesArray', async () => { + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + + beneficiary.address.substring(2); + + const value = '0xbadbadbadbad'; + + await expect( + context.universalProfile.connect(canOnlyAddController).setData(key, value), + ).to.be.revertedWithCustomError( + context.keyManager, + 'InvalidEncodedAllowedERC725YDataKeys', + ); + }); }); - it('should fail when setting an invalid CompactedBytesArray', async () => { - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + - beneficiary.address.substring(2); - - const value = '0xbadbadbadbad'; + describe('when beneficiary had no ERC725Y data keys set under AddressPermissions:AllowedERC725YDataKeys:...', () => { + it('should pass when setting a valid CompactedBytesArray', async () => { + const newController = ethers.Wallet.createRandom(); - await expect( - context.universalProfile.connect(canOnlyAddController).setData(key, value), - ).to.be.revertedWithCustomError( - context.keyManager, - 'InvalidEncodedAllowedERC725YDataKeys', - ); - }); - }); + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + + newController.address.substr(2); - describe('when beneficiary had no ERC725Y data keys set under AddressPermissions:AllowedERC725YDataKeys:...', () => { - it('should pass when setting a valid CompactedBytesArray', async () => { - const newController = ethers.Wallet.createRandom(); + const value = encodeCompactBytesArray([ + // prettier-ignore + ethers.utils.keccak256(ethers.utils.toUtf8Bytes("My Custom Profile Key 1")), + // prettier-ignore + ethers.utils.keccak256(ethers.utils.toUtf8Bytes("My Custom Profile Key 2")), + ]); - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + - newController.address.substr(2); + await context.universalProfile.connect(canOnlyAddController).setData(key, value); - const value = encodeCompactBytesArray([ - // prettier-ignore - ethers.utils.keccak256(ethers.utils.toUtf8Bytes("My Custom Profile Key 1")), // prettier-ignore - ethers.utils.keccak256(ethers.utils.toUtf8Bytes("My Custom Profile Key 2")), - ]); - - await context.universalProfile.connect(canOnlyAddController).setData(key, value); - - // prettier-ignore - const result = await context.universalProfile.getData(key); - expect(result).to.equal(value); - }); - - it('should fail when setting an invalid CompactedBytesArray (random bytes)', async () => { - const newController = ethers.Wallet.createRandom(); - - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + - newController.address.substr(2); - - const value = '0xbadbadbadbad'; - - await expect( - context.universalProfile.connect(canOnlyAddController).setData(key, value), - ).to.be.revertedWithCustomError( - context.keyManager, - 'InvalidEncodedAllowedERC725YDataKeys', - ); + const result = await context.universalProfile.getData(key); + expect(result).to.equal(value); + }); + + it('should fail when setting an invalid CompactedBytesArray (random bytes)', async () => { + const newController = ethers.Wallet.createRandom(); + + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + + newController.address.substr(2); + + const value = '0xbadbadbadbad'; + + await expect( + context.universalProfile.connect(canOnlyAddController).setData(key, value), + ).to.be.revertedWithCustomError( + context.keyManager, + 'InvalidEncodedAllowedERC725YDataKeys', + ); + }); }); }); }); describe('when caller has EDITPERMISSIONS', () => { - describe('when beneficiary had some ERC725Y data keys set under AddressPermissions:AllowedERC725YDataKeys:...', () => { - it('should pass when adding an extra allowed ERC725Y data key', async () => { - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + - beneficiary.address.substring(2); - - const value = encodeCompactBytesArray([ - ERC725YDataKeys.LSP3['LSP3Profile'], - // prettier-ignore - ethers.utils.keccak256(ethers.utils.toUtf8Bytes("Some Custom Profile Data Key")), - // prettier-ignore - ethers.utils.keccak256(ethers.utils.toUtf8Bytes("Another Custom Data Key")), - ]); - - await context.universalProfile.connect(canOnlyEditPermissions).setData(key, value); - - // prettier-ignore - const result = await context.universalProfile.getData(key); - expect(result).to.equal(value); - }); - - it('should pass when removing an allowed ERC725Y data key', async () => { - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + - beneficiary.address.substring(2); - - const value = encodeCompactBytesArray([ERC725YDataKeys.LSP3['LSP3Profile']]); - - await context.universalProfile.connect(canOnlyEditPermissions).setData(key, value); - - // prettier-ignore - const result = await context.universalProfile.getData(key); - expect(result).to.equal(value); - }); - - it('should pass when trying to clear the CompactedBytesArray completely', async () => { - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + - beneficiary.address.substring(2); + describe('when controller / beneficiary had some permissions set', () => { + describe('when beneficiary had some ERC725Y data keys set under AddressPermissions:AllowedERC725YDataKeys:...', () => { + it('should pass when adding an extra allowed ERC725Y data key', async () => { + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + + beneficiary.address.substring(2); + + const value = encodeCompactBytesArray([ + ERC725YDataKeys.LSP3['LSP3Profile'], + // prettier-ignore + ethers.utils.keccak256(ethers.utils.toUtf8Bytes("Some Custom Profile Data Key")), + // prettier-ignore + ethers.utils.keccak256(ethers.utils.toUtf8Bytes("Another Custom Data Key")), + ]); + + await context.universalProfile.connect(canOnlyEditPermissions).setData(key, value); - const value = '0x'; - - await context.universalProfile.connect(canOnlyEditPermissions).setData(key, value); + // prettier-ignore + const result = await context.universalProfile.getData(key); + expect(result).to.equal(value); + }); - // prettier-ignore - const result = await context.universalProfile.getData(key); - expect(result).to.equal(value); - }); + it('should pass when removing an allowed ERC725Y data key', async () => { + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + + beneficiary.address.substring(2); - it('should fail when setting an invalid CompactedBytesArray', async () => { - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + - beneficiary.address.substring(2); + const value = encodeCompactBytesArray([ERC725YDataKeys.LSP3['LSP3Profile']]); - const value = '0xbadbadbadbad'; + await context.universalProfile.connect(canOnlyEditPermissions).setData(key, value); - await expect( - context.universalProfile.connect(canOnlyEditPermissions).setData(key, value), - ).to.be.revertedWithCustomError( - context.keyManager, - 'InvalidEncodedAllowedERC725YDataKeys', - ); - }); - }); + // prettier-ignore + const result = await context.universalProfile.getData(key); + expect(result).to.equal(value); + }); - describe('when beneficiary had no ERC725Y data keys set under AddressPermissions:AllowedERC725YDataKeys:...', () => { - it('should fail and not authorize to add a list of allowed ERC725Y data keys (not authorised)', async () => { - const newController = ethers.Wallet.createRandom(); + it('should pass when trying to clear the CompactedBytesArray completely', async () => { + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + + beneficiary.address.substring(2); - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + - newController.address.substr(2); + const value = '0x'; - const value = encodeCompactBytesArray([ - ethers.utils.keccak256(ethers.utils.toUtf8Bytes('My Custom Key 1')), - ethers.utils.keccak256(ethers.utils.toUtf8Bytes('My Custom Key 2')), - ]); + await context.universalProfile.connect(canOnlyEditPermissions).setData(key, value); - await expect(context.universalProfile.connect(canOnlyEditPermissions).setData(key, value)) - .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') - .withArgs(canOnlyEditPermissions.address, 'ADDCONTROLLER'); + // prettier-ignore + const result = await context.universalProfile.getData(key); + expect(result).to.equal(value); + }); + + it('should fail when setting an invalid CompactedBytesArray', async () => { + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + + beneficiary.address.substring(2); + + const value = '0xbadbadbadbad'; + + await expect( + context.universalProfile.connect(canOnlyEditPermissions).setData(key, value), + ).to.be.revertedWithCustomError( + context.keyManager, + 'InvalidEncodedAllowedERC725YDataKeys', + ); + }); }); - it('should fail when setting an invalid CompactedBytesArray', async () => { - const newController = ethers.Wallet.createRandom(); - - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + - newController.address.substr(2); - - const value = '0xbadbadbadbad'; - - await expect( - context.universalProfile.connect(canOnlyEditPermissions).setData(key, value), - ).to.be.revertedWithCustomError( - context.keyManager, - 'InvalidEncodedAllowedERC725YDataKeys', - ); + describe('when beneficiary had no ERC725Y data keys set under AddressPermissions:AllowedERC725YDataKeys:...', () => { + it('should fail and not authorize to add a list of allowed ERC725Y data keys (not authorised)', async () => { + const newController = ethers.Wallet.createRandom(); + + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + + newController.address.substr(2); + + const value = encodeCompactBytesArray([ + ethers.utils.keccak256(ethers.utils.toUtf8Bytes('My Custom Key 1')), + ethers.utils.keccak256(ethers.utils.toUtf8Bytes('My Custom Key 2')), + ]); + + await expect( + context.universalProfile.connect(canOnlyEditPermissions).setData(key, value), + ) + .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') + .withArgs(canOnlyEditPermissions.address, 'ADDCONTROLLER'); + }); + + it('should fail when setting an invalid CompactedBytesArray', async () => { + const newController = ethers.Wallet.createRandom(); + + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + + newController.address.substr(2); + + const value = '0xbadbadbadbad'; + + await expect( + context.universalProfile.connect(canOnlyEditPermissions).setData(key, value), + ).to.be.revertedWithCustomError( + context.keyManager, + 'InvalidEncodedAllowedERC725YDataKeys', + ); + }); }); }); }); diff --git a/tests/LSP6KeyManager/SetPermissions/SetAllowedCalls.test.ts b/tests/LSP6KeyManager/SetPermissions/SetAllowedCalls.test.ts index 92bc2325b..3ad8fbfa2 100644 --- a/tests/LSP6KeyManager/SetPermissions/SetAllowedCalls.test.ts +++ b/tests/LSP6KeyManager/SetPermissions/SetAllowedCalls.test.ts @@ -86,7 +86,7 @@ export const shouldBehaveLikeSettingAllowedCalls = ( await setupKeyManager(context, permissionKeys, permissionValues); }); - describe('when caller has ADD_CONTROLLER', () => { + describe('when caller has permission ADD_CONTROLLER', () => { describe('when controller in `AddressPermissions:AllowedCalls:` has some permissions', () => { it('should revert and not be allowed to clear the list of allowed calls', async () => { const dataKey = @@ -182,14 +182,16 @@ export const shouldBehaveLikeSettingAllowedCalls = ( zero32Bytes = context.accounts[5]; zero40Bytes = context.accounts[6]; + // prettier-ignore const permissionKeys = [ - ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + - canOnlyAddController.address.substring(2), - ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + - canOnlyEditPermissions.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + canOnlyAddController.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + canOnlyEditPermissions.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + beneficiary.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + invalidBeneficiary.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + zero32Bytes.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + zero40Bytes.address.substring(2), ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + beneficiary.address.substring(2), - ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + - invalidBeneficiary.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + invalidBeneficiary.address.substring(2), ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + zero32Bytes.address.substring(2), ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + zero40Bytes.address.substring(2), ]; @@ -197,6 +199,10 @@ export const shouldBehaveLikeSettingAllowedCalls = ( const permissionValues = [ PERMISSIONS.ADDCONTROLLER, PERMISSIONS.EDITPERMISSIONS, + PERMISSIONS.CALL, + PERMISSIONS.CALL, + PERMISSIONS.CALL, + PERMISSIONS.CALL, combineAllowedCalls( // allow the beneficiary to transfer value to addresses 0xcafe... and 0xbeef... [CALLTYPE.VALUE, CALLTYPE.VALUE], @@ -218,71 +224,17 @@ export const shouldBehaveLikeSettingAllowedCalls = ( }); describe('when caller has permission ADDCONTROLLER', () => { - it('should fail when trying to edit existing allowed addresses for an address', async () => { - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + - beneficiary.address.substring(2); - - const value = combineAllowedCalls( - [CALLTYPE.VALUE, CALLTYPE.VALUE], - [ - '0xcafecafecafecafecafecafecafecafecafecafe', - '0xca11ca11ca11ca11ca11ca11ca11ca11ca11ca11', - ], - ['0xffffffff', '0xffffffff'], - ['0xffffffff', '0xffffffff'], - ); - - const payload = context.universalProfile.interface.encodeFunctionData('setData', [ - key, - value, - ]); - - await expect(context.keyManager.connect(canOnlyAddController).execute(payload)) - .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') - .withArgs(canOnlyAddController.address, 'EDITPERMISSIONS'); - }); - - it('should fail with NotAuthorised -> when beneficiary address had an invalid bytes28[CompatBytesArray]', async () => { - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + - invalidBeneficiary.address.substring(2); - - // try to set for the invalidBeneficiary some allowed calls - // that allow it to transfer value to addresses 0xcafe... and 0xbeef... - const value = combineAllowedCalls( - [CALLTYPE.VALUE, CALLTYPE.VALUE], - [ - '0xcafecafecafecafecafecafecafecafecafecafe', - '0xbeefbeefbeefbeefbeefbeefbeefbeefbeefbeef', - ], - ['0xffffffff', '0xffffffff'], - ['0xffffffff', '0xffffffff'], - ); - - const payload = context.universalProfile.interface.encodeFunctionData('setData', [ - key, - value, - ]); - - await expect(context.keyManager.connect(canOnlyAddController).execute(payload)) - .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') - .withArgs(canOnlyAddController.address, 'EDITPERMISSIONS'); - }); - - // even if the controller had some 00 bytes set as allowed calls, it is not considered as it does not have any allowed calls set - // but rather that its allowed calls are "disabled" - describe('when beneficiary (= controller) had 00 bytes set initially as allowed calls (e.g: allowed calls disabled)', () => { - it('should fail with NotAuthorised -> when beneficiary had 32 x 0 bytes set initially as allowed calls', async () => { + describe('when the controller to edit the AllowedCalls for has some permissions', () => { + it('should fail when trying to edit existing allowed addresses for an address', async () => { const key = ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + - zero32Bytes.address.substring(2); + beneficiary.address.substring(2); const value = combineAllowedCalls( [CALLTYPE.VALUE, CALLTYPE.VALUE], [ '0xcafecafecafecafecafecafecafecafecafecafe', - '0xbeefbeefbeefbeefbeefbeefbeefbeefbeefbeef', + '0xca11ca11ca11ca11ca11ca11ca11ca11ca11ca11', ], ['0xffffffff', '0xffffffff'], ['0xffffffff', '0xffffffff'], @@ -298,11 +250,13 @@ export const shouldBehaveLikeSettingAllowedCalls = ( .withArgs(canOnlyAddController.address, 'EDITPERMISSIONS'); }); - it('should fail with NotAuthorised -> when beneficiary had 40 x 0 bytes set initially as allowed calls', async () => { + it('should fail with NotAuthorised -> when beneficiary address had an invalid bytes32[CompactBytesArray]', async () => { const key = ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + - zero40Bytes.address.substring(2); + invalidBeneficiary.address.substring(2); + // try to set for the invalidBeneficiary some allowed calls + // that allow it to transfer value to addresses 0xcafe... and 0xbeef... const value = combineAllowedCalls( [CALLTYPE.VALUE, CALLTYPE.VALUE], [ @@ -322,36 +276,89 @@ export const shouldBehaveLikeSettingAllowedCalls = ( .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') .withArgs(canOnlyAddController.address, 'EDITPERMISSIONS'); }); - }); - it('should pass when beneficiary had no values set under AddressPermissions:AllowedCalls:... + setting a valid bytes28[CompactBytesArray]', async () => { - const newController = ethers.Wallet.createRandom(); + describe('when beneficiary (= controller) had 00 bytes set initially as allowed calls (e.g: allowed calls disabled)', () => { + it('should fail with NotAuthorised -> when beneficiary had 32 x 0 bytes set initially as allowed calls', async () => { + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + + zero32Bytes.address.substring(2); + + const value = combineAllowedCalls( + [CALLTYPE.VALUE, CALLTYPE.VALUE], + [ + '0xcafecafecafecafecafecafecafecafecafecafe', + '0xbeefbeefbeefbeefbeefbeefbeefbeefbeefbeef', + ], + ['0xffffffff', '0xffffffff'], + ['0xffffffff', '0xffffffff'], + ); + + const payload = context.universalProfile.interface.encodeFunctionData('setData', [ + key, + value, + ]); + + await expect(context.keyManager.connect(canOnlyAddController).execute(payload)) + .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') + .withArgs(canOnlyAddController.address, 'EDITPERMISSIONS'); + }); + + it('should fail with NotAuthorised -> when beneficiary had 40 x 0 bytes set initially as allowed calls', async () => { + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + + zero40Bytes.address.substring(2); + + const value = combineAllowedCalls( + [CALLTYPE.VALUE, CALLTYPE.VALUE], + [ + '0xcafecafecafecafecafecafecafecafecafecafe', + '0xbeefbeefbeefbeefbeefbeefbeefbeefbeefbeef', + ], + ['0xffffffff', '0xffffffff'], + ['0xffffffff', '0xffffffff'], + ); + + const payload = context.universalProfile.interface.encodeFunctionData('setData', [ + key, + value, + ]); + + await expect(context.keyManager.connect(canOnlyAddController).execute(payload)) + .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') + .withArgs(canOnlyAddController.address, 'EDITPERMISSIONS'); + }); + }); - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + newController.address.substr(2); + it('should pass when beneficiary had no values set under AddressPermissions:AllowedCalls:... + setting a valid bytes28[CompactBytesArray]', async () => { + const newController = ethers.Wallet.createRandom(); - // set for the newController some allowed calls - // that allow it to transfer value to addresses 0xcafe... and 0xbeef... - const value = combineAllowedCalls( - [CALLTYPE.VALUE, CALLTYPE.VALUE], - [ - '0xcafecafecafecafecafecafecafecafecafecafe', - '0xbeefbeefbeefbeefbeefbeefbeefbeefbeefbeef', - ], - ['0xffffffff', '0xffffffff'], - ['0xffffffff', '0xffffffff'], - ); + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + + newController.address.substr(2); - const payload = context.universalProfile.interface.encodeFunctionData('setData', [ - key, - value, - ]); + // set for the newController some allowed calls + // that allow it to transfer value to addresses 0xcafe... and 0xbeef... + const value = combineAllowedCalls( + [CALLTYPE.VALUE, CALLTYPE.VALUE], + [ + '0xcafecafecafecafecafecafecafecafecafecafe', + '0xbeefbeefbeefbeefbeefbeefbeefbeefbeefbeef', + ], + ['0xffffffff', '0xffffffff'], + ['0xffffffff', '0xffffffff'], + ); - await context.keyManager.connect(canOnlyAddController).execute(payload); + const payload = context.universalProfile.interface.encodeFunctionData('setData', [ + key, + value, + ]); - // prettier-ignore - const result = await context.universalProfile.getData(key); - expect(result).to.equal(value); + await context.keyManager.connect(canOnlyAddController).execute(payload); + + // prettier-ignore + const result = await context.universalProfile.getData(key); + expect(result).to.equal(value); + }); }); describe('when setting an invalid bytes28[CompactBytesArray] for a new beneficiary', () => { @@ -597,14 +604,16 @@ export const shouldBehaveLikeSettingAllowedCalls = ( zero32Bytes = context.accounts[5]; zero40Bytes = context.accounts[6]; + // prettier-ignore const permissionKeys = [ - ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + - canOnlyAddController.address.substring(2), - ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + - canOnlyEditPermissions.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + canOnlyAddController.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + canOnlyEditPermissions.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + beneficiary.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + invalidBeneficiary.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + zero32Bytes.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + zero40Bytes.address.substring(2), ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + beneficiary.address.substring(2), - ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + - invalidBeneficiary.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + invalidBeneficiary.address.substring(2), ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + zero32Bytes.address.substring(2), ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + zero40Bytes.address.substring(2), ]; @@ -612,6 +621,10 @@ export const shouldBehaveLikeSettingAllowedCalls = ( const permissionValues = [ PERMISSIONS.ADDCONTROLLER, PERMISSIONS.EDITPERMISSIONS, + PERMISSIONS.CALL, + PERMISSIONS.CALL, + PERMISSIONS.CALL, + PERMISSIONS.CALL, combineAllowedCalls( [CALLTYPE.CALL, CALLTYPE.CALL], [ @@ -630,74 +643,21 @@ export const shouldBehaveLikeSettingAllowedCalls = ( }); describe('when caller has permission ADDCONTROLLER', () => { - it('should fail when trying to edit existing allowed functions for an address', async () => { - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + - beneficiary.address.substring(2); - - const value = combineAllowedCalls( - // allow beneficiary to make a CALL to only function selectors 0xcafecafe and 0xf00df00d - [CALLTYPE.CALL, CALLTYPE.CALL], - [ - '0xffffffffffffffffffffffffffffffffffffffff', - '0xffffffffffffffffffffffffffffffffffffffff', - ], - ['0xffffffff', '0xffffffff'], - ['0xcafecafe', '0xf00df00d'], - ); - - const payload = context.universalProfile.interface.encodeFunctionData('setData', [ - key, - value, - ]); - - await expect(context.keyManager.connect(canOnlyAddController).execute(payload)) - .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') - .withArgs(canOnlyAddController.address, 'EDITPERMISSIONS'); - }); - - it('should fail with NotAuthorised -> when beneficiary address had an invalid bytes28[CompactBytesArray] initially', async () => { - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + - invalidBeneficiary.address.substring(2); - - const value = combineAllowedCalls( - // allow beneficiary to make a CALL to only function selectors 0xcafecafe and 0xf00df00d - [CALLTYPE.CALL, CALLTYPE.CALL], - [ - '0xffffffffffffffffffffffffffffffffffffffff', - '0xffffffffffffffffffffffffffffffffffffffff', - ], - ['0xffffffff', '0xffffffff'], - ['0xcafecafe', '0xf00df00d'], - ); - - const payload = context.universalProfile.interface.encodeFunctionData('setData', [ - key, - value, - ]); - - await expect(context.keyManager.connect(canOnlyAddController).execute(payload)) - .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') - .withArgs(canOnlyAddController.address, 'EDITPERMISSIONS'); - }); - - // even if the controller had some 00 bytes set as allowed calls, it is not considered as it does not have any allowed calls set - // but rather that its allowed calls are "disabled" - describe('when beneficiary (= controller) had 00 bytes set initially as allowed calls (e.g: allowed calls disabled)', () => { - it('should fail with NotAuthorised -> when beneficiary had 32 x 0 bytes set initially as allowed calls', async () => { + describe('when controller to edit Allowed Calls for has some permissions set', () => { + it('should fail when trying to edit existing allowed functions for an address', async () => { const key = ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + - zero32Bytes.address.substring(2); + beneficiary.address.substring(2); const value = combineAllowedCalls( + // allow beneficiary to make a CALL to only function selectors 0xcafecafe and 0xf00df00d [CALLTYPE.CALL, CALLTYPE.CALL], [ '0xffffffffffffffffffffffffffffffffffffffff', '0xffffffffffffffffffffffffffffffffffffffff', ], ['0xffffffff', '0xffffffff'], - ['0xcafecafe', '0xca11ca11'], + ['0xcafecafe', '0xf00df00d'], ); const payload = context.universalProfile.interface.encodeFunctionData('setData', [ @@ -710,19 +670,20 @@ export const shouldBehaveLikeSettingAllowedCalls = ( .withArgs(canOnlyAddController.address, 'EDITPERMISSIONS'); }); - it('should fail with NotAuthorised -> when beneficiary had 40 x 0 bytes set initially as allowed calls', async () => { + it('should fail with NotAuthorised -> when beneficiary address had an invalid bytes28[CompactBytesArray] initially', async () => { const key = ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + - zero40Bytes.address.substring(2); + invalidBeneficiary.address.substring(2); const value = combineAllowedCalls( + // allow beneficiary to make a CALL to only function selectors 0xcafecafe and 0xf00df00d [CALLTYPE.CALL, CALLTYPE.CALL], [ '0xffffffffffffffffffffffffffffffffffffffff', '0xffffffffffffffffffffffffffffffffffffffff', ], ['0xffffffff', '0xffffffff'], - ['0xcafecafe', '0xca11ca11'], + ['0xcafecafe', '0xf00df00d'], ); const payload = context.universalProfile.interface.encodeFunctionData('setData', [ @@ -734,35 +695,90 @@ export const shouldBehaveLikeSettingAllowedCalls = ( .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') .withArgs(canOnlyAddController.address, 'EDITPERMISSIONS'); }); - }); - it('should pass when beneficiary had no values set under AddressPermissions:AllowedCalls:... + setting a valid bytes28[CompactBytesArray]', async () => { - const newController = ethers.Wallet.createRandom(); + // even if the controller had some 00 bytes set as allowed calls, it is not considered as it does not have any allowed calls set + // but rather that its allowed calls are "disabled" + describe('when beneficiary (= controller) had 00 bytes set initially as allowed calls (e.g: allowed calls disabled)', () => { + it('should fail with NotAuthorised -> when beneficiary had 32 x 0 bytes set initially as allowed calls', async () => { + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + + zero32Bytes.address.substring(2); + + const value = combineAllowedCalls( + [CALLTYPE.CALL, CALLTYPE.CALL], + [ + '0xffffffffffffffffffffffffffffffffffffffff', + '0xffffffffffffffffffffffffffffffffffffffff', + ], + ['0xffffffff', '0xffffffff'], + ['0xcafecafe', '0xca11ca11'], + ); + + const payload = context.universalProfile.interface.encodeFunctionData('setData', [ + key, + value, + ]); + + await expect(context.keyManager.connect(canOnlyAddController).execute(payload)) + .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') + .withArgs(canOnlyAddController.address, 'EDITPERMISSIONS'); + }); + + it('should fail with NotAuthorised -> when beneficiary had 40 x 0 bytes set initially as allowed calls', async () => { + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + + zero40Bytes.address.substring(2); + + const value = combineAllowedCalls( + [CALLTYPE.CALL, CALLTYPE.CALL], + [ + '0xffffffffffffffffffffffffffffffffffffffff', + '0xffffffffffffffffffffffffffffffffffffffff', + ], + ['0xffffffff', '0xffffffff'], + ['0xcafecafe', '0xca11ca11'], + ); + + const payload = context.universalProfile.interface.encodeFunctionData('setData', [ + key, + value, + ]); + + await expect(context.keyManager.connect(canOnlyAddController).execute(payload)) + .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') + .withArgs(canOnlyAddController.address, 'EDITPERMISSIONS'); + }); + }); - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + newController.address.substr(2); + it('should pass when beneficiary had no values set under AddressPermissions:AllowedCalls:... + setting a valid bytes28[CompactBytesArray]', async () => { + const newController = ethers.Wallet.createRandom(); - const value = combineAllowedCalls( - // allow beneficiary to CALL only function selectors 0xcafecafe and 0xf00df00d - [CALLTYPE.CALL, CALLTYPE.CALL], - [ - '0xffffffffffffffffffffffffffffffffffffffff', - '0xffffffffffffffffffffffffffffffffffffffff', - ], - ['0xffffffff', '0xffffffff'], - ['0xcafecafe', '0xf00df00d'], - ); + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + + newController.address.substr(2); - const payload = context.universalProfile.interface.encodeFunctionData('setData', [ - key, - value, - ]); + const value = combineAllowedCalls( + // allow beneficiary to CALL only function selectors 0xcafecafe and 0xf00df00d + [CALLTYPE.CALL, CALLTYPE.CALL], + [ + '0xffffffffffffffffffffffffffffffffffffffff', + '0xffffffffffffffffffffffffffffffffffffffff', + ], + ['0xffffffff', '0xffffffff'], + ['0xcafecafe', '0xf00df00d'], + ); - await context.keyManager.connect(canOnlyAddController).execute(payload); + const payload = context.universalProfile.interface.encodeFunctionData('setData', [ + key, + value, + ]); - // prettier-ignore - const result = await context.universalProfile.getData(key); - expect(result).to.equal(value); + await context.keyManager.connect(canOnlyAddController).execute(payload); + + // prettier-ignore + const result = await context.universalProfile.getData(key); + expect(result).to.equal(value); + }); }); describe('when setting an invalid bytes28[CompactBytesArray] for a new beneficiary', () => { @@ -807,97 +823,42 @@ export const shouldBehaveLikeSettingAllowedCalls = ( }); describe('when caller has EDITPERMISSIONS', () => { - it('should fail when beneficiary had no values set under AddressPermissions:AllowedCalls:...', async () => { - const newController = ethers.Wallet.createRandom(); - - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + newController.address.substr(2); + describe('when controller to edit Allowed Calls for has some permissions set', () => { + it('should fail when beneficiary had no values set under AddressPermissions:AllowedCalls:...', async () => { + const newController = ethers.Wallet.createRandom(); - const value = combineAllowedCalls( - // allow beneficiary to CALL only function selectors 0xcafecafe and 0xbeefbeef - [CALLTYPE.CALL, CALLTYPE.CALL], - [ - '0xffffffffffffffffffffffffffffffffffffffff', - '0xffffffffffffffffffffffffffffffffffffffff', - ], - ['0xffffffff', '0xffffffff'], - ['0xcafecafe', '0xbeefbeef'], - ); + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + + newController.address.substr(2); - const payload = context.universalProfile.interface.encodeFunctionData('setData', [ - key, - value, - ]); + const value = combineAllowedCalls( + // allow beneficiary to CALL only function selectors 0xcafecafe and 0xbeefbeef + [CALLTYPE.CALL, CALLTYPE.CALL], + [ + '0xffffffffffffffffffffffffffffffffffffffff', + '0xffffffffffffffffffffffffffffffffffffffff', + ], + ['0xffffffff', '0xffffffff'], + ['0xcafecafe', '0xbeefbeef'], + ); - await expect(context.keyManager.connect(canOnlyEditPermissions).execute(payload)) - .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') - .withArgs(canOnlyEditPermissions.address, 'ADDCONTROLLER'); - }); + const payload = context.universalProfile.interface.encodeFunctionData('setData', [ + key, + value, + ]); - it('should pass when trying to edit existing allowed bytes4 selectors under ANY:ANY:', async () => { - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + - beneficiary.address.substring(2); + await expect(context.keyManager.connect(canOnlyEditPermissions).execute(payload)) + .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') + .withArgs(canOnlyEditPermissions.address, 'ADDCONTROLLER'); + }); - const value = combineAllowedCalls( - // allow beneficiary to CALL only function selectors 0xcafecafe and 0xbeefbeef - [CALLTYPE.CALL, CALLTYPE.CALL], - [ - '0xffffffffffffffffffffffffffffffffffffffff', - '0xffffffffffffffffffffffffffffffffffffffff', - ], - ['0xffffffff', '0xffffffff'], - ['0xcafecafe', '0xbeefbeef'], - ); - - const payload = context.universalProfile.interface.encodeFunctionData('setData', [ - key, - value, - ]); - - await context.keyManager.connect(canOnlyEditPermissions).execute(payload); - - // prettier-ignore - const result = await context.universalProfile.getData(key); - expect(result).to.equal(value); - }); - - it('should pass when address had an invalid bytes28[CompactBytesArray] initially', async () => { - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + - invalidBeneficiary.address.substring(2); - - const value = combineAllowedCalls( - // allow beneficiary to CALL only function selectors 0xcafecafe and 0xbeefbeef - [CALLTYPE.CALL, CALLTYPE.CALL], - [ - '0xffffffffffffffffffffffffffffffffffffffff', - '0xffffffffffffffffffffffffffffffffffffffff', - ], - ['0xffffffff', '0xffffffff'], - ['0xcafecafe', '0xbeefbeef'], - ); - - const payload = context.universalProfile.interface.encodeFunctionData('setData', [ - key, - value, - ]); - - await context.keyManager.connect(canOnlyEditPermissions).execute(payload); - - const result = await context.universalProfile.getData(key); - expect(result).to.equal(value); - }); - - // even if the controller had some 00 bytes set as allowed calls, it is not considered as it does not have any allowed calls set - // but rather that its allowed calls are "disabled" - describe('when beneficiary (= controller) had 00 bytes set initially as allowed calls (e.g: allowed calls disabled)', () => { - it('should pass when address had 32 x 0 bytes set initially as allowed calls', async () => { - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + - zero32Bytes.address.substring(2); + it('should pass when trying to edit existing allowed bytes4 selectors under ANY:ANY:', async () => { + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + + beneficiary.address.substring(2); const value = combineAllowedCalls( + // allow beneficiary to CALL only function selectors 0xcafecafe and 0xbeefbeef [CALLTYPE.CALL, CALLTYPE.CALL], [ '0xffffffffffffffffffffffffffffffffffffffff', @@ -914,16 +875,18 @@ export const shouldBehaveLikeSettingAllowedCalls = ( await context.keyManager.connect(canOnlyEditPermissions).execute(payload); + // prettier-ignore const result = await context.universalProfile.getData(key); expect(result).to.equal(value); }); - it('should pass when address had 40 x 0 bytes set initially as allowed functions', async () => { + it('should pass when address had an invalid bytes28[CompactBytesArray] initially', async () => { const key = ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + - zero40Bytes.address.substring(2); + invalidBeneficiary.address.substring(2); const value = combineAllowedCalls( + // allow beneficiary to CALL only function selectors 0xcafecafe and 0xbeefbeef [CALLTYPE.CALL, CALLTYPE.CALL], [ '0xffffffffffffffffffffffffffffffffffffffff', @@ -940,10 +903,64 @@ export const shouldBehaveLikeSettingAllowedCalls = ( await context.keyManager.connect(canOnlyEditPermissions).execute(payload); - // prettier-ignore const result = await context.universalProfile.getData(key); expect(result).to.equal(value); }); + + describe('when beneficiary (= controller) had 00 bytes set initially as allowed calls (e.g: allowed calls disabled)', () => { + it('should pass when address had 32 x 0 bytes set initially as allowed calls', async () => { + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + + zero32Bytes.address.substring(2); + + const value = combineAllowedCalls( + [CALLTYPE.CALL, CALLTYPE.CALL], + [ + '0xffffffffffffffffffffffffffffffffffffffff', + '0xffffffffffffffffffffffffffffffffffffffff', + ], + ['0xffffffff', '0xffffffff'], + ['0xcafecafe', '0xbeefbeef'], + ); + + const payload = context.universalProfile.interface.encodeFunctionData('setData', [ + key, + value, + ]); + + await context.keyManager.connect(canOnlyEditPermissions).execute(payload); + + const result = await context.universalProfile.getData(key); + expect(result).to.equal(value); + }); + + it('should pass when address had 40 x 0 bytes set initially as allowed functions', async () => { + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + + zero40Bytes.address.substring(2); + + const value = combineAllowedCalls( + [CALLTYPE.CALL, CALLTYPE.CALL], + [ + '0xffffffffffffffffffffffffffffffffffffffff', + '0xffffffffffffffffffffffffffffffffffffffff', + ], + ['0xffffffff', '0xffffffff'], + ['0xcafecafe', '0xbeefbeef'], + ); + + const payload = context.universalProfile.interface.encodeFunctionData('setData', [ + key, + value, + ]); + + await context.keyManager.connect(canOnlyEditPermissions).execute(payload); + + // prettier-ignore + const result = await context.universalProfile.getData(key); + expect(result).to.equal(value); + }); + }); }); describe('when changing the list of selectors in allowed calls from existing ANY:ANY: to an invalid value', () => { @@ -1003,14 +1020,16 @@ export const shouldBehaveLikeSettingAllowedCalls = ( zero32Bytes = context.accounts[5]; zero40Bytes = context.accounts[6]; + // prettier-ignore const permissionKeys = [ - ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + - canOnlyAddController.address.substring(2), - ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + - canOnlyEditPermissions.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + canOnlyAddController.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + canOnlyEditPermissions.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + beneficiary.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + invalidBeneficiary.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + zero32Bytes.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + zero40Bytes.address.substring(2), ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + beneficiary.address.substring(2), - ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + - invalidBeneficiary.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + invalidBeneficiary.address.substring(2), ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + zero32Bytes.address.substring(2), ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + zero40Bytes.address.substring(2), ]; @@ -1018,6 +1037,10 @@ export const shouldBehaveLikeSettingAllowedCalls = ( const permissionValues = [ PERMISSIONS.ADDCONTROLLER, PERMISSIONS.EDITPERMISSIONS, + PERMISSIONS.CALL, + PERMISSIONS.CALL, + PERMISSIONS.CALL, + PERMISSIONS.CALL, combineAllowedCalls( // allow beneficiary controller to CALL any functions // on any LSP7 or ERC20 contracts @@ -1038,83 +1061,11 @@ export const shouldBehaveLikeSettingAllowedCalls = ( }); describe('when caller has ADDCONTROLLER', () => { - it('should fail when trying to edit existing allowed standards for an address', async () => { - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + - beneficiary.address.substring(2); - - const value = combineAllowedCalls( - [CALLTYPE.CALL, CALLTYPE.CALL, CALLTYPE.CALL, CALLTYPE.CALL], - [ - '0xffffffffffffffffffffffffffffffffffffffff', - '0xffffffffffffffffffffffffffffffffffffffff', - '0xffffffffffffffffffffffffffffffffffffffff', - '0xffffffffffffffffffffffffffffffffffffffff', - ], - [ - INTERFACE_IDS.LSP7DigitalAsset, - INTERFACE_IDS.ERC20, - // add NFT standards (new LSP8 + old ERC721) - // in the list of allowed calls for the beneficiary controller - // (in addition to token contracts LSP7 + ERC20) - INTERFACE_IDS.LSP8IdentifiableDigitalAsset, - INTERFACE_IDS.ERC721, - ], - ['0xffffffff', '0xffffffff', '0xffffffff', '0xffffffff'], - ); - - const payload = context.universalProfile.interface.encodeFunctionData('setData', [ - key, - value, - ]); - - await expect(context.keyManager.connect(canOnlyAddController).execute(payload)) - .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') - .withArgs(canOnlyAddController.address, 'EDITPERMISSIONS'); - }); - - it('should fail with NotAuthorised -> when beneficiary address had an invalid bytes28[CompactBytesArray] initially', async () => { - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + - invalidBeneficiary.address.substring(2); - - const value = combineAllowedCalls( - [CALLTYPE.CALL, CALLTYPE.CALL, CALLTYPE.CALL, CALLTYPE.CALL], - [ - '0xffffffffffffffffffffffffffffffffffffffff', - '0xffffffffffffffffffffffffffffffffffffffff', - '0xffffffffffffffffffffffffffffffffffffffff', - '0xffffffffffffffffffffffffffffffffffffffff', - ], - [ - INTERFACE_IDS.LSP7DigitalAsset, - INTERFACE_IDS.ERC20, - // add NFT standards (new LSP8 + old ERC721) - // in the list of allowed calls for the beneficiary controller - // (in addition to token standards LSP7 + ERC20) - INTERFACE_IDS.LSP8IdentifiableDigitalAsset, - INTERFACE_IDS.ERC721, - ], - ['0xffffffff', '0xffffffff', '0xffffffff', '0xffffffff'], - ); - - const payload = context.universalProfile.interface.encodeFunctionData('setData', [ - key, - value, - ]); - - await expect(context.keyManager.connect(canOnlyAddController).execute(payload)) - .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') - .withArgs(canOnlyAddController.address, 'EDITPERMISSIONS'); - }); - - // even if the controller had some 00 bytes set as allowed calls, it is not considered as it does not have any allowed calls set - // but rather that its allowed calls are "disabled" - describe('when beneficiary (= controller) had 00 bytes set initially as allowed calls (e.g: allowed calls disabled)', () => { - it('should fail with NotAuthorised -> when beneficiary had 32 x 0 bytes set initially as allowed calls', async () => { + describe('when controller to edit Allowed Calls for has some permissions', () => { + it('should fail when trying to edit existing allowed standards for an address', async () => { const key = ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + - zero32Bytes.address.substring(2); + beneficiary.address.substring(2); const value = combineAllowedCalls( [CALLTYPE.CALL, CALLTYPE.CALL, CALLTYPE.CALL, CALLTYPE.CALL], @@ -1127,6 +1078,9 @@ export const shouldBehaveLikeSettingAllowedCalls = ( [ INTERFACE_IDS.LSP7DigitalAsset, INTERFACE_IDS.ERC20, + // add NFT standards (new LSP8 + old ERC721) + // in the list of allowed calls for the beneficiary controller + // (in addition to token contracts LSP7 + ERC20) INTERFACE_IDS.LSP8IdentifiableDigitalAsset, INTERFACE_IDS.ERC721, ], @@ -1143,10 +1097,10 @@ export const shouldBehaveLikeSettingAllowedCalls = ( .withArgs(canOnlyAddController.address, 'EDITPERMISSIONS'); }); - it('should fail with NotAuthorised -> when beneficiary had 40 x 0 bytes set initially as allowed calls', async () => { + it('should fail with NotAuthorised -> when beneficiary address had an invalid bytes28[CompactBytesArray] initially', async () => { const key = ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + - zero40Bytes.address.substring(2); + invalidBeneficiary.address.substring(2); const value = combineAllowedCalls( [CALLTYPE.CALL, CALLTYPE.CALL, CALLTYPE.CALL, CALLTYPE.CALL], @@ -1159,6 +1113,9 @@ export const shouldBehaveLikeSettingAllowedCalls = ( [ INTERFACE_IDS.LSP7DigitalAsset, INTERFACE_IDS.ERC20, + // add NFT standards (new LSP8 + old ERC721) + // in the list of allowed calls for the beneficiary controller + // (in addition to token standards LSP7 + ERC20) INTERFACE_IDS.LSP8IdentifiableDigitalAsset, INTERFACE_IDS.ERC721, ], @@ -1174,44 +1131,113 @@ export const shouldBehaveLikeSettingAllowedCalls = ( .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') .withArgs(canOnlyAddController.address, 'EDITPERMISSIONS'); }); - }); - it('should pass when beneficiary had no values set under AddressPermissions:AllowedCalls:... + setting a valid bytes28[CompactBytesArray]', async () => { - const newController = ethers.Wallet.createRandom(); + // even if the controller had some 00 bytes set as allowed calls, it is not considered as it does not have any allowed calls set + // but rather that its allowed calls are "disabled" + describe('when beneficiary (= controller) had 00 bytes set initially as allowed calls (e.g: allowed calls disabled)', () => { + it('should fail with NotAuthorised -> when beneficiary had 32 x 0 bytes set initially as allowed calls', async () => { + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + + zero32Bytes.address.substring(2); + + const value = combineAllowedCalls( + [CALLTYPE.CALL, CALLTYPE.CALL, CALLTYPE.CALL, CALLTYPE.CALL], + [ + '0xffffffffffffffffffffffffffffffffffffffff', + '0xffffffffffffffffffffffffffffffffffffffff', + '0xffffffffffffffffffffffffffffffffffffffff', + '0xffffffffffffffffffffffffffffffffffffffff', + ], + [ + INTERFACE_IDS.LSP7DigitalAsset, + INTERFACE_IDS.ERC20, + INTERFACE_IDS.LSP8IdentifiableDigitalAsset, + INTERFACE_IDS.ERC721, + ], + ['0xffffffff', '0xffffffff', '0xffffffff', '0xffffffff'], + ); + + const payload = context.universalProfile.interface.encodeFunctionData('setData', [ + key, + value, + ]); + + await expect(context.keyManager.connect(canOnlyAddController).execute(payload)) + .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') + .withArgs(canOnlyAddController.address, 'EDITPERMISSIONS'); + }); + + it('should fail with NotAuthorised -> when beneficiary had 40 x 0 bytes set initially as allowed calls', async () => { + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + + zero40Bytes.address.substring(2); + + const value = combineAllowedCalls( + [CALLTYPE.CALL, CALLTYPE.CALL, CALLTYPE.CALL, CALLTYPE.CALL], + [ + '0xffffffffffffffffffffffffffffffffffffffff', + '0xffffffffffffffffffffffffffffffffffffffff', + '0xffffffffffffffffffffffffffffffffffffffff', + '0xffffffffffffffffffffffffffffffffffffffff', + ], + [ + INTERFACE_IDS.LSP7DigitalAsset, + INTERFACE_IDS.ERC20, + INTERFACE_IDS.LSP8IdentifiableDigitalAsset, + INTERFACE_IDS.ERC721, + ], + ['0xffffffff', '0xffffffff', '0xffffffff', '0xffffffff'], + ); + + const payload = context.universalProfile.interface.encodeFunctionData('setData', [ + key, + value, + ]); + + await expect(context.keyManager.connect(canOnlyAddController).execute(payload)) + .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') + .withArgs(canOnlyAddController.address, 'EDITPERMISSIONS'); + }); + }); - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + newController.address.substr(2); + it('should pass when beneficiary had no values set under AddressPermissions:AllowedCalls:... + setting a valid bytes28[CompactBytesArray]', async () => { + const newController = ethers.Wallet.createRandom(); - const value = combineAllowedCalls( - [CALLTYPE.CALL, CALLTYPE.CALL, CALLTYPE.CALL, CALLTYPE.CALL], - [ - '0xffffffffffffffffffffffffffffffffffffffff', - '0xffffffffffffffffffffffffffffffffffffffff', - '0xffffffffffffffffffffffffffffffffffffffff', - '0xffffffffffffffffffffffffffffffffffffffff', - ], - [ - INTERFACE_IDS.LSP7DigitalAsset, - INTERFACE_IDS.ERC20, - // add NFT standards (new LSP8 + old ERC721) - // in the list of allowed calls for the beneficiary controller - // (in addition to token standards LSP7 + ERC20) - INTERFACE_IDS.LSP8IdentifiableDigitalAsset, - INTERFACE_IDS.ERC721, - ], - ['0xffffffff', '0xffffffff', '0xffffffff', '0xffffffff'], - ); + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + + newController.address.substr(2); - const payload = context.universalProfile.interface.encodeFunctionData('setData', [ - key, - value, - ]); + const value = combineAllowedCalls( + [CALLTYPE.CALL, CALLTYPE.CALL, CALLTYPE.CALL, CALLTYPE.CALL], + [ + '0xffffffffffffffffffffffffffffffffffffffff', + '0xffffffffffffffffffffffffffffffffffffffff', + '0xffffffffffffffffffffffffffffffffffffffff', + '0xffffffffffffffffffffffffffffffffffffffff', + ], + [ + INTERFACE_IDS.LSP7DigitalAsset, + INTERFACE_IDS.ERC20, + // add NFT standards (new LSP8 + old ERC721) + // in the list of allowed calls for the beneficiary controller + // (in addition to token standards LSP7 + ERC20) + INTERFACE_IDS.LSP8IdentifiableDigitalAsset, + INTERFACE_IDS.ERC721, + ], + ['0xffffffff', '0xffffffff', '0xffffffff', '0xffffffff'], + ); - await context.keyManager.connect(canOnlyAddController).execute(payload); + const payload = context.universalProfile.interface.encodeFunctionData('setData', [ + key, + value, + ]); - // prettier-ignore - const result = await context.universalProfile.getData(key); - expect(result).to.equal(value); + await context.keyManager.connect(canOnlyAddController).execute(payload); + + // prettier-ignore + const result = await context.universalProfile.getData(key); + expect(result).to.equal(value); + }); }); describe('when setting an invalid bytes28[CompactBytesArray] of allowed calls for a new beneficiary', () => { @@ -1256,114 +1282,60 @@ export const shouldBehaveLikeSettingAllowedCalls = ( }); describe('when caller has EDITPERMISSIONS', () => { - it('should fail when beneficiary had no values set under AddressPermissions:AllowedCalls:...', async () => { - const newController = ethers.Wallet.createRandom(); - - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + newController.address.substr(2); - - const value = combineAllowedCalls( - [CALLTYPE.CALL, CALLTYPE.CALL], - [ - '0xffffffffffffffffffffffffffffffffffffffff', - '0xffffffffffffffffffffffffffffffffffffffff', - ], - // try to add in the list of allowed calls for the beneficiary controller - // the rights to CALL any LSP7 or ERC20 token contract - // (NB: just the AllowedCalls, not the permission CALL) - [INTERFACE_IDS.LSP7DigitalAsset, INTERFACE_IDS.ERC20], - ['0xffffffff', '0xffffffff'], - ); - - const payload = context.universalProfile.interface.encodeFunctionData('setData', [ - key, - value, - ]); - - await expect(context.keyManager.connect(canOnlyEditPermissions).execute(payload)) - .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') - .withArgs(canOnlyEditPermissions.address, 'ADDCONTROLLER'); - }); - - it('should pass when trying to edit existing allowed standards for an address', async () => { - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + - beneficiary.address.substring(2); - - const value = combineAllowedCalls( - [CALLTYPE.CALL, CALLTYPE.CALL, CALLTYPE.CALL, CALLTYPE.CALL], - [ - '0xffffffffffffffffffffffffffffffffffffffff', - '0xffffffffffffffffffffffffffffffffffffffff', - '0xffffffffffffffffffffffffffffffffffffffff', - '0xffffffffffffffffffffffffffffffffffffffff', - ], - [ - INTERFACE_IDS.LSP7DigitalAsset, - INTERFACE_IDS.ERC20, - // add NFT standards (new LSP8 + old ERC721) - // in the list of allowed calls for the beneficiary controller - // (in addition to token standards LSP7 + ERC20) - INTERFACE_IDS.LSP8IdentifiableDigitalAsset, - INTERFACE_IDS.ERC721, - ], - ['0xffffffff', '0xffffffff', '0xffffffff', '0xffffffff'], - ); - - const payload = context.universalProfile.interface.encodeFunctionData('setData', [ - key, - value, - ]); - - await context.keyManager.connect(canOnlyEditPermissions).execute(payload); - - // prettier-ignore - const result = await context.universalProfile.getData(key); - expect(result).to.equal(value); - }); - - it('should pass when address had an invalid bytes28[CompactBytesArray] initially', async () => { - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + - invalidBeneficiary.address.substring(2); + describe('when controller to edit Allowed Calls for has some permissions', () => { + it('should fail when beneficiary had no values set under AddressPermissions:AllowedCalls:...', async () => { + const newController = ethers.Wallet.createRandom(); - const value = combineAllowedCalls( - [CALLTYPE.CALL, CALLTYPE.CALL], - [ - '0xffffffffffffffffffffffffffffffffffffffff', - '0xffffffffffffffffffffffffffffffffffffffff', - ], - [INTERFACE_IDS.LSP7DigitalAsset, INTERFACE_IDS.ERC20], - ['0xffffffff', '0xffffffff'], - ); + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + + newController.address.substr(2); - const payload = context.universalProfile.interface.encodeFunctionData('setData', [ - key, - value, - ]); + const value = combineAllowedCalls( + [CALLTYPE.CALL, CALLTYPE.CALL], + [ + '0xffffffffffffffffffffffffffffffffffffffff', + '0xffffffffffffffffffffffffffffffffffffffff', + ], + // try to add in the list of allowed calls for the beneficiary controller + // the rights to CALL any LSP7 or ERC20 token contract + // (NB: just the AllowedCalls, not the permission CALL) + [INTERFACE_IDS.LSP7DigitalAsset, INTERFACE_IDS.ERC20], + ['0xffffffff', '0xffffffff'], + ); - await context.keyManager.connect(canOnlyEditPermissions).execute(payload); + const payload = context.universalProfile.interface.encodeFunctionData('setData', [ + key, + value, + ]); - const result = await context.universalProfile.getData(key); - expect(result).to.equal(value); - }); + await expect(context.keyManager.connect(canOnlyEditPermissions).execute(payload)) + .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') + .withArgs(canOnlyEditPermissions.address, 'ADDCONTROLLER'); + }); - // even if the controller had some 00 bytes set as allowed calls, it is not considered as it does not have any allowed calls set - // but rather that its allowed calls are "disabled" - describe('when beneficiary (= controller) had 00 bytes set initially as allowed calls (e.g: allowed calls disabled)', () => { - it('should pass when address had 32 x 0 bytes set initially as allowed calls', async () => { + it('should pass when trying to edit existing allowed standards for an address', async () => { const key = ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + - zero32Bytes.address.substring(2); + beneficiary.address.substring(2); const value = combineAllowedCalls( - [CALLTYPE.CALL, CALLTYPE.CALL], + [CALLTYPE.CALL, CALLTYPE.CALL, CALLTYPE.CALL, CALLTYPE.CALL], [ '0xffffffffffffffffffffffffffffffffffffffff', '0xffffffffffffffffffffffffffffffffffffffff', + '0xffffffffffffffffffffffffffffffffffffffff', + '0xffffffffffffffffffffffffffffffffffffffff', ], - [INTERFACE_IDS.LSP7DigitalAsset, INTERFACE_IDS.ERC20], - ['0xffffffff', '0xffffffff'], + [ + INTERFACE_IDS.LSP7DigitalAsset, + INTERFACE_IDS.ERC20, + // add NFT standards (new LSP8 + old ERC721) + // in the list of allowed calls for the beneficiary controller + // (in addition to token standards LSP7 + ERC20) + INTERFACE_IDS.LSP8IdentifiableDigitalAsset, + INTERFACE_IDS.ERC721, + ], + ['0xffffffff', '0xffffffff', '0xffffffff', '0xffffffff'], ); const payload = context.universalProfile.interface.encodeFunctionData('setData', [ @@ -1373,14 +1345,15 @@ export const shouldBehaveLikeSettingAllowedCalls = ( await context.keyManager.connect(canOnlyEditPermissions).execute(payload); + // prettier-ignore const result = await context.universalProfile.getData(key); expect(result).to.equal(value); }); - it('should pass when address had 40 x 0 bytes set initially as allowed calls', async () => { + it('should pass when address had an invalid bytes28[CompactBytesArray] initially', async () => { const key = ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + - zero40Bytes.address.substring(2); + invalidBeneficiary.address.substring(2); const value = combineAllowedCalls( [CALLTYPE.CALL, CALLTYPE.CALL], @@ -1399,10 +1372,66 @@ export const shouldBehaveLikeSettingAllowedCalls = ( await context.keyManager.connect(canOnlyEditPermissions).execute(payload); - // prettier-ignore const result = await context.universalProfile.getData(key); expect(result).to.equal(value); }); + + // even if the controller had some 00 bytes set as allowed calls, it is not considered as it does not have any allowed calls set + // but rather that its allowed calls are "disabled" + describe('when beneficiary (= controller) had 00 bytes set initially as allowed calls (e.g: allowed calls disabled)', () => { + it('should pass when address had 32 x 0 bytes set initially as allowed calls', async () => { + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + + zero32Bytes.address.substring(2); + + const value = combineAllowedCalls( + [CALLTYPE.CALL, CALLTYPE.CALL], + [ + '0xffffffffffffffffffffffffffffffffffffffff', + '0xffffffffffffffffffffffffffffffffffffffff', + ], + [INTERFACE_IDS.LSP7DigitalAsset, INTERFACE_IDS.ERC20], + ['0xffffffff', '0xffffffff'], + ); + + const payload = context.universalProfile.interface.encodeFunctionData('setData', [ + key, + value, + ]); + + await context.keyManager.connect(canOnlyEditPermissions).execute(payload); + + const result = await context.universalProfile.getData(key); + expect(result).to.equal(value); + }); + + it('should pass when address had 40 x 0 bytes set initially as allowed calls', async () => { + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedCalls'] + + zero40Bytes.address.substring(2); + + const value = combineAllowedCalls( + [CALLTYPE.CALL, CALLTYPE.CALL], + [ + '0xffffffffffffffffffffffffffffffffffffffff', + '0xffffffffffffffffffffffffffffffffffffffff', + ], + [INTERFACE_IDS.LSP7DigitalAsset, INTERFACE_IDS.ERC20], + ['0xffffffff', '0xffffffff'], + ); + + const payload = context.universalProfile.interface.encodeFunctionData('setData', [ + key, + value, + ]); + + await context.keyManager.connect(canOnlyEditPermissions).execute(payload); + + // prettier-ignore + const result = await context.universalProfile.getData(key); + expect(result).to.equal(value); + }); + }); }); describe('when changing the list of interface IDs in allowed calls :ANY:ANY to an invalid value', () => { diff --git a/tests/LSP6KeyManager/SetPermissions/SetAllowedERC725YDataKeys.test.ts b/tests/LSP6KeyManager/SetPermissions/SetAllowedERC725YDataKeys.test.ts index 848987cb8..f39dcccad 100644 --- a/tests/LSP6KeyManager/SetPermissions/SetAllowedERC725YDataKeys.test.ts +++ b/tests/LSP6KeyManager/SetPermissions/SetAllowedERC725YDataKeys.test.ts @@ -18,7 +18,8 @@ export const shouldBehaveLikeSetAllowedERC725YDataKeys = ( describe('setting Allowed ERC725YDataKeys', () => { let canOnlyAddController: SignerWithAddress, canOnlyEditPermissions: SignerWithAddress; - let beneficiary: SignerWithAddress, + let beneficiaryWithPermissions: SignerWithAddress, + beneficiaryNoPermissions: SignerWithAddress, invalidBeneficiary: SignerWithAddress, zero32Bytes: SignerWithAddress, zero40Bytes: SignerWithAddress; @@ -29,34 +30,43 @@ export const shouldBehaveLikeSetAllowedERC725YDataKeys = ( canOnlyAddController = context.accounts[1]; canOnlyEditPermissions = context.accounts[2]; - beneficiary = context.accounts[3]; - invalidBeneficiary = context.accounts[4]; - zero32Bytes = context.accounts[5]; - zero40Bytes = context.accounts[6]; + beneficiaryWithPermissions = context.accounts[3]; + beneficiaryNoPermissions = context.accounts[4]; + invalidBeneficiary = context.accounts[5]; + zero32Bytes = context.accounts[6]; + zero40Bytes = context.accounts[7]; + // prettier-ignore const permissionKeys = [ - ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + - canOnlyAddController.address.substring(2), - ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + - canOnlyEditPermissions.address.substring(2), - ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + - beneficiary.address.substring(2), - ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + - invalidBeneficiary.address.substring(2), - ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + - zero32Bytes.address.substring(2), - ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + - zero40Bytes.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + canOnlyAddController.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + canOnlyEditPermissions.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + beneficiaryWithPermissions.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + invalidBeneficiary.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + zero32Bytes.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:Permissions'] + zero40Bytes.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + beneficiaryWithPermissions.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + beneficiaryNoPermissions.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + invalidBeneficiary.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + zero32Bytes.address.substring(2), + ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + zero40Bytes.address.substring(2), ]; const permissionValues = [ PERMISSIONS.ADDCONTROLLER, PERMISSIONS.EDITPERMISSIONS, + PERMISSIONS.SETDATA, + PERMISSIONS.SETDATA, + PERMISSIONS.SETDATA, + PERMISSIONS.SETDATA, encodeCompactBytesArray([ ERC725YDataKeys.LSP3['LSP3Profile'], // prettier-ignore ethers.utils.keccak256(ethers.utils.toUtf8Bytes("Some Custom Profile Data Key")), ]), + encodeCompactBytesArray([ + ethers.utils.hexlify(ethers.utils.randomBytes(32)), + ethers.utils.hexlify(ethers.utils.randomBytes(32)), + ]), '0x11223344', '0x0000000000000000000000000000000000000000000000000000000000000000', '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000', @@ -66,98 +76,149 @@ export const shouldBehaveLikeSetAllowedERC725YDataKeys = ( }); describe('when caller has ADDCONTROLLER', () => { - describe('when beneficiary had some ERC725Y data keys set under AddressPermissions:AllowedERC725YDataKeys:...', () => { - it('should fail when adding an extra allowed ERC725Y data key', async () => { - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + - beneficiary.address.substring(2); - - const value = encodeCompactBytesArray([ - ERC725YDataKeys.LSP3['LSP3Profile'], - // prettier-ignore - ethers.utils.keccak256(ethers.utils.toUtf8Bytes("Some Custom Profile Data Key")), - // prettier-ignore - ethers.utils.keccak256(ethers.utils.toUtf8Bytes("Another Custom Data Key")), - ]); - - const payload = context.universalProfile.interface.encodeFunctionData('setData', [ - key, - value, - ]); - - await expect(context.keyManager.connect(canOnlyAddController).execute(payload)) - .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') - .withArgs(canOnlyAddController.address, 'EDITPERMISSIONS'); - }); - - it('should fail when removing an allowed ERC725Y data key', async () => { - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + - beneficiary.address.substring(2); - - const value = encodeCompactBytesArray([ERC725YDataKeys.LSP3['LSP3Profile']]); - - const payload = context.universalProfile.interface.encodeFunctionData('setData', [ - key, - value, - ]); - - await expect(context.keyManager.connect(canOnlyAddController).execute(payload)) - .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') - .withArgs(canOnlyAddController.address, 'EDITPERMISSIONS'); + describe('when controller / beneficiary had some permissions set', () => { + describe('when beneficiary had some ERC725Y data keys set under AddressPermissions:AllowedERC725YDataKeys:...', () => { + it('should fail when adding an extra allowed ERC725Y data key', async () => { + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + + beneficiaryWithPermissions.address.substring(2); + + const value = encodeCompactBytesArray([ + ERC725YDataKeys.LSP3['LSP3Profile'], + // prettier-ignore + ethers.utils.keccak256(ethers.utils.toUtf8Bytes("Some Custom Profile Data Key")), + // prettier-ignore + ethers.utils.keccak256(ethers.utils.toUtf8Bytes("Another Custom Data Key")), + ]); + + const payload = context.universalProfile.interface.encodeFunctionData('setData', [ + key, + value, + ]); + + await expect(context.keyManager.connect(canOnlyAddController).execute(payload)) + .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') + .withArgs(canOnlyAddController.address, 'EDITPERMISSIONS'); + }); + + it('should fail when removing an allowed ERC725Y data key', async () => { + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + + beneficiaryWithPermissions.address.substring(2); + + const value = encodeCompactBytesArray([ERC725YDataKeys.LSP3['LSP3Profile']]); + + const payload = context.universalProfile.interface.encodeFunctionData('setData', [ + key, + value, + ]); + + await expect(context.keyManager.connect(canOnlyAddController).execute(payload)) + .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') + .withArgs(canOnlyAddController.address, 'EDITPERMISSIONS'); + }); + + it('should fail when trying to clear the CompactedBytesArray completely', async () => { + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + + beneficiaryWithPermissions.address.substring(2); + + const value = '0x'; + + const payload = context.universalProfile.interface.encodeFunctionData('setData', [ + key, + value, + ]); + + await expect(context.keyManager.connect(canOnlyAddController).execute(payload)) + .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') + .withArgs(canOnlyAddController.address, 'EDITPERMISSIONS'); + }); + + it('should fail when setting an invalid CompactedBytesArray', async () => { + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + + beneficiaryWithPermissions.address.substring(2); + + const value = '0xbadbadbadbad'; + + const payload = context.universalProfile.interface.encodeFunctionData('setData', [ + key, + value, + ]); + + await expect(context.keyManager.connect(canOnlyAddController).execute(payload)) + .to.be.revertedWithCustomError( + context.keyManager, + 'InvalidEncodedAllowedERC725YDataKeys', + ) + .withArgs(value, "couldn't VALIDATE the data value"); + }); }); - it('should fail when trying to clear the CompactedBytesArray completely', async () => { - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + - beneficiary.address.substring(2); - - const value = '0x'; - - const payload = context.universalProfile.interface.encodeFunctionData('setData', [ - key, - value, - ]); + describe('when beneficiary had no ERC725Y data keys set under AddressPermissions:AllowedERC725YDataKeys:...', () => { + it('should pass when setting a valid CompactedBytesArray', async () => { + const newController = ethers.Wallet.createRandom(); - await expect(context.keyManager.connect(canOnlyAddController).execute(payload)) - .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') - .withArgs(canOnlyAddController.address, 'EDITPERMISSIONS'); - }); + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + + newController.address.substr(2); - it('should fail when setting an invalid CompactedBytesArray', async () => { - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + - beneficiary.address.substring(2); + const value = encodeCompactBytesArray([ + // prettier-ignore + ethers.utils.keccak256(ethers.utils.toUtf8Bytes("My Custom Profile Key 1")), + // prettier-ignore + ethers.utils.keccak256(ethers.utils.toUtf8Bytes("My Custom Profile Key 2")), + ]); - const value = '0xbadbadbadbad'; + const payload = context.universalProfile.interface.encodeFunctionData('setData', [ + key, + value, + ]); - const payload = context.universalProfile.interface.encodeFunctionData('setData', [ - key, - value, - ]); + await context.keyManager.connect(canOnlyAddController).execute(payload); - await expect(context.keyManager.connect(canOnlyAddController).execute(payload)) - .to.be.revertedWithCustomError( - context.keyManager, - 'InvalidEncodedAllowedERC725YDataKeys', - ) - .withArgs(value, "couldn't VALIDATE the data value"); + // prettier-ignore + const result = await context.universalProfile.getData(key); + expect(result).to.equal(value); + }); + + it('should fail when setting an invalid CompactedBytesArray (random bytes)', async () => { + const newController = ethers.Wallet.createRandom(); + + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + + newController.address.substr(2); + + const value = '0xbadbadbadbad'; + + const payload = context.universalProfile.interface.encodeFunctionData('setData', [ + key, + value, + ]); + + await expect(context.keyManager.connect(canOnlyAddController).execute(payload)) + .to.be.revertedWithCustomError( + context.keyManager, + 'InvalidEncodedAllowedERC725YDataKeys', + ) + .withArgs(value, "couldn't VALIDATE the data value"); + }); }); }); - describe('when beneficiary had no ERC725Y data keys set under AddressPermissions:AllowedERC725YDataKeys:...', () => { - it('should pass when setting a valid CompactedBytesArray', async () => { - const newController = ethers.Wallet.createRandom(); - + describe('when controller / beneficiary had no permissions set', () => { + it('should pass and edit the list of Allowed ERC725Y Data Keys', async () => { const key = ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + - newController.address.substr(2); + beneficiaryNoPermissions.address.substring(2); const value = encodeCompactBytesArray([ + ERC725YDataKeys.LSP3['LSP3Profile'], // prettier-ignore - ethers.utils.keccak256(ethers.utils.toUtf8Bytes("My Custom Profile Key 1")), + ethers.utils.keccak256(ethers.utils.toUtf8Bytes("Some Custom Profile Data Key")), // prettier-ignore - ethers.utils.keccak256(ethers.utils.toUtf8Bytes("My Custom Profile Key 2")), + ethers.utils.keccak256(ethers.utils.toUtf8Bytes("Another Custom Data Key")), ]); const payload = context.universalProfile.interface.encodeFunctionData('setData', [ @@ -167,132 +228,157 @@ export const shouldBehaveLikeSetAllowedERC725YDataKeys = ( await context.keyManager.connect(canOnlyAddController).execute(payload); - // prettier-ignore - const result = await context.universalProfile.getData(key); - expect(result).to.equal(value); - }); - - it('should fail when setting an invalid CompactedBytesArray (random bytes)', async () => { - const newController = ethers.Wallet.createRandom(); - - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + - newController.address.substr(2); - - const value = '0xbadbadbadbad'; - - const payload = context.universalProfile.interface.encodeFunctionData('setData', [ - key, - value, - ]); - - await expect(context.keyManager.connect(canOnlyAddController).execute(payload)) - .to.be.revertedWithCustomError( - context.keyManager, - 'InvalidEncodedAllowedERC725YDataKeys', - ) - .withArgs(value, "couldn't VALIDATE the data value"); + expect(await context.universalProfile.getData(key)).to.equal(value); }); }); }); describe('when caller has EDITPERMISSIONS', () => { - describe('when beneficiary had some ERC725Y data keys set under AddressPermissions:AllowedERC725YDataKeys:...', () => { - it('should pass when adding an extra allowed ERC725Y data key', async () => { - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + - beneficiary.address.substring(2); + describe('when controller / beneficiary had some permissions set', () => { + describe('when beneficiary had some ERC725Y data keys set under AddressPermissions:AllowedERC725YDataKeys:...', () => { + it('should pass when adding an extra allowed ERC725Y data key', async () => { + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + + beneficiaryWithPermissions.address.substring(2); + + const value = encodeCompactBytesArray([ + ERC725YDataKeys.LSP3['LSP3Profile'], + // prettier-ignore + ethers.utils.keccak256(ethers.utils.toUtf8Bytes("Some Custom Profile Data Key")), + // prettier-ignore + ethers.utils.keccak256(ethers.utils.toUtf8Bytes("Another Custom Data Key")), + ]); + + const payload = context.universalProfile.interface.encodeFunctionData('setData', [ + key, + value, + ]); + + await context.keyManager.connect(canOnlyEditPermissions).execute(payload); - const value = encodeCompactBytesArray([ - ERC725YDataKeys.LSP3['LSP3Profile'], - // prettier-ignore - ethers.utils.keccak256(ethers.utils.toUtf8Bytes("Some Custom Profile Data Key")), // prettier-ignore - ethers.utils.keccak256(ethers.utils.toUtf8Bytes("Another Custom Data Key")), - ]); - - const payload = context.universalProfile.interface.encodeFunctionData('setData', [ - key, - value, - ]); - - await context.keyManager.connect(canOnlyEditPermissions).execute(payload); - - // prettier-ignore - const result = await context.universalProfile.getData(key); - expect(result).to.equal(value); - }); + const result = await context.universalProfile.getData(key); + expect(result).to.equal(value); + }); - it('should pass when removing an allowed ERC725Y data key', async () => { - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + - beneficiary.address.substring(2); + it('should pass when removing an allowed ERC725Y data key', async () => { + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + + beneficiaryWithPermissions.address.substring(2); - const value = encodeCompactBytesArray([ERC725YDataKeys.LSP3['LSP3Profile']]); + const value = encodeCompactBytesArray([ERC725YDataKeys.LSP3['LSP3Profile']]); - const payload = context.universalProfile.interface.encodeFunctionData('setData', [ - key, - value, - ]); + const payload = context.universalProfile.interface.encodeFunctionData('setData', [ + key, + value, + ]); - await context.keyManager.connect(canOnlyEditPermissions).execute(payload); + await context.keyManager.connect(canOnlyEditPermissions).execute(payload); - // prettier-ignore - const result = await context.universalProfile.getData(key); - expect(result).to.equal(value); - }); + // prettier-ignore + const result = await context.universalProfile.getData(key); + expect(result).to.equal(value); + }); - it('should pass when trying to clear the CompactedBytesArray completely', async () => { - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + - beneficiary.address.substring(2); + it('should pass when trying to clear the CompactedBytesArray completely', async () => { + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + + beneficiaryWithPermissions.address.substring(2); - const value = '0x'; + const value = '0x'; - const payload = context.universalProfile.interface.encodeFunctionData('setData', [ - key, - value, - ]); + const payload = context.universalProfile.interface.encodeFunctionData('setData', [ + key, + value, + ]); - await context.keyManager.connect(canOnlyEditPermissions).execute(payload); + await context.keyManager.connect(canOnlyEditPermissions).execute(payload); - // prettier-ignore - const result = await context.universalProfile.getData(key); - expect(result).to.equal(value); + // prettier-ignore + const result = await context.universalProfile.getData(key); + expect(result).to.equal(value); + }); + + it('should fail when setting an invalid CompactedBytesArray', async () => { + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + + beneficiaryWithPermissions.address.substring(2); + + const value = '0xbadbadbadbad'; + + const payload = context.universalProfile.interface.encodeFunctionData('setData', [ + key, + value, + ]); + + await expect(context.keyManager.connect(canOnlyEditPermissions).execute(payload)) + .to.be.revertedWithCustomError( + context.keyManager, + 'InvalidEncodedAllowedERC725YDataKeys', + ) + .withArgs(value, "couldn't VALIDATE the data value"); + }); }); - it('should fail when setting an invalid CompactedBytesArray', async () => { - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + - beneficiary.address.substring(2); - - const value = '0xbadbadbadbad'; - - const payload = context.universalProfile.interface.encodeFunctionData('setData', [ - key, - value, - ]); - - await expect(context.keyManager.connect(canOnlyEditPermissions).execute(payload)) - .to.be.revertedWithCustomError( - context.keyManager, - 'InvalidEncodedAllowedERC725YDataKeys', - ) - .withArgs(value, "couldn't VALIDATE the data value"); + describe('when beneficiary had no ERC725Y data keys set under AddressPermissions:AllowedERC725YDataKeys:...', () => { + it('should fail and not authorize to add a list of allowed ERC725Y data keys (not authorised)', async () => { + const newController = ethers.Wallet.createRandom(); + + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + + newController.address.substr(2); + + const value = encodeCompactBytesArray([ + ethers.utils.keccak256(ethers.utils.toUtf8Bytes('My Custom Key 1')), + ethers.utils.keccak256(ethers.utils.toUtf8Bytes('My Custom Key 2')), + ]); + + const payload = context.universalProfile.interface.encodeFunctionData('setData', [ + key, + value, + ]); + + await expect(context.keyManager.connect(canOnlyEditPermissions).execute(payload)) + .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') + .withArgs(canOnlyEditPermissions.address, 'ADDCONTROLLER'); + }); + + it('should fail when setting an invalid CompactedBytesArray', async () => { + const newController = ethers.Wallet.createRandom(); + + const key = + ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + + newController.address.substr(2); + + const value = '0xbadbadbadbad'; + + const payload = context.universalProfile.interface.encodeFunctionData('setData', [ + key, + value, + ]); + + await expect(context.keyManager.connect(canOnlyEditPermissions).execute(payload)) + .to.be.revertedWithCustomError( + context.keyManager, + 'InvalidEncodedAllowedERC725YDataKeys', + ) + .withArgs(value, "couldn't VALIDATE the data value"); + }); }); }); - describe('when beneficiary had no ERC725Y data keys set under AddressPermissions:AllowedERC725YDataKeys:...', () => { - it('should fail and not authorize to add a list of allowed ERC725Y data keys (not authorised)', async () => { - const newController = ethers.Wallet.createRandom(); - + describe('when controller / beneficiary had no permissions set', () => { + it("should revert with error `NotAuthorised('ADDCONTROLLER')` when trying to add a list of allowed ERC725Y data keys", async () => { const key = ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + - newController.address.substr(2); + beneficiaryNoPermissions.address.substring(2); const value = encodeCompactBytesArray([ - ethers.utils.keccak256(ethers.utils.toUtf8Bytes('My Custom Key 1')), - ethers.utils.keccak256(ethers.utils.toUtf8Bytes('My Custom Key 2')), + ERC725YDataKeys.LSP3['LSP3Profile'], + // prettier-ignore + ethers.utils.keccak256(ethers.utils.toUtf8Bytes("Some Custom Profile Data Key")), + // prettier-ignore + ethers.utils.keccak256(ethers.utils.toUtf8Bytes("Another Custom Data Key")), ]); const payload = context.universalProfile.interface.encodeFunctionData('setData', [ @@ -304,28 +390,6 @@ export const shouldBehaveLikeSetAllowedERC725YDataKeys = ( .to.be.revertedWithCustomError(context.keyManager, 'NotAuthorised') .withArgs(canOnlyEditPermissions.address, 'ADDCONTROLLER'); }); - - it('should fail when setting an invalid CompactedBytesArray', async () => { - const newController = ethers.Wallet.createRandom(); - - const key = - ERC725YDataKeys.LSP6['AddressPermissions:AllowedERC725YDataKeys'] + - newController.address.substr(2); - - const value = '0xbadbadbadbad'; - - const payload = context.universalProfile.interface.encodeFunctionData('setData', [ - key, - value, - ]); - - await expect(context.keyManager.connect(canOnlyEditPermissions).execute(payload)) - .to.be.revertedWithCustomError( - context.keyManager, - 'InvalidEncodedAllowedERC725YDataKeys', - ) - .withArgs(value, "couldn't VALIDATE the data value"); - }); }); }); });