Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
57 changes: 0 additions & 57 deletions contracts/colony/ColonyExpenditure.sol
Original file line number Diff line number Diff line change
Expand Up @@ -236,37 +236,6 @@ 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,
Expand Down Expand Up @@ -377,32 +346,6 @@ 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
28 changes: 0 additions & 28 deletions contracts/colony/IColony.sol
Original file line number Diff line number Diff line change
Expand Up @@ -622,34 +622,6 @@ interface IColony is ColonyDataTypes, IRecovery, IBasicMetaTransaction, IMultica
int256[] memory _payoutModifiers
) external;

/// @notice Set many values of an expenditure simultaneously. Can only be called by expenditure owner.
/// @param _id Expenditure identifier
/// @param _recipientSlots Array of slots to set recipients
/// @param _recipients Addresses of the recipients
/// @param _skillIdSlots Array of slots to set skills
/// @param _skillIds Ids of the new skills to set
/// @param _claimDelaySlots Array of slots to set claim delays
/// @param _claimDelays Durations of time (in seconds) to delay
/// @param _payoutModifierSlots Array of slots to set payout modifiers
/// @param _payoutModifiers Values (between +/- WAD) to modify the payout & reputation bonus
/// @param _payoutTokens Addresses of the tokens, `0x0` value indicates Ether
/// @param _payoutSlots 2-dimensional array of slots to set payouts
/// @param _payoutValues 2-dimensional array of the payout amounts
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
) external;

/// @notice Set arbitrary state on an expenditure slot. Can only be called by Arbitration role.
/// @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 Down
5 changes: 4 additions & 1 deletion contracts/common/MetaTransactionMsgSender.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@ import { DSMath } from "../../lib/dappsys/math.sol";

