Skip to content

Commit

Permalink
EpochManager use of transient variables (#11235)
Browse files Browse the repository at this point in the history
* Move to 0.8.25

* update celo-foundry-8

* electable validators to 110

* Gas optimization

* Build fix

* prettify

* yarn lint
  • Loading branch information
pahor167 authored Oct 7, 2024
1 parent 9127ba4 commit 3932eca
Show file tree
Hide file tree
Showing 139 changed files with 372 additions and 353 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,6 @@
path = packages/protocol/lib/solidity-bytes-utils-8
url = https://github.com/GNSPS/solidity-bytes-utils
branch = master
[submodule "packages/protocol/lib/transient-goodies"]
path = packages/protocol/lib/transient-goodies
url = https://github.com/Philogy/transient-goodies
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.7 <0.8.20;
pragma solidity >=0.8.7 <0.9;

import "@openzeppelin/contracts8/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts8/utils/math/Math.sol";
Expand Down
85 changes: 48 additions & 37 deletions packages/protocol/contracts-0.8/common/EpochManager.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.8.7 <0.8.20;
pragma solidity >=0.8.7 <0.9;

import "@openzeppelin/contracts8/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts8/security/ReentrancyGuard.sol";
Expand All @@ -13,6 +13,7 @@ import "../../contracts/common/Initializable.sol";
import "../../contracts/common/interfaces/IEpochManager.sol";
import "../../contracts/common/interfaces/ICeloVersionedContract.sol";
import "./interfaces/IEpochManagerInitializer.sol";
import { tuint256 } from "transient-goodies/TransientPrimitives.sol";

contract EpochManager is
Initializable,
Expand Down Expand Up @@ -44,10 +45,6 @@ contract EpochManager is
uint256 totalRewardsCarbonFund; // The total carbon offsetting partner reward.
}

struct ProcessedGroup {
bool processed;
uint256 epochRewards;
}
bool public isSystemInitialized;

// the length of an epoch in seconds
Expand All @@ -58,7 +55,7 @@ contract EpochManager is
address public oracleAddress;
address[] public elected;

mapping(address => ProcessedGroup) public processedGroups;
mapping(address => tuint256) public processedGroups;

EpochProcessState public epochProcessing;
mapping(uint256 => Epoch) private epochs;
Expand Down Expand Up @@ -219,47 +216,29 @@ contract EpochManager is
require(isOnEpochProcess(), "Epoch process is not started");
// finalize epoch
// last block should be the block before and timestamp from previous block
epochs[currentEpochNumber].lastBlock = block.number - 1;
uint256 currentEpoch = currentEpochNumber;
epochs[currentEpoch].lastBlock = block.number - 1;
// start new epoch
currentEpochNumber++;
epochs[currentEpochNumber].firstBlock = block.number;
epochs[currentEpochNumber].startTimestamp = block.timestamp;
currentEpoch++;
epochs[currentEpoch].firstBlock = block.number;
epochs[currentEpoch].startTimestamp = block.timestamp;
currentEpochNumber = currentEpoch;

EpochProcessState storage _epochProcessing = epochProcessing;

uint256 toProcessGroups = 0;
IValidators validators = getValidators();
IElection election = getElection();
IScoreReader scoreReader = getScoreReader();
for (uint i = 0; i < elected.length; i++) {
address group = validators.getValidatorsGroup(elected[i]);
if (!processedGroups[group].processed) {
toProcessGroups++;
uint256 groupScore = scoreReader.getGroupScore(group);
// We need to precompute epoch rewards for each group since computation depends on total active votes for all groups.
uint256 epochRewards = election.getGroupEpochRewardsBasedOnScore(
group,
_epochProcessing.totalRewardsVoter,
groupScore
);
processedGroups[group] = ProcessedGroup(true, epochRewards);
}
}
uint256 toProcessGroups = fillProcessedGroups(election, _epochProcessing);

require(toProcessGroups == groups.length, "number of groups does not match");

