From 78cc1a6ba7521adc772579d16bc59c3d6ae8a466 Mon Sep 17 00:00:00 2001 From: Marcin Chrzanowski Date: Fri, 23 Aug 2024 14:44:26 +0200 Subject: [PATCH 01/19] Set up mocking for payment sending --- .../contracts-0.8/common/EpochManager.sol | 4 ++ .../common/interfaces/IStableToken.sol | 2 + .../common/mocks/EpochManager_WithMocks.sol | 10 +++ .../common/mocks/MockAccounts.sol | 34 +++++++++++ .../governance/test/IMockValidators.sol | 61 +++++++++++++++++++ .../governance/test/MockValidators.sol | 16 +++++ .../test-sol/unit/common/EpochManager.t.sol | 9 ++- 7 files changed, 133 insertions(+), 3 deletions(-) create mode 100644 packages/protocol/contracts-0.8/common/mocks/EpochManager_WithMocks.sol create mode 100644 packages/protocol/contracts-0.8/common/mocks/MockAccounts.sol create mode 100644 packages/protocol/contracts/governance/test/IMockValidators.sol diff --git a/packages/protocol/contracts-0.8/common/EpochManager.sol b/packages/protocol/contracts-0.8/common/EpochManager.sol index 83191eb8842..58ec34ab9f3 100644 --- a/packages/protocol/contracts-0.8/common/EpochManager.sol +++ b/packages/protocol/contracts-0.8/common/EpochManager.sol @@ -318,4 +318,8 @@ contract EpochManager is CELOequivalent ); } + + function sendValidatorPayment(address validator) external { + IStableToken(getStableToken()).transfer(validator, validatorPendingPayments[validator]); + } } diff --git a/packages/protocol/contracts-0.8/common/interfaces/IStableToken.sol b/packages/protocol/contracts-0.8/common/interfaces/IStableToken.sol index 8d5bd9cec00..1fa10340fec 100644 --- a/packages/protocol/contracts-0.8/common/interfaces/IStableToken.sol +++ b/packages/protocol/contracts-0.8/common/interfaces/IStableToken.sol @@ -6,6 +6,8 @@ pragma solidity >=0.8.7 <0.8.20; * absence of interface inheritance is intended as a companion to IERC20.sol and ICeloToken.sol. */ interface IStableToken { + function transfer(address, uint256) external returns (bool); + function mint(address, uint256) external returns (bool); function burn(uint256) external returns (bool); diff --git a/packages/protocol/contracts-0.8/common/mocks/EpochManager_WithMocks.sol b/packages/protocol/contracts-0.8/common/mocks/EpochManager_WithMocks.sol new file mode 100644 index 00000000000..9ddda4aba92 --- /dev/null +++ b/packages/protocol/contracts-0.8/common/mocks/EpochManager_WithMocks.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity >=0.8.7 <0.8.20; + +import "../EpochManager.sol"; + +contract EpochManager_WithMocks is EpochManager(true) { + function _setPaymentAllocation(address validator, uint256 amount) external { + validatorPendingPayments[validator] = amount; + } +} diff --git a/packages/protocol/contracts-0.8/common/mocks/MockAccounts.sol b/packages/protocol/contracts-0.8/common/mocks/MockAccounts.sol new file mode 100644 index 00000000000..7e1c1669bc4 --- /dev/null +++ b/packages/protocol/contracts-0.8/common/mocks/MockAccounts.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity >=0.8.7 <0.8.20; + +import "@celo-contracts/common/FixidityLib.sol"; + +contract MockAccounts { + using FixidityLib for FixidityLib.Fraction; + + struct PaymentDelegation { + // Address that should receive a fraction of validator payments. + address beneficiary; + // Fraction of payment to delegate to `beneficiary`. + FixidityLib.Fraction fraction; + } + + mapping(address => PaymentDelegation) delegations; + + function setPaymentDelegationFor( + address validator, + address beneficiary, + uint256 fraction + ) public { + delegations[validator] = PaymentDelegation(beneficiary, FixidityLib.wrap(fraction)); + } + + function deletePaymentDelegationFor(address validator) public { + delete delegations[validator]; + } + + function getPaymentDelegation(address account) external view returns (address, uint256) { + PaymentDelegation storage delegation = delegations[account]; + return (delegation.beneficiary, delegation.fraction.unwrap()); + } +} diff --git a/packages/protocol/contracts/governance/test/IMockValidators.sol b/packages/protocol/contracts/governance/test/IMockValidators.sol new file mode 100644 index 00000000000..c20e1b06cfd --- /dev/null +++ b/packages/protocol/contracts/governance/test/IMockValidators.sol @@ -0,0 +1,61 @@ +pragma solidity >=0.8.7 <0.8.20; + +interface IMockValidators { + function isValidator(address) external returns (bool); + function isValidatorGroup(address) external returns (bool); + + function updateEcdsaPublicKey(address, address, bytes calldata) external returns (bool); + + function updatePublicKeys( + address, + address, + bytes calldata, + bytes calldata, + bytes calldata + ) external returns (bool); + + function setValidator(address) external; + + function setValidatorGroup(address group) external; + + function affiliate(address group) external returns (bool); + + function setDoesNotMeetAccountLockedGoldRequirements(address account) external; + + function setNumRegisteredValidators(uint256 value) external; + + function setMembers(address group, address[] calldata _members) external; + + function setCommission(address group, uint256 commission) external; + + function setAccountLockedGoldRequirement(address account, uint256 value) external; + + function halveSlashingMultiplier(address) external; + + function forceDeaffiliateIfValidator(address validator) external; + + function getTopGroupValidators(address group, uint256 n) external view returns (address[] memory); + + function getValidatorGroup( + address + ) + external + view + returns (address[] memory, uint256, uint256, uint256, uint256[] memory, uint256, uint256); + + function getValidatorGroupSlashingMultiplier(address) external view returns (uint256); + + function meetsAccountLockedGoldRequirements(address account) external view returns (bool); + + function getNumRegisteredValidators() external view returns (uint256); + + function getAccountLockedGoldRequirement(address account) external view returns (uint256); + + function calculateGroupEpochScore(uint256[] calldata uptimes) external view returns (uint256); + + function getGroupsNumMembers(address[] calldata groups) external view returns (uint256[] memory); + + function groupMembershipInEpoch(address addr, uint256, uint256) external view returns (address); + + function getGroupNumMembers(address group) external view returns (uint256); +} diff --git a/packages/protocol/contracts/governance/test/MockValidators.sol b/packages/protocol/contracts/governance/test/MockValidators.sol index 97cf017a9a3..19a56ca7b65 100644 --- a/packages/protocol/contracts/governance/test/MockValidators.sol +++ b/packages/protocol/contracts/governance/test/MockValidators.sol @@ -19,6 +19,7 @@ contract MockValidators is IsL2Check { mapping(address => bool) private doesNotMeetAccountLockedGoldRequirements; mapping(address => address[]) private members; mapping(address => address) private affiliations; + mapping(address => uint256) private commissions; uint256 private numRegisteredValidators; function updateEcdsaPublicKey(address, address, bytes calldata) external returns (bool) { @@ -63,6 +64,10 @@ contract MockValidators is IsL2Check { members[group] = _members; } + function setCommission(address group, uint256 commission) external { + commissions[group] = commission; + } + function setAccountLockedGoldRequirement(address account, uint256 value) external { lockedGoldRequirements[account] = value; } @@ -87,6 +92,17 @@ contract MockValidators is IsL2Check { return validators; } + function getValidatorGroup( + address group + ) + external + view + returns (address[] memory, uint256, uint256, uint256, uint256[] memory, uint256, uint256) + { + uint256[] memory sizeHistory; + return (members[group], commissions[group], 0, 0, sizeHistory, 0, 0); + } + function getValidatorGroupSlashingMultiplier(address) external view returns (uint256) { allowOnlyL1(); return FIXED1_UINT; diff --git a/packages/protocol/test-sol/unit/common/EpochManager.t.sol b/packages/protocol/test-sol/unit/common/EpochManager.t.sol index d7078dd1000..9286c334192 100644 --- a/packages/protocol/test-sol/unit/common/EpochManager.t.sol +++ b/packages/protocol/test-sol/unit/common/EpochManager.t.sol @@ -2,7 +2,7 @@ pragma solidity >=0.8.7 <0.8.20; import "celo-foundry-8/Test.sol"; -import "@celo-contracts-8/common/EpochManager.sol"; +import "@celo-contracts-8/common/mocks/EpochManager_WithMocks.sol"; import "@celo-contracts-8/stability/test/MockStableToken.sol"; import "@celo-contracts-8/common/interfaces/ICeloToken.sol"; import "@celo-contracts-8/common/ScoreManager.sol"; @@ -16,11 +16,14 @@ import "@celo-contracts/stability/test/MockSortedOracles.sol"; import "@celo-contracts/common/interfaces/IRegistry.sol"; +import { IMockValidators } from "@celo-contracts/governance/test/IMockValidators.sol"; + import { EpochRewardsMock08 } from "@celo-contracts-8/governance/test/EpochRewardsMock.sol"; import { ValidatorsMock08 } from "@celo-contracts-8/governance/test/ValidatorsMock.sol"; +import { MockAccounts } from "@celo-contracts-8/common/mocks/MockAccounts.sol"; contract EpochManagerTest is Test, TestConstants, Utils08 { - EpochManager epochManager; + EpochManager_WithMocks epochManager; MockSortedOracles sortedOracles; MockStableToken08 stableToken; @@ -57,7 +60,7 @@ contract EpochManagerTest is Test, TestConstants, Utils08 { uint256 constant L2_INITIAL_STASH_BALANCE = FIFTEEN_YEAR_LINEAR_REWARD + MAX_L2_DISTRIBUTION; // leftover from L1 target supply plus the 2nd 15 year term. function setUp() public virtual { - epochManager = new EpochManager(true); + epochManager = new EpochManager_WithMocks(); sortedOracles = new MockSortedOracles(); epochRewards = new EpochRewardsMock08(); validators = new ValidatorsMock08(); From cb6eded8bfe97ec01efb0b02b418b33ebdccaa8d Mon Sep 17 00:00:00 2001 From: Marcin Chrzanowski Date: Fri, 23 Aug 2024 14:53:45 +0200 Subject: [PATCH 02/19] Set up basic test for sending payment --- .../test-sol/unit/common/EpochManager.t.sol | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/packages/protocol/test-sol/unit/common/EpochManager.t.sol b/packages/protocol/test-sol/unit/common/EpochManager.t.sol index 9286c334192..17400286869 100644 --- a/packages/protocol/test-sol/unit/common/EpochManager.t.sol +++ b/packages/protocol/test-sol/unit/common/EpochManager.t.sol @@ -165,3 +165,73 @@ contract EpochManagerTest_startNextEpochProcess is EpochManagerTest { epochManager.startNextEpochProcess(); } } + +contract EpochManagerTest_sendValidatorPayment is EpochManagerTest { + address group = actor("group"); + + address validator1 = actor("validator1"); + address validator2 = actor("validator2"); + address validator3 = actor("validator3"); + + uint256 paymentAmount = 4 ether; + uint256 quarterOfPayment = paymentAmount / 4; + uint256 halfOfPayment = paymentAmount / 2; + uint256 threeQuartersOfPayment = (paymentAmount / 4) * 3; + uint256 twentyFivePercent = 250000000000000000000000; + uint256 epochManagerBalanceBefore; + + // TODO: unify mocks + IMockValidators mockValidators = IMockValidators(actor("MockValidators05")); + + MockAccounts accounts; + + function setUp() public override { + super.setUp(); + + deployCodeTo("MockValidators.sol", abi.encode(false), address(mockValidators)); + registry.setAddressFor(ValidatorsContract, address(mockValidators)); + + accounts = new MockAccounts(); + registry.setAddressFor(AccountsContract, address(accounts)); + + mockValidators.setValidatorGroup(group); + mockValidators.setValidator(validator1); + mockValidators.setValidator(validator2); + mockValidators.setValidator(validator3); + + address[] memory members = new address[](3); + members[0] = validator1; + members[1] = validator2; + members[2] = validator3; + mockValidators.setMembers(group, members); + + stableToken.mint(address(epochManager), paymentAmount * 2); + epochManagerBalanceBefore = stableToken.balanceOf(address(epochManager)); + epochManager._setPaymentAllocation(validator1, paymentAmount); + epochManager._setPaymentAllocation(validator3, paymentAmount); + } + + function test_sendsCUsdFromEpochManagerToValidator() public { + epochManager.sendValidatorPayment(validator1); + + uint256 validatorBalanceAfter = stableToken.balanceOf(validator1); + uint256 epochManagerBalanceAfter = stableToken.balanceOf(address(epochManager)); + + assertEq(validatorBalanceAfter, paymentAmount); + assertEq(epochManagerBalanceAfter, epochManagerBalanceBefore - paymentAmount); + } + + function test_sendsCUsdFromEpochManagerToValidatorAndGroup() public {} + + function test_sendsCUsdFromEpochManagerToValidatorAndBeneficiary() public {} + + function test_sendsCUsdFromEpochManagerToValidatorAndGroupAndBeneficiary() public {} + + function test_sendsCUsdFromEpochManagerToValidatorAndGroupAndBeneficiary_whenAggregatedOverMultipleEpochs() + public + {} + + function test_worksWhenCalledByAnyone() public {} + + function test_doesNothingIfNotAllocated() public {} +} From 081328775b819143c6abf9beb0d2d64bcfb3f58c Mon Sep 17 00:00:00 2001 From: Marcin Chrzanowski Date: Fri, 23 Aug 2024 16:16:34 +0200 Subject: [PATCH 03/19] Send commission to group --- .../contracts-0.8/common/EpochManager.sol | 24 ++++++++++++++++++- .../governance/test/MockValidators.sol | 7 ++++++ .../test-sol/unit/common/EpochManager.t.sol | 14 ++++++++++- 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/packages/protocol/contracts-0.8/common/EpochManager.sol b/packages/protocol/contracts-0.8/common/EpochManager.sol index 58ec34ab9f3..56590b5f67c 100644 --- a/packages/protocol/contracts-0.8/common/EpochManager.sol +++ b/packages/protocol/contracts-0.8/common/EpochManager.sol @@ -9,6 +9,7 @@ import "./interfaces/IOracle.sol"; import "./interfaces/IStableToken.sol"; import "../common/UsingRegistry.sol"; +import "../../contracts/common/FixidityLib.sol"; import "../../contracts/common/Initializable.sol"; import "../../contracts/common/interfaces/ICeloVersionedContract.sol"; @@ -19,6 +20,8 @@ contract EpochManager is ReentrancyGuard, ICeloVersionedContract { + using FixidityLib for FixidityLib.Fraction; + struct Epoch { uint256 firstBlock; uint256 lastBlock; @@ -320,6 +323,25 @@ contract EpochManager is } function sendValidatorPayment(address validator) external { - IStableToken(getStableToken()).transfer(validator, validatorPendingPayments[validator]); + FixidityLib.Fraction memory paymentAmount = FixidityLib.newFixed( + validatorPendingPayments[validator] + ); + + IValidators validators = getValidators(); + address group = validators.getValidatorsGroup(validator); + (, uint256 commissionUnwrapped, , , , , ) = validators.getValidatorGroup(group); + FixidityLib.Fraction memory groupPortion = FixidityLib.newFixed(0); + if (commissionUnwrapped > 0) { + FixidityLib.Fraction memory commission = FixidityLib.wrap(commissionUnwrapped); + groupPortion = paymentAmount.multiply(commission); + } + + FixidityLib.Fraction memory validatorPortion = paymentAmount.subtract(groupPortion); + + IStableToken(getStableToken()).transfer(validator, validatorPortion.fromFixed()); + + if (groupPortion.unwrap() > 0) { + IStableToken(getStableToken()).transfer(group, groupPortion.fromFixed()); + } } } diff --git a/packages/protocol/contracts/governance/test/MockValidators.sol b/packages/protocol/contracts/governance/test/MockValidators.sol index 19a56ca7b65..be9dbd4de51 100644 --- a/packages/protocol/contracts/governance/test/MockValidators.sol +++ b/packages/protocol/contracts/governance/test/MockValidators.sol @@ -46,6 +46,10 @@ contract MockValidators is IsL2Check { isValidatorGroup[group] = true; } + function getValidatorsGroup(address validator) external returns (address) { + return affiliations[validator]; + } + function affiliate(address group) external returns (bool) { allowOnlyL1(); affiliations[msg.sender] = group; @@ -62,6 +66,9 @@ contract MockValidators is IsL2Check { function setMembers(address group, address[] calldata _members) external { members[group] = _members; + for (uint256 i; i < _members.length; i++) { + affiliations[_members[i]] = group; + } } function setCommission(address group, uint256 commission) external { diff --git a/packages/protocol/test-sol/unit/common/EpochManager.t.sol b/packages/protocol/test-sol/unit/common/EpochManager.t.sol index 17400286869..a1fc933a5cc 100644 --- a/packages/protocol/test-sol/unit/common/EpochManager.t.sol +++ b/packages/protocol/test-sol/unit/common/EpochManager.t.sol @@ -221,7 +221,19 @@ contract EpochManagerTest_sendValidatorPayment is EpochManagerTest { assertEq(epochManagerBalanceAfter, epochManagerBalanceBefore - paymentAmount); } - function test_sendsCUsdFromEpochManagerToValidatorAndGroup() public {} + function test_sendsCUsdFromEpochManagerToValidatorAndGroup() public { + mockValidators.setCommission(group, twentyFivePercent); + + epochManager.sendValidatorPayment(validator1); + + uint256 validatorBalanceAfter = stableToken.balanceOf(validator1); + uint256 groupBalanceAfter = stableToken.balanceOf(group); + uint256 epochManagerBalanceAfter = stableToken.balanceOf(address(epochManager)); + + assertEq(validatorBalanceAfter, threeQuartersOfPayment); + assertEq(groupBalanceAfter, quarterOfPayment); + assertEq(epochManagerBalanceAfter, epochManagerBalanceBefore - paymentAmount); + } function test_sendsCUsdFromEpochManagerToValidatorAndBeneficiary() public {} From a853665aa122f75755e9c0f61c37238b8187556d Mon Sep 17 00:00:00 2001 From: Marcin Chrzanowski Date: Fri, 23 Aug 2024 16:33:51 +0200 Subject: [PATCH 04/19] Send payment to beneficiary --- .../contracts-0.8/common/EpochManager.sol | 25 +++++++++++-------- .../test-sol/unit/common/EpochManager.t.sol | 16 +++++++++++- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/packages/protocol/contracts-0.8/common/EpochManager.sol b/packages/protocol/contracts-0.8/common/EpochManager.sol index 56590b5f67c..460834983e7 100644 --- a/packages/protocol/contracts-0.8/common/EpochManager.sol +++ b/packages/protocol/contracts-0.8/common/EpochManager.sol @@ -323,25 +323,30 @@ contract EpochManager is } function sendValidatorPayment(address validator) external { - FixidityLib.Fraction memory paymentAmount = FixidityLib.newFixed( + FixidityLib.Fraction memory totalPayment = FixidityLib.newFixed( validatorPendingPayments[validator] ); IValidators validators = getValidators(); address group = validators.getValidatorsGroup(validator); (, uint256 commissionUnwrapped, , , , , ) = validators.getValidatorGroup(group); - FixidityLib.Fraction memory groupPortion = FixidityLib.newFixed(0); - if (commissionUnwrapped > 0) { - FixidityLib.Fraction memory commission = FixidityLib.wrap(commissionUnwrapped); - groupPortion = paymentAmount.multiply(commission); - } - FixidityLib.Fraction memory validatorPortion = paymentAmount.subtract(groupPortion); + uint256 groupPayment = totalPayment.multiply(FixidityLib.wrap(commissionUnwrapped)).fromFixed(); + FixidityLib.Fraction memory remainingPayment = FixidityLib.newFixed( + totalPayment.fromFixed() - groupPayment + ); + (address beneficiary, uint256 fraction) = getAccounts().getPaymentDelegation(validator); + uint256 delegatedPayment = remainingPayment.multiply(FixidityLib.wrap(fraction)).fromFixed(); + uint256 validatorPayment = remainingPayment.fromFixed() - delegatedPayment; - IStableToken(getStableToken()).transfer(validator, validatorPortion.fromFixed()); + IStableToken stableToken = IStableToken(getStableToken()); - if (groupPortion.unwrap() > 0) { - IStableToken(getStableToken()).transfer(group, groupPortion.fromFixed()); + stableToken.transfer(validator, validatorPayment); + if (groupPayment > 0) { + stableToken.transfer(group, groupPayment); + } + if (delegatedPayment > 0) { + stableToken.transfer(beneficiary, delegatedPayment); } } } diff --git a/packages/protocol/test-sol/unit/common/EpochManager.t.sol b/packages/protocol/test-sol/unit/common/EpochManager.t.sol index a1fc933a5cc..47d7bade540 100644 --- a/packages/protocol/test-sol/unit/common/EpochManager.t.sol +++ b/packages/protocol/test-sol/unit/common/EpochManager.t.sol @@ -173,6 +173,8 @@ contract EpochManagerTest_sendValidatorPayment is EpochManagerTest { address validator2 = actor("validator2"); address validator3 = actor("validator3"); + address beneficiary = actor("beneficiary"); + uint256 paymentAmount = 4 ether; uint256 quarterOfPayment = paymentAmount / 4; uint256 halfOfPayment = paymentAmount / 2; @@ -235,7 +237,19 @@ contract EpochManagerTest_sendValidatorPayment is EpochManagerTest { assertEq(epochManagerBalanceAfter, epochManagerBalanceBefore - paymentAmount); } - function test_sendsCUsdFromEpochManagerToValidatorAndBeneficiary() public {} + function test_sendsCUsdFromEpochManagerToValidatorAndBeneficiary() public { + accounts.setPaymentDelegationFor(validator1, beneficiary, twentyFivePercent); + + epochManager.sendValidatorPayment(validator1); + + uint256 validatorBalanceAfter = stableToken.balanceOf(validator1); + uint256 beneficiaryBalanceAfter = stableToken.balanceOf(beneficiary); + uint256 epochManagerBalanceAfter = stableToken.balanceOf(address(epochManager)); + + assertEq(validatorBalanceAfter, threeQuartersOfPayment); + assertEq(beneficiaryBalanceAfter, quarterOfPayment); + assertEq(epochManagerBalanceAfter, epochManagerBalanceBefore - paymentAmount); + } function test_sendsCUsdFromEpochManagerToValidatorAndGroupAndBeneficiary() public {} From ee1eb4682db37b79148153dffdeb297bf7a9dde0 Mon Sep 17 00:00:00 2001 From: Marcin Chrzanowski Date: Fri, 23 Aug 2024 16:36:33 +0200 Subject: [PATCH 05/19] Remove unnecessary test case --- packages/protocol/test-sol/unit/common/EpochManager.t.sol | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/protocol/test-sol/unit/common/EpochManager.t.sol b/packages/protocol/test-sol/unit/common/EpochManager.t.sol index 47d7bade540..48aa6e4291e 100644 --- a/packages/protocol/test-sol/unit/common/EpochManager.t.sol +++ b/packages/protocol/test-sol/unit/common/EpochManager.t.sol @@ -253,10 +253,6 @@ contract EpochManagerTest_sendValidatorPayment is EpochManagerTest { function test_sendsCUsdFromEpochManagerToValidatorAndGroupAndBeneficiary() public {} - function test_sendsCUsdFromEpochManagerToValidatorAndGroupAndBeneficiary_whenAggregatedOverMultipleEpochs() - public - {} - function test_worksWhenCalledByAnyone() public {} function test_doesNothingIfNotAllocated() public {} From ff0c20b9b4cfc4cedb81a80514cdf363781e2568 Mon Sep 17 00:00:00 2001 From: Marcin Chrzanowski Date: Fri, 23 Aug 2024 16:50:28 +0200 Subject: [PATCH 06/19] Test sending to both group and beneficiary --- .../test-sol/unit/common/EpochManager.t.sol | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/packages/protocol/test-sol/unit/common/EpochManager.t.sol b/packages/protocol/test-sol/unit/common/EpochManager.t.sol index 48aa6e4291e..03f5d99b030 100644 --- a/packages/protocol/test-sol/unit/common/EpochManager.t.sol +++ b/packages/protocol/test-sol/unit/common/EpochManager.t.sol @@ -180,6 +180,7 @@ contract EpochManagerTest_sendValidatorPayment is EpochManagerTest { uint256 halfOfPayment = paymentAmount / 2; uint256 threeQuartersOfPayment = (paymentAmount / 4) * 3; uint256 twentyFivePercent = 250000000000000000000000; + uint256 fiftyPercent = 500000000000000000000000; uint256 epochManagerBalanceBefore; // TODO: unify mocks @@ -251,7 +252,22 @@ contract EpochManagerTest_sendValidatorPayment is EpochManagerTest { assertEq(epochManagerBalanceAfter, epochManagerBalanceBefore - paymentAmount); } - function test_sendsCUsdFromEpochManagerToValidatorAndGroupAndBeneficiary() public {} + function test_sendsCUsdFromEpochManagerToValidatorAndGroupAndBeneficiary() public { + mockValidators.setCommission(group, fiftyPercent); + accounts.setPaymentDelegationFor(validator1, beneficiary, fiftyPercent); + + epochManager.sendValidatorPayment(validator1); + + uint256 validatorBalanceAfter = stableToken.balanceOf(validator1); + uint256 groupBalanceAfter = stableToken.balanceOf(group); + uint256 beneficiaryBalanceAfter = stableToken.balanceOf(beneficiary); + uint256 epochManagerBalanceAfter = stableToken.balanceOf(address(epochManager)); + + assertEq(validatorBalanceAfter, quarterOfPayment); + assertEq(groupBalanceAfter, halfOfPayment); + assertEq(beneficiaryBalanceAfter, quarterOfPayment); + assertEq(epochManagerBalanceAfter, epochManagerBalanceBefore - paymentAmount); + } function test_worksWhenCalledByAnyone() public {} From 4d73b88ae6944ca5e5bcf3f60cb744c6a9510a68 Mon Sep 17 00:00:00 2001 From: Marcin Chrzanowski Date: Fri, 23 Aug 2024 16:52:06 +0200 Subject: [PATCH 07/19] Test when not allocated --- .../test-sol/unit/common/EpochManager.t.sol | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/packages/protocol/test-sol/unit/common/EpochManager.t.sol b/packages/protocol/test-sol/unit/common/EpochManager.t.sol index 03f5d99b030..54e5596f288 100644 --- a/packages/protocol/test-sol/unit/common/EpochManager.t.sol +++ b/packages/protocol/test-sol/unit/common/EpochManager.t.sol @@ -269,7 +269,20 @@ contract EpochManagerTest_sendValidatorPayment is EpochManagerTest { assertEq(epochManagerBalanceAfter, epochManagerBalanceBefore - paymentAmount); } - function test_worksWhenCalledByAnyone() public {} + function test_doesNothingIfNotAllocated() public { + mockValidators.setCommission(group, fiftyPercent); + accounts.setPaymentDelegationFor(validator2, beneficiary, fiftyPercent); + + epochManager.sendValidatorPayment(validator2); + + uint256 validatorBalanceAfter = stableToken.balanceOf(validator1); + uint256 groupBalanceAfter = stableToken.balanceOf(group); + uint256 beneficiaryBalanceAfter = stableToken.balanceOf(beneficiary); + uint256 epochManagerBalanceAfter = stableToken.balanceOf(address(epochManager)); - function test_doesNothingIfNotAllocated() public {} + assertEq(validatorBalanceAfter, 0); + assertEq(groupBalanceAfter, 0); + assertEq(beneficiaryBalanceAfter, 0); + assertEq(epochManagerBalanceAfter, epochManagerBalanceBefore); + } } From 54a10378aa564f7468ecbbde953f7e02cf3879b4 Mon Sep 17 00:00:00 2001 From: Marcin Chrzanowski Date: Fri, 23 Aug 2024 16:54:18 +0200 Subject: [PATCH 08/19] Cleanup test --- packages/protocol/test-sol/unit/common/EpochManager.t.sol | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/protocol/test-sol/unit/common/EpochManager.t.sol b/packages/protocol/test-sol/unit/common/EpochManager.t.sol index 54e5596f288..74cf7d02b8a 100644 --- a/packages/protocol/test-sol/unit/common/EpochManager.t.sol +++ b/packages/protocol/test-sol/unit/common/EpochManager.t.sol @@ -168,11 +168,8 @@ contract EpochManagerTest_startNextEpochProcess is EpochManagerTest { contract EpochManagerTest_sendValidatorPayment is EpochManagerTest { address group = actor("group"); - address validator1 = actor("validator1"); address validator2 = actor("validator2"); - address validator3 = actor("validator3"); - address beneficiary = actor("beneficiary"); uint256 paymentAmount = 4 ether; @@ -181,6 +178,7 @@ contract EpochManagerTest_sendValidatorPayment is EpochManagerTest { uint256 threeQuartersOfPayment = (paymentAmount / 4) * 3; uint256 twentyFivePercent = 250000000000000000000000; uint256 fiftyPercent = 500000000000000000000000; + uint256 epochManagerBalanceBefore; // TODO: unify mocks @@ -200,18 +198,15 @@ contract EpochManagerTest_sendValidatorPayment is EpochManagerTest { mockValidators.setValidatorGroup(group); mockValidators.setValidator(validator1); mockValidators.setValidator(validator2); - mockValidators.setValidator(validator3); address[] memory members = new address[](3); members[0] = validator1; members[1] = validator2; - members[2] = validator3; mockValidators.setMembers(group, members); stableToken.mint(address(epochManager), paymentAmount * 2); epochManagerBalanceBefore = stableToken.balanceOf(address(epochManager)); epochManager._setPaymentAllocation(validator1, paymentAmount); - epochManager._setPaymentAllocation(validator3, paymentAmount); } function test_sendsCUsdFromEpochManagerToValidator() public { From 195e718a799521fd070e68332e449b2e1be00df0 Mon Sep 17 00:00:00 2001 From: Marcin Chrzanowski Date: Sat, 24 Aug 2024 16:04:59 +0200 Subject: [PATCH 09/19] Check ERC-20 transfer return values --- packages/protocol/contracts-0.8/common/EpochManager.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/protocol/contracts-0.8/common/EpochManager.sol b/packages/protocol/contracts-0.8/common/EpochManager.sol index 460834983e7..12c193851e0 100644 --- a/packages/protocol/contracts-0.8/common/EpochManager.sol +++ b/packages/protocol/contracts-0.8/common/EpochManager.sol @@ -341,12 +341,12 @@ contract EpochManager is IStableToken stableToken = IStableToken(getStableToken()); - stableToken.transfer(validator, validatorPayment); + require(stableToken.transfer(validator, validatorPayment), "mint failed to validator"); if (groupPayment > 0) { - stableToken.transfer(group, groupPayment); + require(stableToken.transfer(group, groupPayment), "mint failed to validator group"); } if (delegatedPayment > 0) { - stableToken.transfer(beneficiary, delegatedPayment); + require(stableToken.transfer(beneficiary, delegatedPayment), "mint failed to delegatee"); } } } From e1beb8fd0a37a036aade3227a8ce00b2aa5a68be Mon Sep 17 00:00:00 2001 From: Marcin Chrzanowski Date: Sat, 24 Aug 2024 16:05:15 +0200 Subject: [PATCH 10/19] Emit an event on payment sent --- .../contracts-0.8/common/EpochManager.sol | 9 +++++++++ .../test-sol/unit/common/EpochManager.t.sol | 16 ++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/packages/protocol/contracts-0.8/common/EpochManager.sol b/packages/protocol/contracts-0.8/common/EpochManager.sol index 12c193851e0..3afd1f340ea 100644 --- a/packages/protocol/contracts-0.8/common/EpochManager.sol +++ b/packages/protocol/contracts-0.8/common/EpochManager.sol @@ -76,6 +76,13 @@ contract EpochManager is */ event EpochProcessingEnded(uint256 indexed epochNumber); + event ValidatorEpochPaymentDistributed( + address indexed validator, + uint256 validatorPayment, + address indexed group, + uint256 groupPayment + ); + modifier onlyEpochManagerInitializer() { require(msg.sender == epochManagerInitializer, "msg.sender is not Initializer"); _; @@ -348,5 +355,7 @@ contract EpochManager is if (delegatedPayment > 0) { require(stableToken.transfer(beneficiary, delegatedPayment), "mint failed to delegatee"); } + + emit ValidatorEpochPaymentDistributed(validator, validatorPayment, group, groupPayment); } } diff --git a/packages/protocol/test-sol/unit/common/EpochManager.t.sol b/packages/protocol/test-sol/unit/common/EpochManager.t.sol index 74cf7d02b8a..fa26b44f862 100644 --- a/packages/protocol/test-sol/unit/common/EpochManager.t.sol +++ b/packages/protocol/test-sol/unit/common/EpochManager.t.sol @@ -59,6 +59,13 @@ contract EpochManagerTest is Test, TestConstants, Utils08 { uint256 constant L2_INITIAL_STASH_BALANCE = FIFTEEN_YEAR_LINEAR_REWARD + MAX_L2_DISTRIBUTION; // leftover from L1 target supply plus the 2nd 15 year term. + event ValidatorEpochPaymentDistributed( + address indexed validator, + uint256 validatorPayment, + address indexed group, + uint256 groupPayment + ); + function setUp() public virtual { epochManager = new EpochManager_WithMocks(); sortedOracles = new MockSortedOracles(); @@ -264,6 +271,15 @@ contract EpochManagerTest_sendValidatorPayment is EpochManagerTest { assertEq(epochManagerBalanceAfter, epochManagerBalanceBefore - paymentAmount); } + function test_emitsAValidatorEpochPaymentDistributedEvent() public { + mockValidators.setCommission(group, fiftyPercent); + accounts.setPaymentDelegationFor(validator1, beneficiary, fiftyPercent); + + vm.expectEmit(true, true, true, true, address(epochManager)); + emit ValidatorEpochPaymentDistributed(validator1, quarterOfPayment, group, halfOfPayment); + epochManager.sendValidatorPayment(validator1); + } + function test_doesNothingIfNotAllocated() public { mockValidators.setCommission(group, fiftyPercent); accounts.setPaymentDelegationFor(validator2, beneficiary, fiftyPercent); From 771bdfb1ff51aa3e8f7a362f2b5f2619594dace3 Mon Sep 17 00:00:00 2001 From: Marcin Chrzanowski Date: Mon, 26 Aug 2024 19:55:12 +0200 Subject: [PATCH 11/19] Add natspecs --- .../protocol/contracts-0.8/common/EpochManager.sol | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/protocol/contracts-0.8/common/EpochManager.sol b/packages/protocol/contracts-0.8/common/EpochManager.sol index 3afd1f340ea..f0b7d4cedc4 100644 --- a/packages/protocol/contracts-0.8/common/EpochManager.sol +++ b/packages/protocol/contracts-0.8/common/EpochManager.sol @@ -76,6 +76,13 @@ contract EpochManager is */ event EpochProcessingEnded(uint256 indexed epochNumber); + /** + * @notice Emitted when an epoch payment is sent. + * @param validator Address of the validator. + * @param validatorPayment Amount of cUSD sent to the validator. + * @param group Address of the validator's group. + * @param groupPayment Amount of cUSD sent to the group. + */ event ValidatorEpochPaymentDistributed( address indexed validator, uint256 validatorPayment, @@ -329,6 +336,11 @@ contract EpochManager is ); } + /** + * @notice Sends the allocated epoch payment to a validator, their group, and + * delegation beneficiary. + * @param validator Address of the validator. + */ function sendValidatorPayment(address validator) external { FixidityLib.Fraction memory totalPayment = FixidityLib.newFixed( validatorPendingPayments[validator] From 8889bf3fcf4479b43ea8fa8a16bed762a3eb5a58 Mon Sep 17 00:00:00 2001 From: Marcin Chrzanowski Date: Mon, 26 Aug 2024 22:36:33 +0200 Subject: [PATCH 12/19] Get pending payment based on signer --- packages/protocol/contracts-0.8/common/EpochManager.sol | 7 +++++-- .../protocol/contracts-0.8/common/mocks/MockAccounts.sol | 9 +++++++++ .../protocol/test-sol/unit/common/EpochManager.t.sol | 6 +++++- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/packages/protocol/contracts-0.8/common/EpochManager.sol b/packages/protocol/contracts-0.8/common/EpochManager.sol index d8707d96a15..3641c6cc522 100644 --- a/packages/protocol/contracts-0.8/common/EpochManager.sol +++ b/packages/protocol/contracts-0.8/common/EpochManager.sol @@ -340,11 +340,14 @@ contract EpochManager is /** * @notice Sends the allocated epoch payment to a validator, their group, and * delegation beneficiary. - * @param validator Address of the validator. + * @param validator Account of the validator. */ function sendValidatorPayment(address validator) external { + IAccounts accounts = IAccounts(getAccounts()); + address signer = accounts.getValidatorSigner(validator); + FixidityLib.Fraction memory totalPayment = FixidityLib.newFixed( - validatorPendingPayments[validator] + validatorPendingPayments[signer] ); IValidators validators = getValidators(); diff --git a/packages/protocol/contracts-0.8/common/mocks/MockAccounts.sol b/packages/protocol/contracts-0.8/common/mocks/MockAccounts.sol index 7e1c1669bc4..a8439862cab 100644 --- a/packages/protocol/contracts-0.8/common/mocks/MockAccounts.sol +++ b/packages/protocol/contracts-0.8/common/mocks/MockAccounts.sol @@ -14,6 +14,7 @@ contract MockAccounts { } mapping(address => PaymentDelegation) delegations; + mapping(address => address) accountToSigner; function setPaymentDelegationFor( address validator, @@ -31,4 +32,12 @@ contract MockAccounts { PaymentDelegation storage delegation = delegations[account]; return (delegation.beneficiary, delegation.fraction.unwrap()); } + + function setValidatorSigner(address account, address signer) external { + accountToSigner[account] = signer; + } + + function getValidatorSigner(address account) external returns (address) { + return accountToSigner[account]; + } } diff --git a/packages/protocol/test-sol/unit/common/EpochManager.t.sol b/packages/protocol/test-sol/unit/common/EpochManager.t.sol index 50b24136176..5f8edd627ed 100644 --- a/packages/protocol/test-sol/unit/common/EpochManager.t.sol +++ b/packages/protocol/test-sol/unit/common/EpochManager.t.sol @@ -160,7 +160,9 @@ contract EpochManagerTest_startNextEpochProcess is EpochManagerTest { contract EpochManagerTest_sendValidatorPayment is EpochManagerTest { address group = actor("group"); address validator1 = actor("validator1"); + address signer1 = actor("signer1"); address validator2 = actor("validator2"); + address signer2 = actor("signer2"); address beneficiary = actor("beneficiary"); uint256 paymentAmount = 4 ether; @@ -188,7 +190,9 @@ contract EpochManagerTest_sendValidatorPayment is EpochManagerTest { mockValidators.setValidatorGroup(group); mockValidators.setValidator(validator1); + accounts.setValidatorSigner(validator1, signer1); mockValidators.setValidator(validator2); + accounts.setValidatorSigner(validator2, signer2); address[] memory members = new address[](3); members[0] = validator1; @@ -197,7 +201,7 @@ contract EpochManagerTest_sendValidatorPayment is EpochManagerTest { stableToken.mint(address(epochManager), paymentAmount * 2); epochManagerBalanceBefore = stableToken.balanceOf(address(epochManager)); - epochManager._setPaymentAllocation(validator1, paymentAmount); + epochManager._setPaymentAllocation(signer1, paymentAmount); } function test_sendsCUsdFromEpochManagerToValidator() public { From 78c53037a2f7b5d7e6d84fa9c6ba870674a0303f Mon Sep 17 00:00:00 2001 From: Marcin Chrzanowski Date: Mon, 26 Aug 2024 22:49:18 +0200 Subject: [PATCH 13/19] Use relative import --- packages/protocol/contracts-0.8/common/mocks/MockAccounts.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/protocol/contracts-0.8/common/mocks/MockAccounts.sol b/packages/protocol/contracts-0.8/common/mocks/MockAccounts.sol index a8439862cab..e7054bf39e8 100644 --- a/packages/protocol/contracts-0.8/common/mocks/MockAccounts.sol +++ b/packages/protocol/contracts-0.8/common/mocks/MockAccounts.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.7 <0.8.20; -import "@celo-contracts/common/FixidityLib.sol"; +import "../../../contracts/common/FixidityLib.sol"; contract MockAccounts { using FixidityLib for FixidityLib.Fraction; From e0493cff5773d7d9327e369ad9bb1aacabc42138 Mon Sep 17 00:00:00 2001 From: Marcin Chrzanowski Date: Tue, 27 Aug 2024 12:06:31 +0200 Subject: [PATCH 14/19] Move v8 interface to v8 directory --- .../governance/test/IMockValidators.sol | 0 packages/protocol/test-sol/unit/common/EpochManager.t.sol | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename packages/protocol/{contracts => contracts-0.8}/governance/test/IMockValidators.sol (100%) diff --git a/packages/protocol/contracts/governance/test/IMockValidators.sol b/packages/protocol/contracts-0.8/governance/test/IMockValidators.sol similarity index 100% rename from packages/protocol/contracts/governance/test/IMockValidators.sol rename to packages/protocol/contracts-0.8/governance/test/IMockValidators.sol diff --git a/packages/protocol/test-sol/unit/common/EpochManager.t.sol b/packages/protocol/test-sol/unit/common/EpochManager.t.sol index 5f8edd627ed..8bc508789ad 100644 --- a/packages/protocol/test-sol/unit/common/EpochManager.t.sol +++ b/packages/protocol/test-sol/unit/common/EpochManager.t.sol @@ -16,7 +16,7 @@ import "@celo-contracts/stability/test/MockSortedOracles.sol"; import "@celo-contracts/common/interfaces/IRegistry.sol"; -import { IMockValidators } from "@celo-contracts/governance/test/IMockValidators.sol"; +import { IMockValidators } from "@celo-contracts-8/governance/test/IMockValidators.sol"; import { EpochRewardsMock08 } from "@celo-contracts-8/governance/test/EpochRewardsMock.sol"; import { ValidatorsMock08 } from "@celo-contracts-8/governance/test/ValidatorsMock08.sol"; From 7da47c6e955125082cabec17c18ebc5e5d85c2d2 Mon Sep 17 00:00:00 2001 From: Marcin Chrzanowski Date: Fri, 30 Aug 2024 13:18:05 +0200 Subject: [PATCH 15/19] Correct mint to transfer --- packages/protocol/contracts-0.8/common/EpochManager.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/protocol/contracts-0.8/common/EpochManager.sol b/packages/protocol/contracts-0.8/common/EpochManager.sol index 3641c6cc522..bb341327a80 100644 --- a/packages/protocol/contracts-0.8/common/EpochManager.sol +++ b/packages/protocol/contracts-0.8/common/EpochManager.sol @@ -364,12 +364,12 @@ contract EpochManager is IStableToken stableToken = IStableToken(getStableToken()); - require(stableToken.transfer(validator, validatorPayment), "mint failed to validator"); + require(stableToken.transfer(validator, validatorPayment), "transfer failed to validator"); if (groupPayment > 0) { - require(stableToken.transfer(group, groupPayment), "mint failed to validator group"); + require(stableToken.transfer(group, groupPayment), "transfer failed to validator group"); } if (delegatedPayment > 0) { - require(stableToken.transfer(beneficiary, delegatedPayment), "mint failed to delegatee"); + require(stableToken.transfer(beneficiary, delegatedPayment), "transfer failed to delegatee"); } emit ValidatorEpochPaymentDistributed(validator, validatorPayment, group, groupPayment); From 624e34846566608a7489bd0863a31b684e1f9351 Mon Sep 17 00:00:00 2001 From: Marcin Chrzanowski Date: Fri, 30 Aug 2024 13:26:25 +0200 Subject: [PATCH 16/19] Add delegation info to event --- .../protocol/contracts-0.8/common/EpochManager.sol | 13 +++++++++++-- .../test-sol/unit/common/EpochManager.t.sol | 13 +++++++++++-- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/packages/protocol/contracts-0.8/common/EpochManager.sol b/packages/protocol/contracts-0.8/common/EpochManager.sol index bb341327a80..80767619bdd 100644 --- a/packages/protocol/contracts-0.8/common/EpochManager.sol +++ b/packages/protocol/contracts-0.8/common/EpochManager.sol @@ -87,7 +87,9 @@ contract EpochManager is address indexed validator, uint256 validatorPayment, address indexed group, - uint256 groupPayment + uint256 groupPayment, + address indexed beneficiary, + uint256 delegatedPayment ); modifier onlyEpochManagerInitializer() { @@ -372,6 +374,13 @@ contract EpochManager is require(stableToken.transfer(beneficiary, delegatedPayment), "transfer failed to delegatee"); } - emit ValidatorEpochPaymentDistributed(validator, validatorPayment, group, groupPayment); + emit ValidatorEpochPaymentDistributed( + validator, + validatorPayment, + group, + groupPayment, + beneficiary, + delegatedPayment + ); } } diff --git a/packages/protocol/test-sol/unit/common/EpochManager.t.sol b/packages/protocol/test-sol/unit/common/EpochManager.t.sol index 8bc508789ad..539e5de5eca 100644 --- a/packages/protocol/test-sol/unit/common/EpochManager.t.sol +++ b/packages/protocol/test-sol/unit/common/EpochManager.t.sol @@ -50,7 +50,9 @@ contract EpochManagerTest is Test, TestConstants, Utils08 { address indexed validator, uint256 validatorPayment, address indexed group, - uint256 groupPayment + uint256 groupPayment, + address indexed beneficiary, + uint256 delegatedPayment ); function setUp() public virtual { @@ -264,7 +266,14 @@ contract EpochManagerTest_sendValidatorPayment is EpochManagerTest { accounts.setPaymentDelegationFor(validator1, beneficiary, fiftyPercent); vm.expectEmit(true, true, true, true, address(epochManager)); - emit ValidatorEpochPaymentDistributed(validator1, quarterOfPayment, group, halfOfPayment); + emit ValidatorEpochPaymentDistributed( + validator1, + quarterOfPayment, + group, + halfOfPayment, + beneficiary, + quarterOfPayment + ); epochManager.sendValidatorPayment(validator1); } From 2a29cd1074481de458141aa368daaebdd3fa0cec Mon Sep 17 00:00:00 2001 From: Marcin Chrzanowski Date: Fri, 30 Aug 2024 13:38:53 +0200 Subject: [PATCH 17/19] Don't transfer to validator if payment is 0 --- packages/protocol/contracts-0.8/common/EpochManager.sol | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/protocol/contracts-0.8/common/EpochManager.sol b/packages/protocol/contracts-0.8/common/EpochManager.sol index 80767619bdd..a8d89f0a918 100644 --- a/packages/protocol/contracts-0.8/common/EpochManager.sol +++ b/packages/protocol/contracts-0.8/common/EpochManager.sol @@ -366,10 +366,14 @@ contract EpochManager is IStableToken stableToken = IStableToken(getStableToken()); - require(stableToken.transfer(validator, validatorPayment), "transfer failed to validator"); + if (validatorPayment > 0) { + require(stableToken.transfer(validator, validatorPayment), "transfer failed to validator"); + } + if (groupPayment > 0) { require(stableToken.transfer(group, groupPayment), "transfer failed to validator group"); } + if (delegatedPayment > 0) { require(stableToken.transfer(beneficiary, delegatedPayment), "transfer failed to delegatee"); } From 1a50a3feea14ebc290c046107c197ab6d90a167d Mon Sep 17 00:00:00 2001 From: Marcin Chrzanowski Date: Tue, 17 Sep 2024 16:34:46 +0200 Subject: [PATCH 18/19] Rename variable --- packages/protocol/contracts-0.8/common/EpochManager.sol | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/protocol/contracts-0.8/common/EpochManager.sol b/packages/protocol/contracts-0.8/common/EpochManager.sol index 875450df2ad..baf388104b3 100644 --- a/packages/protocol/contracts-0.8/common/EpochManager.sol +++ b/packages/protocol/contracts-0.8/common/EpochManager.sol @@ -374,8 +374,12 @@ contract EpochManager is FixidityLib.Fraction memory remainingPayment = FixidityLib.newFixed( totalPayment.fromFixed() - groupPayment ); - (address beneficiary, uint256 fraction) = getAccounts().getPaymentDelegation(validator); - uint256 delegatedPayment = remainingPayment.multiply(FixidityLib.wrap(fraction)).fromFixed(); + (address beneficiary, uint256 delegatedFraction) = getAccounts().getPaymentDelegation( + validator + ); + uint256 delegatedPayment = remainingPayment + .multiply(FixidityLib.wrap(delegatedFraction)) + .fromFixed(); uint256 validatorPayment = remainingPayment.fromFixed() - delegatedPayment; IStableToken stableToken = IStableToken(getStableToken()); From 34d8949168f827da3571a538ba40fb14e08f08a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Volpe?= Date: Tue, 17 Sep 2024 18:50:55 +0200 Subject: [PATCH 19/19] Trigger CI