Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
ca731fd
Add a new setExpenditurePayouts
kronosapiens May 26, 2022
67ceb3e
Change implementation for updating expenditure payouts via arbitration
kronosapiens May 11, 2022
83891a4
Create ColonyRewards.sol, reorganize ColonyFunding, allow funding wit…
kronosapiens May 12, 2022
9fdf2b8
Add automatic refund functionality
kronosapiens May 13, 2022
039d804
Rename EvaluatedExpenditure to ExpenditureUtils, add staking function…
kronosapiens May 24, 2022
8bcb05b
Add setExpenditureValues
kronosapiens May 25, 2022
7de9f42
Add ability to slash expenditure stakes
kronosapiens May 25, 2022
4dbb0d9
Fix linting
kronosapiens May 25, 2022
f1abfbc
Fix coverage
area May 27, 2022
1fba336
Fix slither, eslint checks
area May 27, 2022
ea54988
Update test file to CommonJS
area May 27, 2022
5895d6e
Fix expenditure tests
kronosapiens May 27, 2022
855e92f
Update in response to review comments I
kronosapiens May 27, 2022
4721bff
Update smoke tests
kronosapiens Jun 2, 2022
4a07ff6
Update VotingReputation to handle setExpenditureStates
kronosapiens Jun 3, 2022
e87db1a
Burn stakes if transferred to address(0x0)
kronosapiens Jun 3, 2022
6eb642e
Update slashing implementation in tokenLocking
kronosapiens Jun 6, 2022
9e8e782
Add tests to improve coverage
kronosapiens Jun 6, 2022
30b40c0
Increase branch coverage on extension tests
area Jun 7, 2022
904a34d
Update in response to review feedback
kronosapiens Jun 9, 2022
f7b9d65
Update in response to review feedback II
kronosapiens Jun 10, 2022
8f52ded
Automatically cancel expenditure when stake is slashed
kronosapiens Jun 15, 2022
a1ef145
Update smoke tests
kronosapiens Jun 15, 2022
6be60d0
Remove ability to give variable rep penalty
kronosapiens Jun 17, 2022
b6c9a42
Update smoke tests
kronosapiens Jun 17, 2022
b2384d9
Combine slash and cancel into a single function
kronosapiens Jun 17, 2022
c0431a0
Allow cancelling an expenditure from any state
kronosapiens Jun 20, 2022
7a06fe6
Burn slashed stakes if possible
kronosapiens Jun 21, 2022
efc1aa2
Disallow cancelling expenditure from draft mode
kronosapiens Jun 21, 2022
38a40b6
Allow owner to cancel & recliam in one tx
kronosapiens Jun 21, 2022
1c36be2
Respond to review comments
kronosapiens Jun 22, 2022
21bc08f
Restore EvaluatedExpenditure
kronosapiens Jun 22, 2022
098e8fb
Rename ExpenditureUtils to StakedExpenditure
kronosapiens Jun 23, 2022
18592d2
Respond to review comments II
kronosapiens Jun 23, 2022
6ebbf3d
Update smoke tests
kronosapiens Jun 23, 2022
e4ef614
Satisfy slither
kronosapiens Jun 23, 2022
947637b
Add two events to StakedExpenditure
kronosapiens Jun 30, 2022
d66348e
Remove expenditureExists modifier
kronosapiens Jun 30, 2022
21f4b7f
Respond to review comments III
kronosapiens Jul 1, 2022
98b7979
Update yarn.lock
kronosapiens Jul 6, 2022
edbc338
Allow for setting multiple payouts in a single expenditure slot
kronosapiens Jul 5, 2022
e5c2908
Respond to review comments IV
kronosapiens Jul 8, 2022
d53ecb0
Update smoke tests
kronosapiens Jul 8, 2022
f03b5b6
Respond to review comments V
kronosapiens Jul 13, 2022
ad15861
Respond to review comments VI
kronosapiens Jul 14, 2022
cbee88f
Update smoke tests
kronosapiens Jul 15, 2022
fb49de4
Respond to review comments VII
kronosapiens Jul 15, 2022
2be192b
Update ExpenditureStateChanged event
kronosapiens Jul 19, 2022
4362e44
Improve no-op test
kronosapiens Jul 20, 2022
190a66a
Update yarn.lock
kronosapiens Jul 25, 2022
11d4e8c
Remove extraneous utility functions
kronosapiens Jul 21, 2022
96dc77d
Introduce setExpenditurePayout for arbitrators
kronosapiens Jul 27, 2022
60731d1
Don't bump version frivolously
kronosapiens Jul 27, 2022
7d61d43
Remove additional extraneous utility functions
kronosapiens Jul 27, 2022
1e9490f
Quieten smoke tests again
area Aug 1, 2022
3607f4c
Update smoke tests
kronosapiens Aug 1, 2022
fc62b9a
Remove special burn handling (for now)
kronosapiens Aug 1, 2022
4cff39d
Delegatecall to preserve msgSender()
area Aug 3, 2022
b79d9b1
Put abi encoding on own line for clarity
area Aug 4, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 4 additions & 7 deletions contracts/colony/Colony.sol
Original file line number Diff line number Diff line change
Expand Up @@ -309,14 +309,11 @@ contract Colony is BasicMetaTransaction, ColonyStorage, PatriciaTreeProofs {

// v9 to v10
function finishUpgrade() public always {
// Leaving in as an example of what this function usually does.

// ColonyAuthority colonyAuthority = ColonyAuthority(address(authority));
// bytes4 sig;

// sig = bytes4(keccak256("addLocalSkill()"));
// colonyAuthority.setRoleCapability(uint8(ColonyRole.Root), address(this), sig, true);
ColonyAuthority colonyAuthority = ColonyAuthority(address(authority));
bytes4 sig;

sig = bytes4(keccak256("setExpenditurePayout(uint256,uint256,uint256,uint256,address,uint256)"));
colonyAuthority.setRoleCapability(uint8(ColonyRole.Arbitration), address(this), sig, true);
}

function getMetatransactionNonce(address _user) override public view returns (uint256 nonce){
Expand Down
5 changes: 4 additions & 1 deletion contracts/colony/ColonyAuthority.sol
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,14 @@ contract ColonyAuthority is CommonAuthority {
addRoleCapability(ROOT_ROLE, "setDefaultGlobalClaimDelay(uint256)");
addRoleCapability(ARBITRATION_ROLE, "setExpenditureMetadata(uint256,uint256,uint256,string)");

// Added in colony v9 (f-lwss)
// Added in colony v9 (fuschia-lwss)
addRoleCapability(ROOT_ROLE, "addLocalSkill()");
addRoleCapability(ROOT_ROLE, "deprecateLocalSkill(uint256,bool)");
addRoleCapability(ARCHITECTURE_ROLE, "deprecateDomain(uint256,uint256,uint256,bool)");
addRoleCapability(ROOT_ROLE, "editColonyByDelta(string)");

// Added in colony v10 (ginger-lwss)
addRoleCapability(ARBITRATION_ROLE, "setExpenditurePayout(uint256,uint256,uint256,uint256,address,uint256)");
}

function addRoleCapability(uint8 role, bytes memory sig) private {
Expand Down
16 changes: 16 additions & 0 deletions contracts/colony/ColonyDataTypes.sol
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,22 @@ interface ColonyDataTypes {
/// @param payoutModifier The payout modifier for the slot
event ExpenditurePayoutModifierSet(address agent, uint256 indexed expenditureId, uint256 indexed slot, int256 payoutModifier);

/// @notice Event logged when an expenditure slot payout modifier changes
/// @param agent The address that is responsible for triggering this event
/// @param expenditureId Id of the expenditure
/// @param storageSlot Initial storage slot being set (expenditures or expenditureSlots)
/// @param mask Mask indicating whether we are making mapping or array operations
/// @param keys Values used to construct final slot via mapping or array operations
/// @param value Value being set in the slot
event ExpenditureStateChanged(
address agent,
uint256 indexed expenditureId,
uint256 indexed storageSlot,
bool[] mask,
bytes32[] keys,
bytes32 value
);

/// @notice Event logged when a new payment is added
/// @param agent The address that is responsible for triggering this event
/// @param paymentId The newly added payment id
Expand Down
72 changes: 54 additions & 18 deletions contracts/colony/ColonyExpenditure.sol
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ contract ColonyExpenditure is ColonyStorage {
function transferExpenditure(uint256 _id, address _newOwner)
public
stoppable
expenditureExists(_id)
expenditureDraftOrLocked(_id)
expenditureOnlyOwner(_id)
{
Expand All @@ -86,7 +85,6 @@ contract ColonyExpenditure is ColonyStorage {
)
public
stoppable
expenditureExists(_id)
expenditureDraftOrLocked(_id)
authDomain(_permissionDomainId, _childSkillIndex, expenditures[_id].domainId)
{
Expand All @@ -98,7 +96,6 @@ contract ColonyExpenditure is ColonyStorage {
function cancelExpenditure(uint256 _id)
public
stoppable
expenditureExists(_id)
expenditureDraft(_id)
expenditureOnlyOwner(_id)
{
Expand All @@ -110,7 +107,6 @@ contract ColonyExpenditure is ColonyStorage {
function lockExpenditure(uint256 _id)
public
stoppable
expenditureExists(_id)
expenditureDraft(_id)
expenditureOnlyOwner(_id)
{
Expand All @@ -122,7 +118,6 @@ contract ColonyExpenditure is ColonyStorage {
function finalizeExpenditure(uint256 _id)
public
stoppable
expenditureExists(_id)
expenditureDraftOrLocked(_id)
expenditureOnlyOwner(_id)
{
Expand All @@ -138,7 +133,6 @@ contract ColonyExpenditure is ColonyStorage {
function setExpenditureMetadata(uint256 _id, string memory _metadata)
public
stoppable
expenditureExists(_id)
expenditureDraft(_id)
expenditureOnlyOwner(_id)
{
Expand All @@ -153,7 +147,7 @@ contract ColonyExpenditure is ColonyStorage {
)
public
stoppable
expenditureExists(_id)
validExpenditure(_id)
authDomain(_permissionDomainId, _childSkillIndex, expenditures[_id].domainId)
{
emit ExpenditureMetadataSet(msgSender(), _id, _metadata);
Expand All @@ -162,7 +156,6 @@ contract ColonyExpenditure is ColonyStorage {
function setExpenditureRecipients(uint256 _id, uint256[] memory _slots, address payable[] memory _recipients)
public
stoppable
expenditureExists(_id)
expenditureDraft(_id)
expenditureOnlyOwner(_id)
{
Expand All @@ -178,7 +171,6 @@ contract ColonyExpenditure is ColonyStorage {
function setExpenditureSkills(uint256 _id, uint256[] memory _slots, uint256[] memory _skillIds)
public
stoppable
expenditureExists(_id)
expenditureDraft(_id)
expenditureOnlyOwner(_id)
{
Expand All @@ -201,7 +193,6 @@ contract ColonyExpenditure is ColonyStorage {
function setExpenditureClaimDelays(uint256 _id, uint256[] memory _slots, uint256[] memory _claimDelays)
public
stoppable
expenditureExists(_id)
expenditureDraft(_id)
expenditureOnlyOwner(_id)
{
Expand All @@ -217,7 +208,6 @@ contract ColonyExpenditure is ColonyStorage {
function setExpenditurePayoutModifiers(uint256 _id, uint256[] memory _slots, int256[] memory _payoutModifiers)
public
stoppable
expenditureExists(_id)
expenditureDraft(_id)
expenditureOnlyOwner(_id)
{
Expand All @@ -230,6 +220,32 @@ contract ColonyExpenditure is ColonyStorage {
}
}

function setExpenditureValues(
uint256 _id,
uint256[] memory _recipientSlots,
address payable[] memory _recipients,
uint256[] memory _skillIdSlots,
uint256[] memory _skillIds,
uint256[] memory _claimDelaySlots,
uint256[] memory _claimDelays,
uint256[] memory _payoutModifierSlots,
int256[] memory _payoutModifiers,
address[] memory _payoutTokens,
uint256[][] memory _payoutSlots,
uint256[][] memory _payoutValues
)
public
stoppable
expenditureDraft(_id)
expenditureOnlyOwner(_id)
{
if (_recipients.length > 0) { setExpenditureRecipients(_id, _recipientSlots, _recipients); }
if (_skillIds.length > 0) { setExpenditureSkills(_id, _skillIdSlots, _skillIds); }
if (_claimDelays.length > 0) { setExpenditureClaimDelays(_id, _claimDelaySlots, _claimDelays); }
if (_payoutModifiers.length > 0) { setExpenditurePayoutModifiers(_id, _payoutModifierSlots, _payoutModifiers); }
if (_payoutTokens.length > 0) { setExpenditurePayouts(_id, _payoutTokens, _payoutSlots, _payoutValues); }
}

// Deprecated
function setExpenditureRecipient(uint256 _id, uint256 _slot, address payable _recipient)
public
Expand Down Expand Up @@ -268,7 +284,6 @@ contract ColonyExpenditure is ColonyStorage {

uint256 constant EXPENDITURES_SLOT = 25;
uint256 constant EXPENDITURESLOTS_SLOT = 26;
uint256 constant EXPENDITURESLOTPAYOUTS_SLOT = 27;

function setExpenditureState(
uint256 _permissionDomainId,
Expand All @@ -281,10 +296,11 @@ contract ColonyExpenditure is ColonyStorage {
)
public
stoppable
expenditureExists(_id)
validExpenditure(_id)
authDomain(_permissionDomainId, _childSkillIndex, expenditures[_id].domainId)
{
// Only allow editing expenditure status, owner, and finalizedTimestamp
// Only allow editing expenditure status, owner, finalizedTimestamp, and globalClaimDelay
// Do not allow editing of fundingPotId or domainId
// Note that status + owner occupy one slot
if (_storageSlot == EXPENDITURES_SLOT) {
require(_keys.length == 1, "colony-expenditure-bad-keys");
Expand All @@ -306,15 +322,13 @@ contract ColonyExpenditure is ColonyStorage {
);
}

// 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, _storageSlot)), _mask, _keys, _value);

emit ExpenditureStateChanged(msgSender(), _id, _storageSlot, _mask, _keys, _value);
}

// Public view functions
Expand All @@ -337,6 +351,28 @@ contract ColonyExpenditure is ColonyStorage {

// Internal functions

// Used to avoid stack error in setExpenditureValues
function setExpenditurePayouts(
uint256 _id,
address[] memory _tokens,
uint256[][] memory _slots,
uint256[][] memory _values
)
internal
{
for (uint256 i; i < _tokens.length; i++) {
(bool success, bytes memory returndata) = address(this).delegatecall(
abi.encodeWithSignature("setExpenditurePayouts(uint256,uint256[],address,uint256[])", _id, _slots[i], _tokens[i], _values[i])
);
if (!success) {
if (returndata.length == 0) revert();
assembly {
revert(add(32, returndata), mload(returndata))
}
}
}
}

bool constant MAPPING = false;
bool constant ARRAY = true;
uint256 constant MAX_ARRAY = 1024; // Prevent writing arbitrary slots
Expand Down
60 changes: 48 additions & 12 deletions contracts/colony/ColonyFunding.sol
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ contract ColonyFunding is ColonyStorage { // ignore-swc-123

// Public

function moveFundsBetweenPots(
function moveFundsBetweenPots(
uint256 _permissionDomainId,
uint256 _childSkillIndex,
uint256 _domainId,
Expand All @@ -43,8 +43,8 @@ contract ColonyFunding is ColonyStorage { // ignore-swc-123
authDomain(_permissionDomainId, _childSkillIndex, _domainId)
validFundingTransfer(_fromPot, _toPot)
{
require(validateDomainInheritance(_domainId, _fromChildSkillIndex, getDomainFromFundingPot(_fromPot)), "colony-invalid-domain-inheritence");
require(validateDomainInheritance(_domainId, _toChildSkillIndex, getDomainFromFundingPot(_toPot)), "colony-invalid-domain-inheritence");
require(validateDomainInheritance(_domainId, _fromChildSkillIndex, getDomainFromFundingPot(_fromPot)), "colony-invalid-domain-inheritance");
require(validateDomainInheritance(_domainId, _toChildSkillIndex, getDomainFromFundingPot(_toPot)), "colony-invalid-domain-inheritance");

moveFundsBetweenPotsFunctionality(_fromPot, _toPot, _amount, _token);
}
Expand Down Expand Up @@ -138,33 +138,61 @@ contract ColonyFunding is ColonyStorage { // ignore-swc-123
}
}

function setExpenditurePayouts(uint256 _id, uint256[] memory _slots, address _token, uint256[] memory _amounts)
/// @notice For owners to update payouts with one token and many slots
function setExpenditurePayouts(
uint256 _id,
uint256[] memory _slots,
address _token,
uint256[] memory _amounts
)
public
stoppable
expenditureExists(_id)
expenditureDraft(_id)
expenditureOnlyOwner(_id)
{
setExpenditurePayoutsInternal(_id, _slots, _token, _amounts);
}

/// @notice For arbitrators to update payouts with one token and one slot
function setExpenditurePayout(
uint256 _permissionDomainId,
uint256 _childSkillIndex,
uint256 _id,
uint256 _slot,
address _token,
uint256 _amount
)
public
stoppable
validExpenditure(_id)
authDomain(_permissionDomainId, _childSkillIndex, expenditures[_id].domainId)
{
uint256[] memory slots = new uint256[](1);
slots[0] = _slot;
uint256[] memory amounts = new uint256[](1);
amounts[0] = _amount;
setExpenditurePayoutsInternal(_id, slots, _token, amounts);
}

/// @notice For owners to update payouts with one token and one slot
function setExpenditurePayout(uint256 _id, uint256 _slot, address _token, uint256 _amount)
public
stoppable
expenditureDraft(_id)
expenditureOnlyOwner(_id)
{
uint256[] memory slots = new uint256[](1);
slots[0] = _slot;
uint256[] memory amounts = new uint256[](1);
amounts[0] = _amount;
setExpenditurePayouts(_id, slots, _token, amounts);
setExpenditurePayoutsInternal(_id, slots, _token, amounts);
}

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];
Expand All @@ -188,12 +216,9 @@ contract ColonyFunding is ColonyStorage { // ignore-swc-123
uint256 tokenPayout = min(initialPayout, repPayout);
uint256 tokenSurplus = sub(initialPayout, tokenPayout);

// Send any surplus back to the domain (for payoutScalars < 1)
// Deduct any surplus from the outstanding payouts (for payoutScalars < 1)
if (tokenSurplus > 0) {
fundingPot.payouts[_token] = sub(fundingPot.payouts[_token], tokenSurplus);
fundingPot.balance[_token] = sub(fundingPot.balance[_token], tokenSurplus);
FundingPot storage domainFundingPot = fundingPots[domains[expenditure.domainId].fundingPotId];
domainFundingPot.balance[_token] = add(domainFundingPot.balance[_token], tokenSurplus);
}

// Process reputation updates if internal token
Expand Down Expand Up @@ -420,6 +445,8 @@ contract ColonyFunding is ColonyStorage { // ignore-swc-123
}

function processPayout(uint256 _fundingPotId, address _token, uint256 _payout, address payable _user) private {
refundDomain(_fundingPotId, _token);

IColonyNetwork colonyNetworkContract = IColonyNetwork(colonyNetworkAddress);
address payable metaColonyAddress = colonyNetworkContract.getMetaColony();

Expand Down Expand Up @@ -450,4 +477,13 @@ contract ColonyFunding is ColonyStorage { // ignore-swc-123

emit PayoutClaimed(msgSender(), _fundingPotId, _token, remainder);
}
}

function refundDomain(uint256 _fundingPotId, address _token) private {
FundingPot storage fundingPot = fundingPots[_fundingPotId];
if (fundingPot.payouts[_token] < fundingPot.balance[_token]) {
uint256 domainId = getDomainFromFundingPot(_fundingPotId);
uint256 surplus = sub(fundingPot.balance[_token], fundingPot.payouts[_token]);
moveFundsBetweenPotsFunctionality(_fundingPotId, domains[domainId].fundingPotId, surplus, _token);
}
}
}
2 changes: 1 addition & 1 deletion contracts/colony/ColonyRewards.sol
Original file line number Diff line number Diff line change
Expand Up @@ -205,4 +205,4 @@ contract ColonyRewards is ColonyStorage, PatriciaTreeProofs { // ignore-swc-123

return (payout.tokenAddress, reward);
}
}
}
Loading