for (uint i = 0; i < groups.length; i++) {
ProcessedGroup storage processedGroup = processedGroups[groups[i]];
uint256 epochRewards = processedGroups[groups[i]].get();
// checks that group is actually from elected group
require(processedGroup.processed, "group not from current elected set");
election.distributeEpochRewards(
groups[i],
processedGroup.epochRewards,
lessers[i],
greaters[i]
);

delete processedGroups[groups[i]];
require(epochRewards > 0, "group not from current elected set");
if (epochRewards == type(uint256).max) {
continue;
}
election.distributeEpochRewards(groups[i], epochRewards, lessers[i], greaters[i]);
}
getCeloUnreleasedTreasury().release(
registry.getAddressForOrDie(GOVERNANCE_REGISTRY_ID),
Expand Down Expand Up @@ -494,4 +473,36 @@ contract EpochManager is
CELOequivalent
);
}

/**
* @notice Fills the processedGroups mapping with the groups that need to be processed.
* @param election The Election contract.
* @param _epochProcessing The current epoch processing state.
* @return toProcessGroups The number of groups that need to be processed.
*/
function fillProcessedGroups(
IElection election,
EpochProcessState storage _epochProcessing
) internal returns (uint256 toProcessGroups) {
IScoreReader scoreReader = getScoreReader();
IValidators validators = getValidators();

for (uint i = 0; i < elected.length; i++) {
address group = validators.getValidatorsGroup(elected[i]);
tuint256 storage processedGroup = processedGroups[group];
if (processedGroup.get() == 0) {
toProcessGroups++;
uint256 groupScore = scoreReader.getGroupScore(group);
// We need to precompute epoch rewards for each group since computation depends on total active votes for all groups.
uint256 epochRewards = election.getGroupEpochRewardsBasedOnScore(
group,
_epochProcessing.totalRewardsVoter,
groupScore
);

// If the group has no votes, we set the rewards to max uint256 so we can recognize that this group should be processed
processedGroup.set(epochRewards == 0 ? type(uint256).max : epochRewards);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.7 <0.8.20;
pragma solidity >=0.8.7 <0.9;

import "../common/UsingRegistry.sol";
import "../common/UsingPrecompiles.sol";
Expand Down
2 changes: 1 addition & 1 deletion packages/protocol/contracts-0.8/common/GasPriceMinimum.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.7 <0.8.20;
pragma solidity >=0.8.7 <0.9;

import "@openzeppelin/contracts8/access/Ownable.sol";

Expand Down
2 changes: 1 addition & 1 deletion packages/protocol/contracts-0.8/common/IsL2Check.sol
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pragma solidity >=0.5.13 <0.8.20;
pragma solidity >=0.5.13 <0.9;

/**
* @title Based on predeploy returns whether this is L1 or L2.
Expand Down
8 changes: 4 additions & 4 deletions packages/protocol/contracts-0.8/common/ScoreManager.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.8.7 <0.8.20;
pragma solidity >=0.8.7 <0.9;

import "../../contracts/common/Initializable.sol";
import "../../contracts/common/interfaces/ICeloVersionedContract.sol";
Expand All @@ -11,14 +11,14 @@ contract ScoreManager is Initializable, Ownable {
bool exists;
}

event GroupScoreSet(address indexed group, uint256 score);
event ValidatorScoreSet(address indexed validator, uint256 score);

uint256 private constant FIXED1_UINT = 1e24;

mapping(address => Score) public groupScores;
mapping(address => Score) public validatorScores;

event GroupScoreSet(address indexed group, uint256 score);
event ValidatorScoreSet(address indexed validator, uint256 score);

/**
* @notice Sets initialized == true on implementation contracts
* @param test Set to true to skip implementation initialization
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.8.0 <0.8.20;
pragma solidity >=0.8.0 <0.9;

// Note: This is not an exact copy of UsingPrecompiles in the contract's folder, but in solidity 0.8
import "@openzeppelin/contracts8/utils/math/SafeMath.sol";
Expand Down
2 changes: 1 addition & 1 deletion packages/protocol/contracts-0.8/common/UsingRegistry.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.8.0 <0.8.20;
pragma solidity >=0.8.0 <0.9;

// Note: This is not an exact copy of UsingRegistry or UsingRegistryV2 in the contract's folder
// because Mento's interfaces still don't support Solidity 0.8
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
pragma solidity >=0.5.13 <0.9;

interface ICeloUnreleasedTreasuryInitializer {
function initialize(address registryAddress) external;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
pragma solidity >=0.5.13 <0.9;

interface IEpochManagerEnablerInitializer {
function initialize(address registryAddress) external;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
pragma solidity >=0.5.13 <0.9;

interface IEpochManagerInitializer {
function initialize(address registryAddress, uint256 newEpochDuration) external;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pragma solidity >=0.5.13 <0.9.0;
pragma solidity >=0.5.13 <0.9;

// TODO add to GasPrice
interface IGasPriceMinimum {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pragma solidity >=0.5.13 <0.9.0;
pragma solidity >=0.5.13 <0.9;

interface IGasPriceMinimumInitializer {
function initialize(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.5.13 <0.9.0;
pragma solidity >=0.5.13 <0.9;

/// Possibly not final version
interface IOracle {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.5.13 <0.9.0;
pragma solidity >=0.5.13 <0.9;

interface IPrecompiles {
function getEpochSize() external view returns (uint256);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
pragma solidity >=0.5.13 <0.9;

interface IScoreManager {
function setGroupScore(address group, uint256 score) external;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
pragma solidity >=0.5.13 <0.9;

interface IScoreManagerInitializer {
function initialize() external;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.8.7 <0.8.20;
pragma solidity >=0.8.7 <0.9;

interface IScoreReader {
function getValidatorScore(address validator) external view returns (uint256);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.8.7 <0.8.20;
pragma solidity >=0.8.7 <0.9;

/**
* @title This interface describes the functions specific to Celo Stable Tokens, and in the
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pragma solidity >=0.8.0 <0.8.20;
pragma solidity >=0.8.0 <0.9;

import "@openzeppelin/contracts8/utils/math/SafeMath.sol";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pragma solidity >=0.8.0 <0.8.20;
pragma solidity >=0.8.0 <0.9;

import "@openzeppelin/contracts8/utils/math/SafeMath.sol";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pragma solidity >=0.8.0 <0.8.20;
pragma solidity >=0.8.0 <0.9;

import "@openzeppelin/contracts8/utils/math/SafeMath.sol";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pragma solidity >=0.8.0 <0.8.20;
pragma solidity >=0.8.0 <0.9;

import "@openzeppelin/contracts8/utils/math/SafeMath.sol";
import "./LinkedList.sol";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pragma solidity >=0.8.0 <0.8.20;
pragma solidity >=0.8.0 <0.9;

import "@openzeppelin/contracts8/utils/math/SafeMath.sol";
import "./LinkedList.sol";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.7 <0.8.20;
pragma solidity >=0.8.7 <0.9;

import "../EpochManager.sol";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.7 <0.8.20;
pragma solidity >=0.8.7 <0.9;

import "../../../contracts/common/FixidityLib.sol";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.7 <0.8.20;
pragma solidity >=0.8.7 <0.9;

import "../../../contracts-0.8/common/FeeCurrencyDirectory.sol";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
pragma solidity >=0.5.13 <0.9;
// solhint-disable no-unused-vars

import "../../../contracts/common/interfaces/IEpochManager.sol";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.8.7 <0.8.20;
pragma solidity >=0.8.7 <0.9;

import "@openzeppelin/contracts8/utils/math/SafeMath.sol";
import "@openzeppelin/contracts8/access/Ownable.sol";
Expand Down
2 changes: 1 addition & 1 deletion packages/protocol/contracts-0.8/governance/Validators.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.8.7 <0.8.20;
pragma solidity >=0.8.7 <0.9;

import "@openzeppelin/contracts8/access/Ownable.sol";
import "@openzeppelin/contracts8/utils/math/Math.sol";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.7 <0.8.20;
pragma solidity >=0.8.7 <0.9;

import "../../../contracts/governance/interfaces/IEpochRewards.sol";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pragma solidity >=0.8.7 <0.8.20;
pragma solidity >=0.8.7 <0.9;

interface IMockValidators {
function isValidator(address) external returns (bool);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.8.7 <0.8.20;
pragma solidity >=0.8.7 <0.9;

import "./FeeCurrencyAdapterOwnable.sol";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.8.7 <0.8.20;
pragma solidity >=0.8.7 <0.9;

import "@openzeppelin/contracts8/access/Ownable.sol";
import "@openzeppelin/contracts8/token/ERC20/IERC20.sol";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.8.7 <0.8.20;
pragma solidity >=0.8.7 <0.9;

import "@openzeppelin/contracts8/access/Ownable.sol";
import "@openzeppelin/contracts8/token/ERC20/IERC20.sol";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.8.7 <0.8.20;
pragma solidity >=0.8.7 <0.9;

interface IFeeCurrencyAdapter {
/**
Expand Down
Loading

0 comments on commit 3932eca

Please sign in to comment.