Skip to content

Commit 5a7b35c

Browse files
committed
Add support for deprecated interface
1 parent d574493 commit 5a7b35c

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
@@ -79,10 +79,12 @@ contract Colony is ColonyStorage, PatriciaTreeProofs, MultiChain {
7979
external stoppable self
8080
returns (bool)
8181
{
82-
// Prevent transactions to network contracts
82+
// Prevent transactions to network contracts or network-managed extensions installed in this colony
8383
require(_to != address(this), "colony-cannot-target-self");
8484
require(_to != colonyNetworkAddress, "colony-cannot-target-network");
8585
require(_to != tokenLockingAddress, "colony-cannot-target-token-locking");
86+
require(isContract(_to), "colony-must-target-contract");
87+
require(!isOwnExtension(_to), "colony-cannot-target-own-extensions");
8688

8789
// Prevent transactions to transfer held tokens
8890
bytes4 sig;
@@ -93,16 +95,6 @@ contract Colony is ColonyStorage, PatriciaTreeProofs, MultiChain {
9395
else if (sig == TRANSFER_SIG) { transferTransactionPreparation(_to, _action); }
9496
else if (sig == BURN_GUY_SIG || sig == TRANSFER_FROM_SIG) { burnGuyOrTransferFromTransactionPreparation(_action); }
9597

96-
// Prevent transactions to network-managed extensions installed in this colony
97-
require(isContract(_to), "colony-to-must-be-contract");
98-
// slither-disable-next-line unused-return
99-
try ColonyExtension(_to).identifier() returns (bytes32 extensionId) {
100-
require(
101-
IColonyNetwork(colonyNetworkAddress).getExtensionInstallation(extensionId, address(this)) != _to,
102-
"colony-cannot-target-extensions"
103-
);
104-
} catch {}
105-
10698
bool res = executeCall(_to, 0, _action);
10799

108100
if (sig == APPROVE_SIG) { approveTransactionCleanup(_to, _action); }
@@ -375,23 +367,43 @@ contract Colony is ColonyStorage, PatriciaTreeProofs, MultiChain {
375367
function installExtension(bytes32 _extensionId, uint256 _version)
376368
public stoppable auth returns (address)
377369
{
378-
address extension = IColonyNetwork(colonyNetworkAddress).installExtension(_extensionId, _version);
379-
return extension;
370+
return IColonyNetwork(colonyNetworkAddress).installExtension(_extensionId, _version);
380371
}
381372

382-
function upgradeExtension(address payable _extension, uint256 _newVersion)
373+
// Deprecated
374+
function upgradeExtension(bytes32 _extensionId, uint256 _newVersion)
375+
public stoppable auth
376+
{
377+
IColonyNetwork(colonyNetworkAddress).upgradeExtension(_extensionId, _newVersion);
378+
}
379+
380+
function upgradeExtension(address _extension, uint256 _newVersion)
383381
public stoppable auth
384382
{
385383
IColonyNetwork(colonyNetworkAddress).upgradeExtension(_extension, _newVersion);
386384
}
387385

388-
function deprecateExtension(address payable _extension, bool _deprecated)
386+
// Deprecated
387+
function deprecateExtension(bytes32 _extensionId, bool _deprecated)
388+
public stoppable auth
389+
{
390+
IColonyNetwork(colonyNetworkAddress).deprecateExtension(_extensionId, _deprecated);
391+
}
392+
393+
function deprecateExtension(address _extension, bool _deprecated)
389394
public stoppable auth
390395
{
391396
IColonyNetwork(colonyNetworkAddress).deprecateExtension(_extension, _deprecated);
392397
}
393398

394-
function uninstallExtension(address payable _extension)
399+
// Deprecated
400+
function uninstallExtension(bytes32 _extensionId)
401+
public stoppable auth
402+
{
403+
IColonyNetwork(colonyNetworkAddress).uninstallExtension(_extensionId);
404+
}
405+
406+
function uninstallExtension(address _extension)
395407
public stoppable auth
396408
{
397409
IColonyNetwork(colonyNetworkAddress).uninstallExtension(_extension);

contracts/colony/ColonyStorage.sol

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

241241
modifier onlyExtension() {
242-
// Ensure msg.sender is a contract
243-
require(isContract(msg.sender), "colony-sender-must-be-contract");
244-
245-
// Ensure msg.sender is an extension, must check old & new formats
246-
// slither-disable-next-line unused-return
247-
try ColonyExtension(msg.sender).identifier() returns (bytes32 extensionId) {
248-
require(
249-
IColonyNetwork(colonyNetworkAddress).getExtensionInstallation(extensionId, address(this)) == msg.sender ||
250-
IColonyNetwork(colonyNetworkAddress).getExtensionMultiInstallation(msg.sender) == address(this),
251-
"colony-must-be-extension"
252-
);
253-
} catch {
254-
require(false, "colony-must-be-extension");
255-
}
242+
require(isOwnExtension(msg.sender), "colony-must-be-extension");
256243
_;
257244
}
258245

@@ -301,6 +288,23 @@ contract ColonyStorage is CommonStorage, ColonyDataTypes, ColonyNetworkDataTypes
301288
return size > 0;
302289
}
303290

291+
function isOwnExtension(address addr) internal returns (bool) {
292+
// Ensure addr is a contract first, otherwise `try` block will revert
293+
if (!isContract(addr)) { return false; }
294+
295+
// // Ensure addr is an extension installed in the colony, must check old & new formats
296+
// // slither-disable-next-line unused-return
297+
try ColonyExtension(addr).identifier() returns (bytes32 extensionId) {
298+
return (
299+
IColonyNetwork(colonyNetworkAddress).getExtensionInstallation(extensionId, address(this)) == addr ||
300+
IColonyNetwork(colonyNetworkAddress).getExtensionMultiInstallation(addr) == address(this)
301+
);
302+
} catch {
303+
return false;
304+
}
305+
306+
}
307+
304308
function domainExists(uint256 domainId) internal view returns (bool) {
305309
return domainId > 0 && domainId <= domainCount;
306310
}

contracts/colony/IColony.sol

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

269+
/// @dev DEPRECATED
270+
/// @notice Upgrade an extension in a colony. Secured function to authorised members.
271+
/// @param extensionId keccak256 hash of the extension name, used as an indentifier
272+
/// @param newVersion The version to upgrade to (must be one larger than the current version)
273+
function upgradeExtension(bytes32 extensionId, uint256 newVersion) external;
274+
269275
/// @notice Upgrade an extension in a colony. Secured function to authorised members.
270276
/// @param extension The address of the extension installation
271277
/// @param newVersion The version to upgrade to (must be one larger than the current version)
272-
function upgradeExtension(address payable extension, uint256 newVersion) external;
278+
function upgradeExtension(address extension, uint256 newVersion) external;
279+
280+
/// @dev DEPRECATED
281+
/// @notice Set the deprecation of an extension in a colony. Secured function to authorised members.
282+
/// @param extensionId keccak256 hash of the extension name, used as an indentifier
283+
/// @param deprecated Whether to deprecate the extension or not
284+
function deprecateExtension(bytes32 extensionId, bool deprecated) external;
273285

274286
/// @notice Set the deprecation of an extension in a colony. Secured function to authorised members.
275287
/// @param extension The address of the extension installation
276288
/// @param deprecated Whether to deprecate the extension or not
277-
function deprecateExtension(address payable extension, bool deprecated) external;
289+
function deprecateExtension(address extension, bool deprecated) external;
290+
291+
/// @dev DEPRECATED
292+
/// @notice Uninstall an extension from a colony. Secured function to authorised members.
293+
/// @dev This is a permanent action -- re-installing the extension will deploy a new contract
294+
/// @dev It is recommended to deprecate an extension before uninstalling to allow active objects to be resolved
295+
/// @param extensionId keccak256 hash of the extension name, used as an indentifier
296+
function uninstallExtension(bytes32 extensionId) external;
278297

279298
/// @notice Uninstall an extension from a colony. Secured function to authorised members.
280299
/// @dev This is a permanent action -- re-installing the extension will deploy a new contract
281300
/// @dev It is recommended to deprecate an extension before uninstalling to allow active objects to be resolved
282301
/// @param extension The address of the extension installation
283-
function uninstallExtension(address payable extension) external;
302+
function uninstallExtension(address extension) external;
284303

285304
/// @notice Add a colony domain, and its respective local skill under skill with id `_parentSkillId`.
286305
/// 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
@@ -1902,6 +1915,19 @@ Uninstall an extension from a colony. Secured function to authorised members.
19021915
|extension|address|The address of the extension installation
19031916

19041917

1918+
### `uninstallExtension`
1919+
1920+
Uninstall an extension from a colony. Secured function to authorised members.
1921+
1922+
*Note: This is a permanent action -- re-installing the extension will deploy a new contract*
1923+
1924+
**Parameters**
1925+
1926+
|Name|Type|Description|
1927+
|---|---|---|
1928+
|extensionId|bytes32|keccak256 hash of the extension name, used as an indentifier
1929+
1930+
19051931
### `unlockToken`
19061932

19071933
unlock the native colony token, if possible
@@ -1973,6 +1999,19 @@ Upgrade an extension in a colony. Secured function to authorised members.
19731999
|newVersion|uint256|The version to upgrade to (must be one larger than the current version)
19742000

19752001

2002+
### `upgradeExtension`
2003+
2004+
Upgrade an extension in a colony. Secured function to authorised members.
2005+
2006+
2007+
**Parameters**
2008+
2009+
|Name|Type|Description|
2010+
|---|---|---|
2011+
|extensionId|bytes32|keccak256 hash of the extension name, used as an indentifier
2012+
|newVersion|uint256|The version to upgrade to (must be one larger than the current version)
2013+
2014+
19762015
### `userCanSetRoles`
19772016

19782017
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)