From f9dc8577f93db89ff68abcf86f92e7c7e753f2d5 Mon Sep 17 00:00:00 2001 From: Daniel Kronovet Date: Thu, 25 Jul 2024 12:12:54 -0400 Subject: [PATCH] Test deprecation of 'old' local skills --- contracts/colony/Colony.sol | 4 ++ contracts/colony/IColony.sol | 5 ++ docs/interfaces/icolony.md | 17 +++++++ test/contracts-network/colony-expenditure.js | 52 +++++++++++++++++++- 4 files changed, 77 insertions(+), 1 deletion(-) diff --git a/contracts/colony/Colony.sol b/contracts/colony/Colony.sol index dd211a5356..11d1108141 100755 --- a/contracts/colony/Colony.sol +++ b/contracts/colony/Colony.sol @@ -259,6 +259,10 @@ contract Colony is BasicMetaTransaction, Multicall, ColonyStorage, PatriciaTreeP return rootLocalSkill; } + function getLocalSkill(uint256 _localSkillId) public view returns (LocalSkill memory localSkill) { + localSkill = localSkills[_localSkillId]; + } + function verifyReputationProof( bytes memory key, bytes memory value, diff --git a/contracts/colony/IColony.sol b/contracts/colony/IColony.sol index 220006ad94..210311a402 100644 --- a/contracts/colony/IColony.sol +++ b/contracts/colony/IColony.sol @@ -349,6 +349,11 @@ interface IColony is ColonyDataTypes, IRecovery, IBasicMetaTransaction, IMultica /// @return rootLocalSkill The root local skill id function getRootLocalSkill() external view returns (uint256 rootLocalSkill); + /// @notice Get the local skill + /// @param localSkillId Id for the local skill + /// @return localSkill The local skill + function getLocalSkill(uint256 localSkillId) external view returns (LocalSkill memory localSkill); + /// @notice Add a colony domain, and its respective local skill under skill with id `_parentSkillId`. /// New funding pot is created and associated with the domain here. /// @param _permissionDomainId The domainId in which I have the permission to take this action diff --git a/docs/interfaces/icolony.md b/docs/interfaces/icolony.md index aee5722207..143c34a561 100644 --- a/docs/interfaces/icolony.md +++ b/docs/interfaces/icolony.md @@ -612,6 +612,23 @@ Get the assigned `_token` payouts of pot with id `_potId`. |---|---|---| |payout|uint256|Funding pot payout amount +### ▸ `getLocalSkill(uint256 localSkillId):LocalSkill localSkill` + +Get the local skill + + +**Parameters** + +|Name|Type|Description| +|---|---|---| +|localSkillId|uint256|Id for the local skill + +**Return Parameters** + +|Name|Type|Description| +|---|---|---| +|localSkill|LocalSkill|The local skill + ### ▸ `getNonRewardPotsTotal(address _token):uint256 amount` Get the total amount of tokens `_token` minus amount reserved to be paid to the reputation and token holders as rewards. diff --git a/test/contracts-network/colony-expenditure.js b/test/contracts-network/colony-expenditure.js index 4d053b032f..a9ed4ae5cf 100644 --- a/test/contracts-network/colony-expenditure.js +++ b/test/contracts-network/colony-expenditure.js @@ -314,7 +314,7 @@ contract("Colony Expenditure", (accounts) => { ); }); - it.skip("should not allow owners to update a slot skill with a deprecated local skill", async () => { + it("should not allow owners to update a slot skill with a deprecated local skill", async () => { await colony.deprecateLocalSkill(localSkillId, true); await checkErrorRevert(colony.setExpenditureSkills(expenditureId, [SLOT0], [localSkillId], { from: ADMIN }), "colony-not-valid-local-skill"); @@ -324,6 +324,56 @@ contract("Colony Expenditure", (accounts) => { await checkErrorRevert(colony.setExpenditureSkills(expenditureId, [SLOT0], [100], { from: ADMIN }), "colony-not-valid-local-skill"); }); + it("should allow colonies to deprecate 'old' local skills", async () => { + const { OldInterface } = await deployColonyVersionGLWSS4(colonyNetwork); + await deployColonyVersionHMWSS(colonyNetwork); + await downgradeColony(colonyNetwork, colony, "glwss4"); + + // Make the colonyNetwork the old version + await deployColonyNetworkVersionGLWSS4(); + + const colonyNetworkAsEtherRouter = await EtherRouter.at(colonyNetwork.address); + const latestResolver = await colonyNetworkAsEtherRouter.resolver(); + + await downgradeColonyNetwork(colonyNetwork, "glwss4"); + + // Add two local skills + const oldColony = await OldInterface.at(colony.address); + await oldColony.addLocalSkill(); + const localSkillId2 = await colonyNetwork.getSkillCount(); + await oldColony.addLocalSkill(); + const localSkillId3 = await colonyNetwork.getSkillCount(); + + // Deprecate localSkillId2 in the old way + await colony.deprecateLocalSkill(localSkillId2, true); + + // Upgrade to current version + await colonyNetworkAsEtherRouter.setResolver(latestResolver); + await upgradeColonyOnceThenToLatest(colony); + + // Deprecate localSkillId3 in the new way + await colony.deprecateLocalSkill(localSkillId3, true); + + const localSkill = await colony.getLocalSkill(localSkillId3); + expect(localSkill.exists).to.be.true; + expect(localSkill.deprecated).to.be.true; + + // Both are deprecated + await colony.makeExpenditure(1, UINT256_MAX, 1); + expenditureId = await colony.getExpenditureCount(); + + await checkErrorRevert(colony.setExpenditureSkills(expenditureId, [SLOT0], [localSkillId2]), "colony-not-valid-local-skill"); + await checkErrorRevert(colony.setExpenditureSkills(expenditureId, [SLOT0], [localSkillId3]), "colony-not-valid-local-skill"); + + // A skill that doesn't exist cannot be deprecated + const fakeLocalSkillId = 10000; + await colony.deprecateLocalSkill(fakeLocalSkillId, true); + + const fakeLocalSkill = await colony.getLocalSkill(fakeLocalSkillId); + expect(fakeLocalSkill.exists).to.be.false; + expect(fakeLocalSkill.deprecated).to.be.false; + }); + it("should not allow owners to set a (now defunct) global skill, either deprecated or undeprecated", async () => { const { OldInterface } = await deployColonyVersionGLWSS4(colonyNetwork); await deployColonyVersionHMWSS(colonyNetwork);