Skip to content

Commit 2a7ee7a

Browse files
committed
Update in response to review comments
1 parent f40a9bd commit 2a7ee7a

File tree

5 files changed

+82
-107
lines changed

5 files changed

+82
-107
lines changed

contracts/colony/Colony.sol

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -370,39 +370,18 @@ contract Colony is ColonyStorage, PatriciaTreeProofs, MultiChain {
370370
return IColonyNetwork(colonyNetworkAddress).installExtension(_extensionId, _version);
371371
}
372372

373-
// Deprecated
374-
function upgradeExtension(bytes32 _extensionId, uint256 _newVersion)
375-
public stoppable auth
376-
{
377-
IColonyNetwork(colonyNetworkAddress).upgradeExtension(_extensionId, _newVersion);
378-
}
379-
380373
function upgradeExtension(address _extension, uint256 _newVersion)
381374
public stoppable auth
382375
{
383376
IColonyNetwork(colonyNetworkAddress).upgradeExtension(_extension, _newVersion);
384377
}
385378

386-
// Deprecated
387-
function deprecateExtension(bytes32 _extensionId, bool _deprecated)
388-
public stoppable auth
389-
{
390-
IColonyNetwork(colonyNetworkAddress).deprecateExtension(_extensionId, _deprecated);
391-
}
392-
393379
function deprecateExtension(address _extension, bool _deprecated)
394380
public stoppable auth
395381
{
396382
IColonyNetwork(colonyNetworkAddress).deprecateExtension(_extension, _deprecated);
397383
}
398384