abstract contract MetaTransactionMsgSender is DSMath {
bytes32 constant METATRANSACTION_FLAG = keccak256("METATRANSACTION");
uint256 constant METATRANSACTION_DATA_MIN_LENGTH = 32 + 20;
// Where 32 is the length of METATRANSACTION_FLAG in bytes
// Where 20 is the length of an address in bytes

function msgSender() internal view returns (address payable sender) {
uint256 index = msg.data.length;
if (msg.sender == address(this) && index >= 52) {
if (msg.sender == address(this) && index >= METATRANSACTION_DATA_MIN_LENGTH) {
bytes memory array = msg.data;
bytes32 flag;
assembly {
Expand Down
23 changes: 0 additions & 23 deletions docs/interfaces/icolony.md
Original file line number Diff line number Diff line change
Expand Up @@ -1422,29 +1422,6 @@ Set arbitrary state on an expenditure slot. Can only be called by Arbitration ro
|_value|bytes32|Value to set at location


### ▸ `setExpenditureValues(uint256 _id, uint256[] memory _recipientSlots, address[] memory _recipients, uint256[] memory _skillIdSlots, uint256[] memory _skillIds, uint256[] memory _claimDelaySlots, uint256[] memory _claimDelays, uint256[] memory _payoutModifierSlots, int256[] memory _payoutModifiers, address[] memory _payoutTokens, undefined[] memory _payoutSlots, undefined[] memory _payoutValues)`

Set many values of an expenditure simultaneously. Can only be called by expenditure owner.


**Parameters**

|Name|Type|Description|
|---|---|---|
|_id|uint256|Expenditure identifier
|_recipientSlots|uint256[]|Array of slots to set recipients
|_recipients|address[]|Addresses of the recipients
|_skillIdSlots|uint256[]|Array of slots to set skills
|_skillIds|uint256[]|Ids of the new skills to set
|_claimDelaySlots|uint256[]|Array of slots to set claim delays
|_claimDelays|uint256[]|Durations of time (in seconds) to delay
|_payoutModifierSlots|uint256[]|Array of slots to set payout modifiers
|_payoutModifiers|int256[]|Values (between +/- WAD) to modify the payout & reputation bonus
|_payoutTokens|address[]|Addresses of the tokens, `0x0` value indicates Ether
|_payoutSlots|undefined[]|2-dimensional array of slots to set payouts
|_payoutValues|undefined[]|2-dimensional array of the payout amounts


### ▸ `setFundingRole(uint256 _permissionDomainId, uint256 _childSkillIndex, address _user, uint256 _domainId, bool _setTo)`

Set new colony funding role. Can be called by root role or architecture role.
Expand Down
159 changes: 0 additions & 159 deletions test/contracts-network/colony-expenditure.js
Original file line number Diff line number Diff line change
Expand Up @@ -500,165 +500,6 @@ contract("Colony Expenditure", (accounts) => {
it("should not allow non-owners to set a payout", async () => {
await checkErrorRevert(colony.setExpenditurePayout(expenditureId, SLOT0, token.address, WAD, { from: USER }), "colony-expenditure-not-owner");
});

it("should allow owners to update many values simultaneously", async () => {
await colony.setExpenditureValues(
expenditureId,
[SLOT0, SLOT1, SLOT2],
[RECIPIENT, USER, ADMIN],
[SLOT1, SLOT2],
[localSkillId, localSkillId],
[SLOT0, SLOT1],
[10, 20],
[SLOT0, SLOT2],
[WAD.divn(3), WAD.divn(2)],
[token.address, otherToken.address],
[
[SLOT0, SLOT1],
[SLOT1, SLOT2],
],
[
[WAD.muln(10), WAD.muln(20)],
[WAD.muln(30), WAD.muln(40)],
],
{ from: ADMIN },
);

let slot;
slot = await colony.getExpenditureSlot(expenditureId, SLOT0);
expect(slot.recipient).to.equal(RECIPIENT);
expect(slot.skills[0]).to.be.zero;
expect(slot.claimDelay).to.eq.BN(10);
expect(slot.payoutModifier).to.eq.BN(WAD.divn(3));

slot = await colony.getExpenditureSlot(expenditureId, SLOT1);
expect(slot.recipient).to.equal(USER);
expect(slot.skills[0]).to.eq.BN(localSkillId);
expect(slot.claimDelay).to.eq.BN(20);
expect(slot.payoutModifier).to.be.zero;

slot = await colony.getExpenditureSlot(expenditureId, SLOT2);
expect(slot.recipient).to.equal(ADMIN);
expect(slot.skills[0]).to.eq.BN(localSkillId);
expect(slot.claimDelay).to.be.zero;
expect(slot.payoutModifier).to.eq.BN(WAD.divn(2));

let payout;
payout = await colony.getExpenditureSlotPayout(expenditureId, SLOT0, token.address);
expect(payout).to.eq.BN(WAD.muln(10));
payout = await colony.getExpenditureSlotPayout(expenditureId, SLOT1, token.address);
expect(payout).to.eq.BN(WAD.muln(20));
payout = await colony.getExpenditureSlotPayout(expenditureId, SLOT2, token.address);
expect(payout).to.be.zero;

payout = await colony.getExpenditureSlotPayout(expenditureId, SLOT0, otherToken.address);
expect(payout).to.be.zero;
payout = await colony.getExpenditureSlotPayout(expenditureId, SLOT1, otherToken.address);
expect(payout).to.eq.BN(WAD.muln(30));
payout = await colony.getExpenditureSlotPayout(expenditureId, SLOT2, otherToken.address);
expect(payout).to.eq.BN(WAD.muln(40));
});

it("should revert with an error even if the delegatecall in setExpenditurePayouts is used and fails", async () => {
await checkErrorRevert(
colony.setExpenditureValues(
expenditureId,
[SLOT0, SLOT1, SLOT2],
[RECIPIENT, USER, ADMIN],
[SLOT1, SLOT2],
[localSkillId, localSkillId],
[SLOT0, SLOT1],
[10, 20],
[SLOT0, SLOT2],
[WAD.divn(3), WAD.divn(2)],
[token.address, otherToken.address],
[[SLOT0], [SLOT1, SLOT2]],
[
[WAD.muln(10), WAD.muln(20)],
[WAD.muln(30), WAD.muln(40)],
],
{ from: ADMIN },
),
"colony-expenditure-bad-slots",
);
});

it("should not allow owners to update many values simultaneously if not owner", async () => {
await checkErrorRevert(
colony.setExpenditureValues(expenditureId, [], [], [], [], [], [], [], [], [], [[], []], [[], []], { from: USER }),
"colony-expenditure-not-owner",
);
});

it("should not allow owners to update many values simultaneously if not in draft", async () => {
await colony.cancelExpenditure(expenditureId, { from: ADMIN });

await checkErrorRevert(
colony.setExpenditureValues(expenditureId, [], [], [], [], [], [], [], [], [], [[], []], [[], []], { from: ADMIN }),
"colony-expenditure-not-draft",
);
});

it("will not update values if empty arrays are passed", async () => {
await colony.setExpenditureValues(
expenditureId,
[SLOT0, SLOT1, SLOT2],
[RECIPIENT, USER, ADMIN],
[SLOT1, SLOT2],
[localSkillId, localSkillId],
[SLOT0, SLOT1],
[10, 20],
[SLOT0, SLOT2],
[WAD.divn(3), WAD.divn(2)],
[token.address, otherToken.address],
[
[SLOT0, SLOT1],
[SLOT1, SLOT2],
],
[
[WAD.muln(10), WAD.muln(20)],
[WAD.muln(30), WAD.muln(40)],
],
{ from: ADMIN },
);

// This call has no effect
await colony.setExpenditureValues(expenditureId, [], [], [], [], [], [], [], [], [], [[], []], [[], []], { from: ADMIN });

let slot;
slot = await colony.getExpenditureSlot(expenditureId, SLOT0);
expect(slot.recipient).to.equal(RECIPIENT);
expect(slot.skills[0]).to.be.zero;
expect(slot.claimDelay).to.eq.BN(10);
expect(slot.payoutModifier).to.eq.BN(WAD.divn(3));

slot = await colony.getExpenditureSlot(expenditureId, SLOT1);
expect(slot.recipient).to.equal(USER);
expect(slot.skills[0]).to.eq.BN(localSkillId);
expect(slot.claimDelay).to.eq.BN(20);
expect(slot.payoutModifier).to.be.zero;

slot = await colony.getExpenditureSlot(expenditureId, SLOT2);
expect(slot.recipient).to.equal(ADMIN);
expect(slot.skills[0]).to.eq.BN(localSkillId);
expect(slot.claimDelay).to.be.zero;
expect(slot.payoutModifier).to.eq.BN(WAD.divn(2));

let payout;
payout = await colony.getExpenditureSlotPayout(expenditureId, SLOT0, token.address);
expect(payout).to.eq.BN(WAD.muln(10));
payout = await colony.getExpenditureSlotPayout(expenditureId, SLOT1, token.address);
expect(payout).to.eq.BN(WAD.muln(20));
payout = await colony.getExpenditureSlotPayout(expenditureId, SLOT2, token.address);
expect(payout).to.be.zero;

payout = await colony.getExpenditureSlotPayout(expenditureId, SLOT0, otherToken.address);
expect(payout).to.be.zero;
payout = await colony.getExpenditureSlotPayout(expenditureId, SLOT1, otherToken.address);
expect(payout).to.eq.BN(WAD.muln(30));
payout = await colony.getExpenditureSlotPayout(expenditureId, SLOT2, otherToken.address);
expect(payout).to.eq.BN(WAD.muln(40));
});
});

describe("when locking expenditures", () => {
Expand Down
1 change: 0 additions & 1 deletion test/contracts-network/colony-recovery.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,6 @@ contract("Colony Recovery", (accounts) => {
await checkErrorRevert(metaColony.setExpenditureRecipient(0, 0, ADDRESS_ZERO), "colony-in-recovery-mode");
await checkErrorRevert(metaColony.setExpenditureClaimDelay(0, 0, 0), "colony-in-recovery-mode");
await checkErrorRevert(metaColony.setExpenditureState(0, 0, 0, 0, [], [], HASHZERO), "colony-in-recovery-mode");
await checkErrorRevert(metaColony.setExpenditureValues(0, [], [], [], [], [], [], [], [], [], [[]], [[]]), "colony-in-recovery-mode");
await checkErrorRevert(metaColony.setArbitrationRole(0, 0, ADDRESS_ZERO, 0, true), "colony-in-recovery-mode");
await checkErrorRevert(metaColony.setArchitectureRole(0, 0, ADDRESS_ZERO, 0, true), "colony-in-recovery-mode");
await checkErrorRevert(metaColony.setFundingRole(0, 0, ADDRESS_ZERO, 0, true), "colony-in-recovery-mode");
Expand Down