Skip to content

Commit df2047d

Browse files
committed
Add support for deprecated interface
1 parent b709c03 commit df2047d

17 files changed

+436
-158
lines changed

contracts/colony/Colony.sol

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,12 @@ contract Colony is ColonyStorage, PatriciaTreeProofs, MultiChain {
4949
public stoppable auth
5050
returns (bool)
5151
{
52-
// Prevent transactions to network contracts
52+
// Prevent transactions to network contracts or network-managed extensions installed in this colony
5353
require(_to != address(this), "colony-cannot-target-self");
5454
require(_to != colonyNetworkAddress, "colony-cannot-target-network");
5555
require(_to != tokenLockingAddress, "colony-cannot-target-token-locking");
56+
require(isContract(_to), "colony-must-target-contract");
57+
require(!isOwnExtension(_to), "colony-cannot-target-own-extensions");
5658

5759
// Prevent transactions to transfer held tokens
5860
bytes4 sig;
@@ -63,16 +65,6 @@ contract Colony is ColonyStorage, PatriciaTreeProofs, MultiChain {
6365
else if (sig == TRANSFER_SIG) { transferTransactionPreparation(_to, _action); }
6466
else if (sig == BURN_GUY_SIG || sig == TRANSFER_FROM_SIG) { burnGuyOrTransferFromTransactionPreparation(_action); }
6567

66-
// Prevent transactions to network-managed extensions installed in this colony
67-
require(isContract(_to), "colony-to-must-be-contract");
68-
// slither-disable-next-line unused-return
69-
try ColonyExtension(_to).identifier() returns (bytes32 extensionId) {
70-
require(
71-
IColonyNetwork(colonyNetworkAddress).getExtensionInstallation(extensionId, address(this)) != _to,
72-
"colony-cannot-target-extensions"
73-
);
74-
} catch {}
75-
7668
bool res = executeCall(_to, 0, _action);
7769

7870
if (sig == APPROVE_SIG) { approveTransactionCleanup(_to, _action); }
@@ -345,23 +337,43 @@ contract Colony is ColonyStorage, PatriciaTreeProofs, MultiChain {
345337
function installExtension(bytes32 _extensionId, uint256 _version)
346338
public stoppable auth returns (address)
347339
{
348-
address extension = IColonyNetwork(colonyNetworkAddress).installExtension(_extensionId, _version);
349-
return extension;
340+
return IColonyNetwork(colonyNetworkAddress).installExtension(_extensionId, _version);
350341
}
351342

352-
function upgradeExtension(address payable _extension, uint256 _newVersion)
343+
// Deprecated
344+
function upgradeExtension(bytes32 _extensionId, uint256 _newVersion)
345+
public stoppable auth
346+
{
347+
IColonyNetwork(colonyNetworkAddress).upgradeExtension(_extensionId, _newVersion);
348+
}
349+
350+
function upgradeExtension(address _extension, uint256 _newVersion)
353351
public stoppable auth
354352
{
355353
IColonyNetwork(colonyNetworkAddress).upgradeExtension(_extension, _newVersion);
356354
}
357355

358-
function deprecateExtension(address payable _extension, bool _deprecated)
356+
// Deprecated
357+
function deprecateExtension(bytes32 _extensionId, bool _deprecated)
358+
public stoppable auth
359+
{
360+
IColonyNetwork(colonyNetworkAddress).deprecateExtension(_extensionId, _deprecated);
361+
}
362+
363+
function deprecateExtension(address _extension, bool _deprecated)
359364
public stoppable auth
360365
{
361366
IColonyNetwork(colonyNetworkAddress).deprecateExtension(_extension, _deprecated);
362367
}
363368

364-
function uninstallExtension(address payable _extension)
369+
// Deprecated
370+
function uninstallExtension(bytes32 _extensionId)
371+
public stoppable auth
372+
{
373+
IColonyNetwork(colonyNetworkAddress).uninstallExtension(_extensionId);
374+
}
375+
376+
function uninstallExtension(address _extension)
365377
public stoppable auth
366378
{
367379
IColonyNetwork(colonyNetworkAddress).uninstallExtension(_extension);

contracts/colony/ColonyStorage.sol

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -221,20 +221,7 @@ contract ColonyStorage is CommonStorage, ColonyDataTypes, ColonyNetworkDataTypes
221221
}
222222

223223
modifier onlyExtension() {
224-
// Ensure msg.sender is a contract
225-
require(isContract(msg.sender), "colony-sender-must-be-contract");
226-
227-
// Ensure msg.sender is an extension, must check old & new formats
228-
// slither-disable-next-line unused-return
229-
try ColonyExtension(msg.sender).identifier() returns (bytes32 extensionId) {
230-
require(
231-
IColonyNetwork(colonyNetworkAddress).getExtensionInstallation(extensionId, address(this)) == msg.sender ||
232-
IColonyNetwork(colonyNetworkAddress).getExtensionMultiInstallation(msg.sender) == address(this),
233-
"colony-must-be-extension"
234-
);
235-
} catch {
236-
require(false, "colony-must-be-extension");
237-
}
224+
require(isOwnExtension(msg.sender), "colony-must-be-extension");
238225
_;
239226
}
240227

@@ -283,6 +270,23 @@ contract ColonyStorage is CommonStorage, ColonyDataTypes, ColonyNetworkDataTypes
283270
return size > 0;
284271
}
285272

273+
function isOwnExtension(address addr) internal returns (bool) {
274+
// Ensure addr is a contract first, otherwise `try` block will revert
275+
if (!isContract(addr)) { return false; }
276+
277+
// // Ensure addr is an extension installed in the colony, must check old & new formats
278+
// // slither-disable-next-line unused-return
279+
try ColonyExtension(addr).identifier() returns (bytes32 extensionId) {
280+
return (
281+
IColonyNetwork(colonyNetworkAddress).getExtensionInstallation(extensionId, address(this)) == addr ||
282+
IColonyNetwork(colonyNetworkAddress).getExtensionMultiInstallation(addr) == address(this)
283+
);
284+
} catch {
285+
return false;
286+
}
287+
288+
}
289+
286290
function domainExists(uint256 domainId) internal view returns (bool) {
287291
return domainId > 0 && domainId <= domainCount;
288292
}

contracts/colony/IColony.sol

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -250,21 +250,40 @@ interface IColony is ColonyDataTypes, IRecovery {
250250
/// @return extension The address of the extension installation
251251
function installExtension(bytes32 extensionId, uint256 version) external returns (address extension);
252252

253+
/// @dev DEPRECATED
254+
/// @notice Upgrade an extension in a colony. Secured function to authorised members.
255+
/// @param extensionId keccak256 hash of the extension name, used as an indentifier
256+
/// @param newVersion The version to upgrade to (must be one larger than the current version)
257+
function upgradeExtension(bytes32 extensionId, uint256 newVersion) external;
258+
253259
/// @notice Upgrade an extension in a colony. Secured function to authorised members.
254260
/// @param extension The address of the extension installation
255261
/// @param newVersion The version to upgrade to (must be one larger than the current version)
256-
function upgradeExtension(address payable extension, uint256 newVersion) external;
262+
function upgradeExtension(address extension, uint256 newVersion) external;
263+
264+
/// @dev DEPRECATED
265+
/// @notice Set the deprecation of an extension in a colony. Secured function to authorised members.
266+
/// @param extensionId keccak256 hash of the extension name, used as an indentifier
267+
/// @param deprecated Whether to deprecate the extension or not
268+
function deprecateExtension(bytes32 extensionId, bool deprecated) external;
257269

258270
/// @notice Set the deprecation of an extension in a colony. Secured function to authorised members.
259271
/// @param extension The address of the extension installation
260272
/// @param deprecated Whether to deprecate the extension or not
261-
function deprecateExtension(address payable extension, bool deprecated) external;
273+
function deprecateExtension(address extension, bool deprecated) external;
274+
275+
/// @dev DEPRECATED
276+
/// @notice Uninstall an extension from a colony. Secured function to authorised members.
277+
/// @dev This is a permanent action -- re-installing the extension will deploy a new contract
278+
/// @dev It is recommended to deprecate an extension before uninstalling to allow active objects to be resolved
279+
/// @param extensionId keccak256 hash of the extension name, used as an indentifier
280+
function uninstallExtension(bytes32 extensionId) external;
262281

263282
/// @notice Uninstall an extension from a colony. Secured function to authorised members.
264283
/// @dev This is a permanent action -- re-installing the extension will deploy a new contract
265284
/// @dev It is recommended to deprecate an extension before uninstalling to allow active objects to be resolved
266285
/// @param extension The address of the extension installation
267-
function uninstallExtension(address payable extension) external;
286+
function uninstallExtension(address extension) external;
268287

269288
/// @notice Add a colony domain, and its respective local skill under skill with id `_parentSkillId`.
270289
/// New funding pot is created and associated with the domain here.

contracts/colonyNetwork/ColonyNetworkDataTypes.sol

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,18 +121,38 @@ interface ColonyNetworkDataTypes {
121121
/// @param version The version of the extension
122122
event ExtensionInstalled(bytes32 indexed extensionId, address indexed extension, address indexed colony, uint256 version);
123123

124+
/// @dev DEPRECATED
125+
/// @notice Event logged when an extension is upgraded in a colony
126+
/// @param extensionId The identifier for the extension
127+
/// @param colony The address of the colony
128+
/// @param version The new version of the extension
129+
event ExtensionUpgraded(bytes32 indexed extensionId, address indexed colony, uint256 version);
130+
124131
/// @notice Event logged when an extension is upgraded in a colony
125132
/// @param extension Address of the extension installation
126133
/// @param colony The address of the colony
127134
/// @param version The new version of the extension
128135
event ExtensionUpgraded(address indexed extension, address indexed colony, uint256 version);
129136

137+
/// @dev DEPRECATED
138+
/// @notice Event logged when an extension is (un)deprecated in a colony
139+
/// @param extensionId The identifier for the extension
140+
/// @param colony The address of the colony
141+
/// @param deprecated Whether the extension is deprecated or not
142+
event ExtensionDeprecated(bytes32 indexed extensionId, address indexed colony, bool deprecated);
143+
130144
/// @notice Event logged when an extension is (un)deprecated in a colony
131145
/// @param extension Address of the extension installation
132146
/// @param colony The address of the colony
133147
/// @param deprecated Whether the extension is deprecated or not
134148
event ExtensionDeprecated(address indexed extension, address indexed colony, bool deprecated);
135149

150+
/// @dev DEPRECATED
151+
/// @notice Event logged when an extension is uninstalled from a colony
152+
/// @param extensionId The identifier for the extension
153+
/// @param colony The address of the colony
154+
event ExtensionUninstalled(bytes32 indexed extensionId, address indexed colony);
155+
136156
/// @notice Event logged when an extension is uninstalled from a colony
137157
/// @param extension Address of the extension installation
138158
/// @param colony The address of the colony

contracts/colonyNetwork/ColonyNetworkExtensions.sol

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,18 @@ contract ColonyNetworkExtensions is ColonyNetworkStorage {
6565
return address(extension);
6666
}
6767

68-
function upgradeExtension(address payable _extension, uint256 _newVersion)
68+
// Deprecated
69+
function upgradeExtension(bytes32 _extensionId, uint256 _newVersion)
70+
public
71+
stoppable
72+
{
73+
address extension = migrateToMultiExtension(_extensionId);
74+
upgradeExtension(extension, _newVersion);
75+
76+
emit ExtensionUpgraded(_extensionId, msg.sender, _newVersion);
77+
}
78+
79+
function upgradeExtension(address _extension, uint256 _newVersion)
6980
public
7081
stoppable
7182
calledByColony
@@ -77,15 +88,26 @@ contract ColonyNetworkExtensions is ColonyNetworkStorage {
7788
require(_newVersion == ColonyExtension(_extension).version() + 1, "colony-network-extension-bad-increment");
7889
require(resolvers[extensionId][_newVersion] != address(0x0), "colony-network-extension-bad-version");
7990

80-
EtherRouter(_extension).setResolver(resolvers[extensionId][_newVersion]);
91+
EtherRouter(payable(_extension)).setResolver(resolvers[extensionId][_newVersion]);
8192
ColonyExtension(_extension).finishUpgrade();
8293

8394
assert(ColonyExtension(_extension).version() == _newVersion);
8495

8596
emit ExtensionUpgraded(_extension, msg.sender, _newVersion);
8697
}
8798

88-
function deprecateExtension(address payable _extension, bool _deprecated)
99+
// Deprecated
100+
function deprecateExtension(bytes32 _extensionId, bool _deprecated)
101+
public
102+
stoppable
103+
{
104+
address extension = migrateToMultiExtension(_extensionId);
105+
deprecateExtension(extension, _deprecated);
106+
107+
emit ExtensionDeprecated(_extensionId, msg.sender, _deprecated);
108+
}
109+
110+
function deprecateExtension(address _extension, bool _deprecated)
89111
public
90112
stoppable
91113
calledByColony
@@ -95,7 +117,18 @@ contract ColonyNetworkExtensions is ColonyNetworkStorage {
95117
emit ExtensionDeprecated(_extension, msg.sender, _deprecated);
96118
}
97119

98-
function uninstallExtension(address payable _extension)
120+
// Deprecated
121+
function uninstallExtension(bytes32 _extensionId)
122+
public
123+
stoppable
124+
{
125+
address extension = migrateToMultiExtension(_extensionId);
126+
uninstallExtension(extension);
127+
128+
emit ExtensionUninstalled(_extensionId, msg.sender);
129+
}
130+
131+
function uninstallExtension(address _extension)
99132
public
100133
stoppable
101134
calledByColony
@@ -150,4 +183,12 @@ contract ColonyNetworkExtensions is ColonyNetworkStorage {
150183
address extension = Resolver(_resolver).lookup(VERSION_SIG);
151184
return ColonyExtension(extension).version();
152185
}
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+
}
153194
}

contracts/colonyNetwork/IColonyNetwork.sol

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -319,19 +319,36 @@ interface IColonyNetwork is ColonyNetworkDataTypes, IRecovery {
319319
/// @return extension The address of the extension installation
320320
function installExtension(bytes32 extensionId, uint256 version) external returns (address extension);
321321

322+
/// @dev DEPRECATED
323+
/// @notice Upgrade an extension in a colony. Can only be called by a Colony.
324+
/// @param extensionId keccak256 hash of the extension name, used as an indentifier
325+
/// @param newVersion Version of the extension to upgrade to (must be one greater than current)
326+
function upgradeExtension(bytes32 extensionId, uint256 newVersion) external;
327+
322328
/// @notice Upgrade an extension in a colony. Can only be called by a Colony.
323329
/// @param extension Address of the extension installation
324330
/// @param newVersion Version of the extension to upgrade to (must be one greater than current)
325-
function upgradeExtension(address payable extension, uint256 newVersion) external;
331+
function upgradeExtension(address extension, uint256 newVersion) external;
332+
333+
/// @dev DEPRECATED
334+
/// @notice Set the deprecation of an extension in a colony. Can only be called by a Colony.
335+
/// @param extensionId keccak256 hash of the extension name, used as an indentifier
336+
/// @param deprecated Whether to deprecate the extension or not
337+
function deprecateExtension(bytes32 extensionId, bool deprecated) external;
326338

327339
/// @notice Set the deprecation of an extension in a colony. Can only be called by a Colony.
328340
/// @param extension Address of the extension installation
329341
/// @param deprecated Whether to deprecate the extension or not
330-
function deprecateExtension(address payable extension, bool deprecated) external;
342+
function deprecateExtension(address extension, bool deprecated) external;
343+
344+
/// @dev DEPRECATED
345+
/// @notice Uninstall an extension in a colony. Can only be called by a Colony.
346+
/// @param extensionId keccak256 hash of the extension name, used as an indentifier
347+
function uninstallExtension(bytes32 extensionId) external;
331348

332349
/// @notice Uninstall an extension in a colony. Can only be called by a Colony.
333350
/// @param extension Address of the extension installation
334-
function uninstallExtension(address payable extension) external;
351+
function uninstallExtension(address extension) external;
335352

336353
/// @notice Get an extension's resolver.
337354
/// @param extensionId keccak256 hash of the extension name, used as an indentifier

docs/_Interface_IColony.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,19 @@ Set the deprecation of an extension in a colony. Secured function to authorised
261261
|deprecated|bool|Whether to deprecate the extension or not
262262

263263

264+
### `deprecateExtension`
265+
266+
Set the deprecation of an extension in a colony. Secured function to authorised members.
267+
268+
269+
**Parameters**
270+
271+
|Name|Type|Description|
272+
|---|---|---|
273+
|extensionId|bytes32|keccak256 hash of the extension name, used as an indentifier
274+
|deprecated|bool|Whether to deprecate the extension or not
275+
276+
264277
### `editColony`
265278

266279
Called to change the metadata associated with a colony. Expected to be a IPFS hash of a JSON blob, but not enforced to any degree by the contracts
@@ -1761,6 +1774,19 @@ Uninstall an extension from a colony. Secured function to authorised members.
17611774
|extension|address|The address of the extension installation
17621775

17631776

1777+
### `uninstallExtension`
1778+
1779+
Uninstall an extension from a colony. Secured function to authorised members.
1780+
1781+
*Note: This is a permanent action -- re-installing the extension will deploy a new contract*
1782+
1783+
**Parameters**
1784+
1785+
|Name|Type|Description|
1786+
|---|---|---|
1787+
|extensionId|bytes32|keccak256 hash of the extension name, used as an indentifier
1788+
1789+
17641790
### `unlockToken`
17651791

17661792
unlock the native colony token, if possible
@@ -1832,6 +1858,19 @@ Upgrade an extension in a colony. Secured function to authorised members.
18321858
|newVersion|uint256|The version to upgrade to (must be one larger than the current version)
18331859

18341860

1861+
### `upgradeExtension`
1862+
1863+
Upgrade an extension in a colony. Secured function to authorised members.
1864+
1865+
1866+
**Parameters**
1867+
1868+
|Name|Type|Description|
1869+
|---|---|---|
1870+
|extensionId|bytes32|keccak256 hash of the extension name, used as an indentifier
1871+
|newVersion|uint256|The version to upgrade to (must be one larger than the current version)
1872+
1873+
18351874
### `userCanSetRoles`
18361875

18371876
Check whether a given user can modify roles in the target domain `_childDomainId`. Mostly a convenience function to provide a uniform interface for extension contracts validating permissions

0 commit comments

Comments
 (0)