Skip to content

Commit

Permalink
Merge pull request #644 from JoinColony/feat/voting
Browse files Browse the repository at this point in the history
Reputation Voting
  • Loading branch information
kronosapiens authored Sep 4, 2020
2 parents c1fe2e7 + 0d0a788 commit cfaf3d9
Show file tree
Hide file tree
Showing 15 changed files with 2,970 additions and 98 deletions.
8 changes: 6 additions & 2 deletions contracts/colony/Colony.sol
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,12 @@ contract Colony is ColonyStorage, PatriciaTreeProofs {
);
}

function getUserRoles(address who, uint256 where) public view returns (bytes32) {
return ColonyAuthority(address(authority)).getUserRoles(who, where);
function getUserRoles(address _user, uint256 _domainId) public view returns (bytes32) {
return ColonyAuthority(address(authority)).getUserRoles(_user, _domainId);
}

function getCapabilityRoles(bytes4 _sig) public view returns (bytes32) {
return ColonyAuthority(address(authority)).getCapabilityRoles(address(this), _sig);
}

function getColonyNetwork() public view returns (address) {
Expand Down
1 change: 1 addition & 0 deletions contracts/colony/ColonyDataTypes.sol
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ contract ColonyDataTypes {
uint256 fundingPotId;
uint256 domainId;
uint256 finalizedTimestamp;
uint256 globalClaimDelay;
}

struct ExpenditureSlot {
Expand Down
38 changes: 23 additions & 15 deletions contracts/colony/ColonyExpenditure.sol
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ contract ColonyExpenditure is ColonyStorage {
owner: msg.sender,
fundingPotId: fundingPotCount,
domainId: _domainId,
finalizedTimestamp: 0
finalizedTimestamp: 0,
globalClaimDelay: 0
});

emit FundingPotAdded(fundingPotCount);
Expand Down Expand Up @@ -144,6 +145,7 @@ contract ColonyExpenditure is ColonyStorage {
emit ExpenditureSkillSet(_id, _slot, _skillId);
}

// Deprecated
function setExpenditurePayoutModifier(
uint256 _permissionDomainId,
uint256 _childSkillIndex,
Expand All @@ -161,6 +163,7 @@ contract ColonyExpenditure is ColonyStorage {
expenditureSlots[_id][_slot].payoutModifier = _payoutModifier;
}

// Deprecated
function setExpenditureClaimDelay(
uint256 _permissionDomainId,
uint256 _childSkillIndex,
Expand All @@ -183,7 +186,7 @@ contract ColonyExpenditure is ColonyStorage {
uint256 _permissionDomainId,
uint256 _childSkillIndex,
uint256 _id,
uint256 _slot,
uint256 _storageSlot,
bool[] memory _mask,
bytes32[] memory _keys,
bytes32 _value
Expand All @@ -193,23 +196,28 @@ contract ColonyExpenditure is ColonyStorage {
expenditureExists(_id)
authDomain(_permissionDomainId, _childSkillIndex, expenditures[_id].domainId)
{
require(_keys.length > 0, "colony-expenditure-no-keys");

require(
_slot == EXPENDITURES_SLOT ||
_slot == EXPENDITURESLOTS_SLOT ||
_slot == EXPENDITURESLOTPAYOUTS_SLOT,
"colony-expenditure-bad-slot"
);

// Only allow editing expenditure status, owner, and finalizedTimestamp
// Note that status + owner occupy one slot
if (_slot == EXPENDITURES_SLOT) {
uint256 offset = uint256(_keys[_keys.length - 1]);
require(offset == 0 || offset == 3, "colony-expenditure-bad-offset");
if (_storageSlot == EXPENDITURES_SLOT) {
require(_keys.length == 1, "colony-expenditure-bad-keys");
uint256 offset = uint256(_keys[0]);
require(offset == 0 || offset == 3 || offset == 4, "colony-expenditure-bad-offset");

// Explicitly whitelist all slots, in case we add new slots in the future
} else if (_storageSlot == EXPENDITURESLOTS_SLOT) {
require(_keys.length >= 2, "colony-expenditure-bad-keys");
uint256 offset = uint256(_keys[1]);
require(offset <= 3, "colony-expenditure-bad-offset");

// Should always be two mappings
} else if (_storageSlot == EXPENDITURESLOTPAYOUTS_SLOT) {
require(_keys.length == 2, "colony-expenditure-bad-keys");

} else {
require(false, "colony-expenditure-bad-slot");
}

executeStateChange(keccak256(abi.encode(_id, _slot)), _mask, _keys, _value);
executeStateChange(keccak256(abi.encode(_id, _storageSlot)), _mask, _keys, _value);
}

// Public view functions
Expand Down
16 changes: 13 additions & 3 deletions contracts/colony/ColonyFunding.sol
Original file line number Diff line number Diff line change
Expand Up @@ -95,24 +95,34 @@ contract ColonyFunding is ColonyStorage, PatriciaTreeProofs { // ignore-swc-123
}
}

int256 constant MAX_PAYOUT_MODIFIER = int256(WAD);
int256 constant MIN_PAYOUT_MODIFIER = -int256(WAD);

function claimExpenditurePayout(uint256 _id, uint256 _slot, address _token) public
stoppable
expenditureExists(_id)
expenditureFinalized(_id)
{
Expenditure storage expenditure = expenditures[_id];
ExpenditureSlot storage slot = expenditureSlots[_id][_slot];
require(add(expenditure.finalizedTimestamp, slot.claimDelay) <= now, "colony-expenditure-cannot-claim");

require(
add(expenditure.finalizedTimestamp, add(expenditure.globalClaimDelay, slot.claimDelay)) <= now,
"colony-expenditure-cannot-claim"
);

FundingPot storage fundingPot = fundingPots[expenditure.fundingPotId];
assert(fundingPot.balance[_token] >= fundingPot.payouts[_token]);

uint256 initialPayout = expenditureSlotPayouts[_id][_slot][_token];
uint256 payoutScalar = uint256(slot.payoutModifier + int256(WAD));
delete expenditureSlotPayouts[_id][_slot][_token];

int256 payoutModifier = imin(imax(slot.payoutModifier, MIN_PAYOUT_MODIFIER), MAX_PAYOUT_MODIFIER);
uint256 payoutScalar = uint256(payoutModifier + int256(WAD));

uint256 repPayout = wmul(initialPayout, payoutScalar);
uint256 tokenPayout = min(initialPayout, repPayout);
uint256 tokenSurplus = sub(initialPayout, tokenPayout);
expenditureSlotPayouts[_id][_slot][_token] = 0;

// Process reputation updates if own token
if (_token == token) {
Expand Down
28 changes: 18 additions & 10 deletions contracts/colony/IColony.sol
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,15 @@ contract IColony is ColonyDataTypes, IRecovery {
public view returns (bool hasRole);

/// @notice Gets the bytes32 representation of the roles for a user in a given domain
/// @param who The user whose roles we want to get
/// @param where The domain where we want to get roles for
/// @return roles bytes32 representation of the roles
function getUserRoles(address who, uint256 where) public view returns (bytes32 roles);
/// @param _user The user whose roles we want to get
/// @param _domain The domain we want to get roles in
/// @return roles bytes32 representation of the held roles
function getUserRoles(address _user, uint256 _domain) public view returns (bytes32 roles);

/// @notice Gets the bytes32 representation of the roles authorized to call a function
/// @param _sig The function signature
/// @return roles bytes32 representation of the authorized roles
function getCapabilityRoles(bytes4 _sig) public view returns (bytes32 roles);

/// @notice Emit a negative domain reputation update. Available only to Arbitration role holders
/// @param _permissionDomainId The domainId in which I hold the Arbitration role
Expand Down Expand Up @@ -223,6 +228,7 @@ contract IColony is ColonyDataTypes, IRecovery {
function transferExpenditure(uint256 _id, address _newOwner) public;

/// @notice DEPRECATED Updates the expenditure owner. Can only be called by Arbitration role.
/// @dev This is now deprecated and will be removed in a future version
/// @param _permissionDomainId The domainId in which I have the permission to take this action
/// @param _childSkillIndex The index that the `_domainId` is relative to `_permissionDomainId`,
/// (only used if `_permissionDomainId` is different to `_domainId`)
Expand Down Expand Up @@ -257,7 +263,8 @@ contract IColony is ColonyDataTypes, IRecovery {
/// @param _skillId Id of the new skill to set
function setExpenditureSkill(uint256 _id, uint256 _slot, uint256 _skillId) public;

/// @notice Set the payout modifier on an expenditure slot. Can only be called by Arbitration role.
/// @notice DEPRECATED Set the payout modifier on an expenditure slot. Can only be called by Arbitration role.
/// @dev This is now deprecated and will be removed in a future version
/// @dev Note that when determining payouts the payoutModifier is incremented by WAD and converted into payoutScalar
/// @param _permissionDomainId The domainId in which I have the permission to take this action
/// @param _childSkillIndex The index that the `_domainId` is relative to `_permissionDomainId`,
Expand All @@ -273,7 +280,8 @@ contract IColony is ColonyDataTypes, IRecovery {
int256 _payoutModifier
) public;

/// @notice Set the claim delay on an expenditure slot. Can only be called by Arbitration role.
/// @notice DEPRECATED Set the claim delay on an expenditure slot. Can only be called by Arbitration role.
/// @dev This is now deprecated and will be removed in a future version
/// @param _permissionDomainId The domainId in which I have the permission to take this action
/// @param _childSkillIndex The index that the `_domainId` is relative to `_permissionDomainId`,
/// (only used if `_permissionDomainId` is different to `_domainId`)
Expand All @@ -293,15 +301,15 @@ contract IColony is ColonyDataTypes, IRecovery {
/// @param _childSkillIndex The index that the `_domainId` is relative to `_permissionDomainId`,
/// (only used if `_permissionDomainId` is different to `_domainId`)
/// @param _id Expenditure identifier
/// @param _slot Number of the top-level storage slot
/// @param _mask Array of booleans indicated whether a key is a mapping (F) or offset (T).
/// @param _keys Array of additional keys (mappings & offsets)
/// @param _storageSlot Number of the top-level storage slot (25, 26, or 27)
/// @param _mask Array of booleans indicated whether a key is a mapping (F) or an array index (T).
/// @param _keys Array of additional keys (for mappings & arrays)
/// @param _value Value to set at location
function setExpenditureState(
uint256 _permissionDomainId,
uint256 _childSkillIndex,
uint256 _id,
uint256 _slot,
uint256 _storageSlot,
bool[] memory _mask,
bytes32[] memory _keys,
bytes32 _value
Expand Down
Loading

0 comments on commit cfaf3d9

Please sign in to comment.