Epochs And rewards
Overview of rewards and epochs in L1
The Celo L1 produces a special block (“epoch block”) every 17280 blocks (approximately one day). This blocks includes “epoch transactions” that are triggered by the blockchain itself. During these epoch transactions, the protocol does:- Updates target voting yield
- Calculates validator rewards
- Update validators’ scores
- Mints Celo:
- For validator rewards (then exchanged for cUSD using Mento)
- For voter rewards
- For CarbonOffsetting fund
- For Community Fund (Celo Governance)
- Distributing validator rewards to the validators, groups and delegator (in cUSD)
- Distributing voter rewards
- Running validator elections (the result is the addresses of the signers, then stored in the blockchain storage and accessed via a precompile)
Overview of rewards and epochs in L2
In the L2 “epoch blocks” no longer exist. There are no transactions triggered by the blockchain itself. Precompiles that were used to query epoch state are also not longer available. The concept for epochs still remains, but they are determined to be at least as long as “epoch duration” (targeted to be set as one day on mainnet), but there’s no guaranteed limit of the maximal duration. The size of an epoch can no longer be deterministically calculated based on block numbers alone. The logic for processing epochs is now fully implemented in Solidity in the EpochManager contract introduced in Contract Release 12. cLabs runs a bot that calls the functions to trigger the epoch change and rewards distributions as soon as they are ready to be called, in a best-effort way. Epochs are now processed using multiple calls, as the gas consumption of the process involved uses is relatively high. Celo is no longer minted when processing the epoch, it is now transferred from theCeloUnreleasedTreasury. The contract CeloUnreleasedTreasury is allocated the full amount of unminted Celo at the time of the transition to L2.
When “epoch duration” has elapsed since the current epoch started, the function startNextEpochProcess can be called. This function:
- Is permissionless, every EOA or contract can call it given that certain conditions are met:
- Enough time has elapsed after the beginning of the epoch.
- The epoch is not currently processing.
- Updates target voting yield
- Calculates epoch rewards (
EpochRewards.calculateTargetEpochRewards()) - Allocates validator rewards:
- mints CELO and exchanges it to cUSD
- Sets an internal mapping with the allocation for each validator. Validators can later claim it calling
sendValidatorPayment
- Starts a block that prevents certain actions to be performed, notable lock Celo, unlock Celo and change validator locks.
- Emits events:
- EpochRewards:
TargetVotingYieldUpdated(uint256 fraction) - CeloUnreleasedTreasury:
Released(address indexed to, uint256 amount) - cUSD:
Transfer(address indexed from, address indexed to, uint256 value) - EpochManager
EpochProcessingStarted(uint256 indexed epochNumber)
- EpochRewards:
startNextEpochProcess is called, the epoch can be fully finished by calling finishNextEpochProcess . This function:
- Is permissionless, every EOA or contract can call it given that certain conditions are met:
startNextEpochProcesshas been called before.
- Distributes rewards to voters (Celo)
- Elects validators (the result is stored as an array of accounts of the elected validators, signers are also stored for backwards compatibility purposes)
- Unblocks all actions blocked in
startNextEpochProcess. - Updates the Epoch state.
- Emits events:
- Election:
EpochRewardsDistributedToVoters(address indexed group, uint256 value) - CeloUnreleasedTreasury:
Released(address indexed to, uint256 amount) - EpochManager:
EpochProcessingEnded(uint256 indexed epochNumber)
- Election:
In the unlikely case thatstartNextEpochProcessneeds to use more gas than available in a block, the same result can be achieved using multiple calls toprocessGroup.
Scoring
The rewards for a validator, its group and its voters were previously based on the score of the validator, and the downtime the validator. The score itsef was defined by the downtime the validator had over multiple epochs. The scoring is now managed by a contract calledScoreManager. This contract is a placeholder for a more complex implementation, meanwhile Governance and a multisig has the power to change the score of a validator. The score is now fully proportional to the rewards the validator and its voters will get at the end of the epoch.
Celo minting
In the L1 Celo used to be minted using the well knownmint function, that was using the transfer precompile under the hood.
In the L2, the Celo in the L2 is a bridged token from the L1. At the moment of the transition the whole total supply of Celo (1 billion tokens) is allocated to the bridge contract in the L1. In the L2, all holders (contracts and EOAs) will remain with their balance in their account, but tokens that were previously unallocated in Celo as a L1 will now be allocated to a new contract called CeloUnreleasedTreasury.
This comes with the implication that the totalSuply() function of the Celo Token (contract name GoldToken) will return 1 billion Celo after the L2 transition.
This means that the Celo token is now an ERC20 on the Ethereum network, and the tokens available on the Celo chain are a bridged representation of the tokens in the L1. This is achieved by using the custom gas token functionality of the OP stack.
Governance Hotfix
The hot fix mechanism has been changed from a consensus of validators to a security council multisig.FeeCurrencyDirectory
The contractFeeCurrencyWhitelist is now deprecated. Fee currencies are now stored in a new contract called FeeCurrencyDirectory. To add a new token to the directory, an address for an oracle needs to be provided, as well as the intrinsic gas for transactions paid with this token as fee. Changes can only be made by Celo Governance.
The intrinsic gas is the amount of gas that it will be added to all transactions paying for fees with this token. It is meant to accurately represent the cost of the functions debitGasFeesand creditGasFees, that were used to collect the fees involved while validating the transaction.
FeeHandler
The FeeHandler was extended to support multiple beneficiaries. On the L1, only a carbon fund beneficiary and the burn fraction could be set. Since Contract Release 12, many beneficiaries can be set, and the burn fraction is the remainder of all the allocations of the beneficiaries.Slashing
DowntimeSlasher and DoubleSigningSlasher were deprecated with the L2 transition, as the validators were replaced by RPC providers. GovernanceSlasher remains available and now supports removing members of a validator group and changing the slash multiplier. Governance slasher now supports to enable a multisig with the slasher role.Deprecated contracts
The following contracts have been deprecated:- Attestations (withdraws still enabled).
- FeeCurrencyWhitelist
- GasPriceMinimum
- BlockChainParameters
- DowntimeSlasher
- DoubleSigningSlasher
- Random
- UsingPrecompiles
Deprecated Contract Methods with Replacements Table
Precompiles deprecation
On the L2, thetransfer precompile is the only supported Celo-specific precompile.
Also, the transfer precompile can no longer mint Celo. There’s an ongoing effort to push the transfer precompile upstream to the OP stack to guarantee full Superchain compatibility.
All other Celo-specific precompiles are deprecated, so the L2 migration removes support for the following precompiles:
fractionMulExpproofOfPossessiongetValidatornumberValidatorsepochSizeblockNumberFromHeaderhashHeadergetParentSealBitmapgetVerifiedSealBitmap