399-
// Deprecated
400-
function uninstallExtension(bytes32 _extensionId)
401-
public stoppable auth
402-
{
403-
IColonyNetwork(colonyNetworkAddress).uninstallExtension(_extensionId);
404-
}
405-
406385
function uninstallExtension(address _extension)
407386
public stoppable auth
408387
{

contracts/colonyNetwork/ColonyNetworkExtensions.sol

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ contract ColonyNetworkExtensions is ColonyNetworkStorage {
7070
public
7171
stoppable
7272
{
73-
address extension = migrateToMultiExtension(_extensionId);
73+
address extension = migrateToMultiExtension(_extensionId, msg.sender);
7474
upgradeExtension(extension, _newVersion);
7575

7676
emit ExtensionUpgraded(_extensionId, msg.sender, _newVersion);
@@ -101,7 +101,7 @@ contract ColonyNetworkExtensions is ColonyNetworkStorage {
101101
public
102102
stoppable
103103
{
104-
address extension = migrateToMultiExtension(_extensionId);
104+
address extension = migrateToMultiExtension(_extensionId, msg.sender);
105105
deprecateExtension(extension, _deprecated);
106106

107107
emit ExtensionDeprecated(_extensionId, msg.sender, _deprecated);
@@ -122,7 +122,7 @@ contract ColonyNetworkExtensions is ColonyNetworkStorage {
122122
public
123123
stoppable
124124
{
125-
address extension = migrateToMultiExtension(_extensionId);
125+
address extension = migrateToMultiExtension(_extensionId, msg.sender);
126126
uninstallExtension(extension);
127127

128128
emit ExtensionUninstalled(_extensionId, msg.sender);
@@ -142,6 +142,18 @@ contract ColonyNetworkExtensions is ColonyNetworkStorage {
142142
emit ExtensionUninstalled(_extension, msg.sender);
143143
}
144144

145+
function migrateToMultiExtension(bytes32 _extensionId, address _colony)
146+
public
147+
stoppable
148+
returns (address)
149+
{
150+
address extension = installations[_extensionId][_colony];
151+
require(extension != address(0x0), "colony-network-extension-not-installed");
152+
153+
multiInstallations[extension] = payable(_colony);
154+
return extension;
155+
}
156+
145157
// Public view functions
146158

147159
function getExtensionResolver(bytes32 _extensionId, uint256 _version)
@@ -183,12 +195,4 @@ contract ColonyNetworkExtensions is ColonyNetworkStorage {
183195
address extension = Resolver(_resolver).lookup(VERSION_SIG);
184196
return ColonyExtension(extension).version();
185197
}
186-
187-
function migrateToMultiExtension(bytes32 _extensionId) internal returns (address) {
188-
address extension = installations[_extensionId][msg.sender];
189-
require(extension != address(0x0), "colony-network-extension-not-installed");
190-
191-
multiInstallations[extension] = msg.sender;
192-
return extension;
193-
}
194198
}

contracts/colonyNetwork/IColonyNetwork.sol

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,12 @@ interface IColonyNetwork is ColonyNetworkDataTypes, IRecovery {
350350
/// @param extension Address of the extension installation
351351
function uninstallExtension(address extension) external;
352352

353+
/// @notice Migrate extension bookkeeping to multiExtension
354+
/// @param extensionId keccak256 hash of the extension name, used as an indentifier
355+
/// @param colony Address of the colony the extension is installed in
356+
/// @return extension The address of the extension
357+
function migrateToMultiExtension(bytes32 extensionId, address colony) external returns (address extension);
358+
353359
/// @notice Get an extension's resolver.
354360
/// @param extensionId keccak256 hash of the extension name, used as an indentifier
355361
/// @param version Version of the extension

docs/_Interface_IColonyNetwork.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,24 @@ Reverse lookup a username from an address.
733733
|---|---|---|
734734
|domain|string|A string containing the colony-based ENS name corresponding to addr
735735

736+
### `migrateToMultiExtension`
737+
738+
Migrate extension bookkeeping to multiExtension
739+
740+
741+
**Parameters**
742+
743+
|Name|Type|Description|
744+
|---|---|---|
745+
|extensionId|bytes32|keccak256 hash of the extension name, used as an indentifier
746+
|colony|address|Address of the colony the extension is installed in
747+
748+
**Return Parameters**
749+
750+
|Name|Type|Description|
751+
|---|---|---|
752+
|extension|address|The address of the extension
753+
736754
### `punishStakers`
737755

738756
Function called to punish people who staked against a new reputation root hash that turned out to be incorrect.

test/contracts-network/colony-network-extensions.js

Lines changed: 43 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ const ContractEditing = artifacts.require("ContractEditing");
2929

3030
contract("Colony Network Extensions", (accounts) => {
3131
let colonyNetwork;
32-
let editableColonyNetwork;
3332
let metaColony;
3433
let colony;
3534
let token;
@@ -73,13 +72,6 @@ contract("Colony Network Extensions", (accounts) => {
7372
colonyNetwork = await setupColonyNetwork();
7473
({ metaColony } = await setupMetaColonyWithLockedCLNYToken(colonyNetwork));
7574

76-
const colonyNetworkAsER = await EtherRouter.at(colonyNetwork.address);
77-
const colonyNetworkResolverAddress = await colonyNetworkAsER.resolver();
78-
const colonyNetworkResolver = await Resolver.at(colonyNetworkResolverAddress);
79-
const contractEditing = await ContractEditing.new();
80-
await colonyNetworkResolver.register("setStorageSlot(uint256,bytes32)", contractEditing.address);
81-
editableColonyNetwork = await ContractEditing.at(colonyNetwork.address);
82-
8375
({ colony, token } = await setupRandomColony(colonyNetwork));
8476
await colony.addDomain(1, UINT256_MAX, 1); // Domain 2
8577

@@ -154,28 +146,67 @@ contract("Colony Network Extensions", (accounts) => {
154146
await metaColony.addExtensionToNetwork(TEST_EXTENSION, testExtension2Resolver.address);
155147
});
156148

157-
it("allows a root user to install an extension with any version", async () => {
158-
const tx = await colony.installExtension(TEST_EXTENSION, 2, { from: ROOT });
149+
it("allows a root user to install an extension", async () => {
150+
const tx = await colony.installExtension(TEST_EXTENSION, 1, { from: ROOT });
159151

160152
const extensionAddress = getExtensionAddressFromTx(tx);
161-
const extension = await TestExtension2.at(extensionAddress);
153+
const extension = await TestExtension1.at(extensionAddress);
162154
const owner = await extension.owner();
163155
expect(owner).to.equal(colonyNetwork.address);
164156

165157
const identifier = await extension.identifier();
166158
const version = await extension.version();
167159
const colonyAddress = await extension.getColony();
168160
expect(identifier).to.equal(TEST_EXTENSION);
169-
expect(version).to.eq.BN(2);
161+
expect(version).to.eq.BN(1);
170162
expect(colonyAddress).to.equal(colony.address);
171163

172164
// Only colonyNetwork can install the extension
173165
await checkErrorRevert(extension.install(colony.address), "ds-auth-unauthorized");
174166
});
175167

168+
it("allows a root user to install an extension with any version", async () => {
169+
const tx = await colony.installExtension(TEST_EXTENSION, 2, { from: ROOT });
170+
171+
const extensionAddress = getExtensionAddressFromTx(tx);
172+
const extension = await TestExtension2.at(extensionAddress);
173+
174+
const identifier = await extension.identifier();
175+
const version = await extension.version();
176+
expect(identifier).to.equal(TEST_EXTENSION);
177+
expect(version).to.eq.BN(2);
178+
});
179+
176180
it("does not allow an extension to be installed with a nonexistent resolver", async () => {
177181
await checkErrorRevert(colony.installExtension(TEST_EXTENSION, 0, { from: ROOT }), "colony-network-extension-bad-version");
178182
});
183+
184+
it("allows colonies to migrate to multiExtension bookkeeping", async () => {
185+
const colonyNetworkAsER = await EtherRouter.at(colonyNetwork.address);
186+
const colonyNetworkResolverAddress = await colonyNetworkAsER.resolver();
187+
const colonyNetworkResolver = await Resolver.at(colonyNetworkResolverAddress);
188+
const contractEditing = await ContractEditing.new();
189+
await colonyNetworkResolver.register("setStorageSlot(uint256,bytes32)", contractEditing.address);
190+
const editableColonyNetwork = await ContractEditing.at(colonyNetwork.address);
191+
192+
const extension = await TestExtension1.new();
193+
await extension.install(colony.address);
194+
195+
let colonyAddress;
196+
197+
colonyAddress = await colonyNetwork.getExtensionMultiInstallation(extension.address);
198+
expect(colonyAddress).to.equal(ethers.constants.AddressZero);
199+
200+
// Set up `installations` mapping in the old style
201+
const slot = soliditySha3(`0x000000000000000000000000${colony.address.slice(2)}`, soliditySha3(TEST_EXTENSION, 39));
202+
const value = `0x000000000000000000000000${extension.address.slice(2)}`;
203+
await editableColonyNetwork.setStorageSlot(slot, value);
204+
205+
await colonyNetwork.migrateToMultiExtension(TEST_EXTENSION, colony.address);
206+
207+
colonyAddress = await colonyNetwork.getExtensionMultiInstallation(extension.address);
208+
expect(colonyAddress).to.equal(colony.address);
209+
});
179210
});
180211

181212
describe("upgrading extensions", () => {
@@ -200,26 +231,6 @@ contract("Colony Network Extensions", (accounts) => {
200231
expect(version).to.eq.BN(2);
201232
});
202233

203-
it("allows root users to upgrade an extension, with the deprecated interface", async () => {
204-
const tx = await colony.installExtension(TEST_EXTENSION, 1, { from: ROOT });
205-
206-
const extensionAddress = getExtensionAddressFromTx(tx);
207-
let extension = await ColonyExtension.at(extensionAddress);
208-
let version = await extension.version();
209-
expect(version).to.eq.BN(1);
210-
211-
// Set up `installations` mapping in the old style
212-
const slot = soliditySha3(`0x000000000000000000000000${colony.address.slice(2)}`, soliditySha3(TEST_EXTENSION, 39));
213-
const value = `0x000000000000000000000000${extensionAddress.slice(2)}`;
214-
await editableColonyNetwork.setStorageSlot(slot, value);
215-
216-
await colony.methods["upgradeExtension(bytes32,uint256)"](TEST_EXTENSION, 2, { from: ROOT });
217-
218-
extension = await ColonyExtension.at(extensionAddress);
219-
version = await extension.version();
220-
expect(version).to.eq.BN(2);
221-
});
222-
223234
it("does not allow non-root users to upgrade an extension", async () => {
224235
const tx = await colony.installExtension(TEST_EXTENSION, 1, { from: ROOT });
225236

@@ -279,28 +290,6 @@ contract("Colony Network Extensions", (accounts) => {
279290
await extension.foo();
280291
});
281292

282-
it("allows root users to deprecate and undeprecate an extension, with the deprecated interface", async () => {
283-
const tx = await colony.installExtension(TEST_EXTENSION, 1, { from: ROOT });
284-
285-
const extensionAddress = getExtensionAddressFromTx(tx);
286-
const extension = await TestExtension1.at(extensionAddress);
287-
288-
// Set up `installations` mapping in the old style
289-
const slot = soliditySha3(`0x000000000000000000000000${colony.address.slice(2)}`, soliditySha3(TEST_EXTENSION, 39));
290-
const value = `0x000000000000000000000000${extensionAddress.slice(2)}`;
291-
await editableColonyNetwork.setStorageSlot(slot, value);
292-
293-
await extension.foo();
294-
295-
await colony.methods["deprecateExtension(bytes32,bool)"](TEST_EXTENSION, true, { from: ROOT });
296-
297-
await checkErrorRevert(extension.foo(), "colony-extension-deprecated");
298-
299-
await colony.methods["deprecateExtension(bytes32,bool)"](TEST_EXTENSION, false, { from: ROOT });
300-
301-
await extension.foo();
302-
});
303-
304293
it("does not allow non-root users to deprecate an extension", async () => {
305294
const tx = await colony.installExtension(TEST_EXTENSION, 1, { from: ROOT });
306295

@@ -330,27 +319,6 @@ contract("Colony Network Extensions", (accounts) => {
330319
expect(new BN(colonyBalance)).to.eq.BN(100);
331320
});
332321

333-
it("allows root users to uninstall an extension and send ether to the beneficiary, with the deprecated interface", async () => {
334-
const tx = await colony.installExtension(TEST_EXTENSION, 1, { from: ROOT });
335-
336-
const extensionAddress = getExtensionAddressFromTx(tx);
337-
const extension = await TestExtension1.at(extensionAddress);
338-
await extension.send(100);
339-
340-
// Set up `installations` mapping in the old style
341-
const slot = soliditySha3(`0x000000000000000000000000${colony.address.slice(2)}`, soliditySha3(TEST_EXTENSION, 39));
342-
const value = `0x000000000000000000000000${extensionAddress.slice(2)}`;
343-
await editableColonyNetwork.setStorageSlot(slot, value);
344-
345-
// Only colonyNetwork can uninstall
346-
await checkErrorRevert(extension.uninstall(), "ds-auth-unauthorized");
347-
348-
await colony.methods["uninstallExtension(bytes32)"](TEST_EXTENSION, { from: ROOT });
349-
350-
const colonyBalance = await web3GetBalance(colony.address);
351-
expect(new BN(colonyBalance)).to.eq.BN(100);
352-
});
353-
354322
it("does not allow non-root users to uninstall an extension", async () => {
355323
await checkErrorRevert(colony.methods["uninstallExtension(address)"](ethers.constants.AddressZero, { from: USER }), "ds-auth-unauthorized");
356324
});

0 commit comments

Comments
 (0)