Skip to content

Commit ac25958

Browse files
committed
Add Arbitration reputation penalties
1 parent c888778 commit ac25958

File tree

5 files changed

+97
-8
lines changed

5 files changed

+97
-8
lines changed

contracts/colony/Colony.sol

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,25 @@ contract Colony is ColonyStorage, PatriciaTreeProofs {
117117
return token;
118118
}
119119

120+
function emitDomainReputationPenalty(
121+
uint256 _permissionDomainId,
122+
uint256 _childSkillIndex,
123+
uint256 _domainId,
124+
address _user,
125+
int256 _amount
126+
) public stoppable authDomain(_permissionDomainId, _childSkillIndex, _domainId)
127+
{
128+
require(_amount <= 0, "colony-penalty-cannot-be-positive");
129+
IColonyNetwork(colonyNetworkAddress).appendReputationUpdateLog(_user, _amount, domains[_domainId].skillId);
130+
}
131+
132+
function emitSkillReputationPenalty(uint256 _skillId, address _user, int256 _amount)
133+
public stoppable auth validGlobalSkill(_skillId)
134+
{
135+
require(_amount <= 0, "colony-penalty-cannot-be-positive");
136+
IColonyNetwork(colonyNetworkAddress).appendReputationUpdateLog(_user, _amount, _skillId);
137+
}
138+
120139
function initialiseColony(address _colonyNetworkAddress, address _token) public stoppable {
121140
require(colonyNetworkAddress == address(0x0), "colony-already-initialised-network");
122141
require(token == address(0x0), "colony-already-initialised-token");
@@ -302,14 +321,17 @@ contract Colony is ColonyStorage, PatriciaTreeProofs {
302321
// v4 to v5
303322
function finishUpgrade() public always {
304323
ColonyAuthority colonyAuthority = ColonyAuthority(address(authority));
324+
bytes4 sig;
305325

306-
// Add stake management functionality
307-
colonyAuthority.setRoleCapability(
308-
uint8(ColonyRole.Arbitration),
309-
address(this),
310-
bytes4(keccak256("transferStake(uint256,uint256,address,address,uint256,uint256,address)")),
311-
true
312-
);
326+
// Add stake management functionality (colonyNetwork#757)
327+
sig = bytes4(keccak256("transferStake(uint256,uint256,address,address,uint256,uint256,address)"));
328+
colonyAuthority.setRoleCapability(uint8(ColonyRole.Arbitration), address(this), sig, true);
329+
330+
// Add reputation penalty functionality (colonyNetwork#845)
331+
sig = bytes4(keccak256("emitDomainReputationPenalty(uint256,uint256,uint256,address,int256)"));
332+
colonyAuthority.setRoleCapability(uint8(ColonyRole.Arbitration), address(this), sig, true);
333+
sig = bytes4(keccak256("emitSkillReputationPenalty(uint256,address,int256)"));
334+
colonyAuthority.setRoleCapability(uint8(ColonyRole.Arbitration), address(this), sig, true);
313335
}
314336

315337
function checkNotAdditionalProtectedVariable(uint256 _slot) public view recovery {

contracts/colony/ColonyAuthority.sol

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,10 @@ contract ColonyAuthority is CommonAuthority {
8585
addRoleCapability(ARBITRATION_ROLE, "setExpenditurePayoutModifier(uint256,uint256,uint256,uint256,int256)");
8686
addRoleCapability(ARBITRATION_ROLE, "setExpenditureClaimDelay(uint256,uint256,uint256,uint256,uint256)");
8787

88-
// Added in colony v5
88+
// Added in colony v5 (current version)
8989
addRoleCapability(ARBITRATION_ROLE, "transferStake(uint256,uint256,address,address,uint256,uint256,address)");
90+
addRoleCapability(ARBITRATION_ROLE, "emitDomainReputationPenalty(uint256,uint256,uint256,address,int256)");
91+
addRoleCapability(ARBITRATION_ROLE, "emitSkillReputationPenalty(uint256,address,int256)");
9092
}
9193

9294
function addRoleCapability(uint8 role, bytes memory sig) private {

contracts/colony/IColony.sol

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,26 @@ contract IColony is ColonyDataTypes, IRecovery {
127127
/// @return roles bytes32 representation of the roles
128128
function getUserRoles(address who, uint256 where) public view returns (bytes32 roles);
129129

130+
/// @notice Emit a negative domain reputation update. Available only to Arbitration role holders
131+
/// @param _permissionDomainId The domainId in which I hold the Arbitration role
132+
/// @param _childSkillIndex The index that the `_domainId` is relative to `_permissionDomainId`
133+
/// @param _domainId The domain where the user will lose reputation
134+
/// @param _user The user who will lose reputation
135+
/// @param _amount The (negative) amount of reputation to lose
136+
function emitDomainReputationPenalty(
137+
uint256 _permissionDomainId,
138+
uint256 _childSkillIndex,
139+
uint256 _domainId,
140+
address _user,
141+
int256 _amount
142+
) public;
143+
144+
/// @notice Emit a negative skill reputation update. Available only to Arbitration role holders in the root domain
145+
/// @param _skillId The skill where the user will lose reputation
146+
/// @param _user The user who will lose reputation
147+
/// @param _amount The (negative) amount of reputation to lose
148+
function emitSkillReputationPenalty(uint256 _skillId, address _user, int256 _amount) public;
149+
130150
/// @notice Called once when the colony is created to initialise certain storage slot values.
131151
/// @dev Sets the reward inverse to the uint max 2**256 - 1.
132152
/// @param _colonyNetworkAddress Address of the colony network

docs/_Interface_IColony.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,36 @@ Deobligate the user some amount of tokens, releasing the stake.
206206
|_amount|uint256|Amount of internal token we are deobligating.
207207

208208

209+
### `emitDomainReputationPenalty`
210+
211+
Emit a negative domain reputation update. Available only to Arbitration role holders
212+
213+
214+
**Parameters**
215+
216+
|Name|Type|Description|
217+
|---|---|---|
218+
|_permissionDomainId|uint256|The domainId in which I hold the Arbitration role
219+
|_childSkillIndex|uint256|The index that the `_domainId` is relative to `_permissionDomainId`
220+
|_domainId|uint256|The domain where the user will lose reputation
221+
|_user|address|The user who will lose reputation
222+
|_amount|int256|The (negative) amount of reputation to lose
223+
224+
225+
### `emitSkillReputationPenalty`
226+
227+
Emit a negative skill reputation update. Available only to Arbitration role holders in the root domain
228+
229+
230+
**Parameters**
231+
232+
|Name|Type|Description|
233+
|---|---|---|
234+
|_skillId|uint256|The skill where the user will lose reputation
235+
|_user|address|The user who will lose reputation
236+
|_amount|int256|The (negative) amount of reputation to lose
237+
238+
209239
### `executeTaskChange`
210240

211241
Executes a task update transaction `_data` which is approved and signed by two of its roles (e.g. manager and worker) using the detached signatures for these users.

test/contracts-network/colony-permissions.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
ADMINISTRATION_ROLE,
1313
INITIAL_FUNDING,
1414
SPECIFICATION_HASH,
15+
GLOBAL_SKILL_ID,
1516
} from "../../helpers/constants";
1617

1718
import { fundColonyWithTokens, makeTask, setupRandomColony } from "../../helpers/test-data-generator";
@@ -278,6 +279,20 @@ contract("ColonyPermissions", (accounts) => {
278279
await colony.setAdministrationRole(1, 1, USER2, 3, true, { from: USER1 });
279280
});
280281

282+
it("should allow users with arbitration permission to emit negative reputation penalties", async () => {
283+
await colony.setArbitrationRole(1, UINT256_MAX, USER1, 1, true);
284+
await colony.setArbitrationRole(1, 0, USER2, 2, true);
285+
286+
// Domain penalties
287+
await colony.emitDomainReputationPenalty(1, 1, 3, USER2, -100, { from: USER1 });
288+
await checkErrorRevert(colony.emitDomainReputationPenalty(1, 1, 3, USER2, 100, { from: USER1 }), "colony-penalty-cannot-be-positive");
289+
290+
// Skill penalties (root domain only)
291+
await colony.emitSkillReputationPenalty(GLOBAL_SKILL_ID, USER2, -100, { from: USER1 });
292+
await checkErrorRevert(colony.emitSkillReputationPenalty(GLOBAL_SKILL_ID, USER2, 100, { from: USER1 }), "colony-penalty-cannot-be-positive");
293+
await checkErrorRevert(colony.emitSkillReputationPenalty(GLOBAL_SKILL_ID, USER2, -100, { from: USER2 }), "ds-auth-unauthorized");
294+
});
295+
281296
it("should allow permissions to propagate to subdomains", async () => {
282297
// Give User 2 funding permissions in domain 1
283298
await colony.setFundingRole(1, UINT256_MAX, USER2, 1, true);

0 commit comments

Comments
 (0)