Skip to content

Commit 607ed1e

Browse files
authored
feat: constructor arg to delay reward claiming (#17943)
1 parent 26f3d4d commit 607ed1e

File tree

15 files changed

+162
-59
lines changed

15 files changed

+162
-59
lines changed

l1-contracts/foundry.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ script = 'script'
55
out = 'out'
66
libs = ['lib']
77
solc = "0.8.27"
8-
evm_version = 'cancun'
8+
evm_version = 'prague'
99
optimizer = true
1010

1111
match_path = "test/**/*.t.sol"

l1-contracts/src/core/Rollup.sol

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,14 @@ contract Rollup is IStaking, IValidatorSelection, IRollup, RollupCore {
524524
return RewardLib.getBlockReward();
525525
}
526526

527+
function isRewardsClaimable() external view override(IRollup) returns (bool) {
528+
return RewardLib.isRewardsClaimable();
529+
}
530+
531+
function getEarliestRewardsClaimableTimestamp() external view override(IRollup) returns (Timestamp) {
532+
return RewardLib.getEarliestRewardsClaimableTimestamp();
533+
}
534+
527535
function getAvailableValidatorFlushes() external view override(IStaking) returns (uint256) {
528536
return ValidatorOperationsExtLib.getAvailableValidatorFlushes();
529537
}

l1-contracts/src/core/RollupCore.sol

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import {CommitteeAttestations} from "@aztec/core/libraries/rollup/AttestationLib
1717
import {Errors} from "@aztec/core/libraries/Errors.sol";
1818
import {RollupOperationsExtLib} from "@aztec/core/libraries/rollup/RollupOperationsExtLib.sol";
1919
import {ValidatorOperationsExtLib} from "@aztec/core/libraries/rollup/ValidatorOperationsExtLib.sol";
20-
import {RewardDeploymentExtLib} from "@aztec/core/libraries/rollup/RewardDeploymentExtLib.sol";
2120
import {TallySlasherDeploymentExtLib} from "@aztec/core/libraries/rollup/TallySlasherDeploymentExtLib.sol";
2221
import {EmpireSlasherDeploymentExtLib} from "@aztec/core/libraries/rollup/EmpireSlasherDeploymentExtLib.sol";
2322
import {SlasherFlavor} from "@aztec/core/interfaces/ISlasher.sol";
@@ -33,7 +32,7 @@ import {GSE} from "@aztec/governance/GSE.sol";
3332
import {Ownable} from "@oz/access/Ownable.sol";
3433
import {IERC20} from "@oz/token/ERC20/IERC20.sol";
3534
import {EIP712} from "@oz/utils/cryptography/EIP712.sol";
36-
import {RewardLib, RewardConfig} from "@aztec/core/libraries/rollup/RewardLib.sol";
35+
import {RewardExtLib, RewardConfig} from "@aztec/core/libraries/rollup/RewardExtLib.sol";
3736
import {StakingQueueConfig} from "@aztec/core/libraries/compressed-data/StakingQueueConfig.sol";
3837
import {FeeConfigLib, CompressedFeeConfig} from "@aztec/core/libraries/compressed-data/fees/FeeConfig.sol";
3938
import {G1Point, G2Point} from "@aztec/shared/libraries/BN254Lib.sol";
@@ -198,11 +197,6 @@ contract RollupCore is EIP712("Aztec Rollup", "1"), Ownable, IStakingCore, IVali
198197
*/
199198
bool public checkBlob = true;
200199

201-
/**
202-
* @notice Flag controlling whether rewards can be claimed
203-
*/
204-
bool public isRewardsClaimable = false;
205-
206200
/**
207201
* @notice Initializes the Aztec rollup with all required configurations
208202
* @dev Sets up time parameters, deploys auxiliary contracts (slasher, reward booster),
@@ -212,8 +206,9 @@ contract RollupCore is EIP712("Aztec Rollup", "1"), Ownable, IStakingCore, IVali
212206
* @param _gse The Governance Staking Escrow contract
213207
* @param _epochProofVerifier The honk verifier contract for root epoch proofs
214208
* @param _governance The address with owner privileges
215-
* @param _genesisState Initial state containing VK tree root, protocol contract tree root, and genesis archive
216-
* @param _config Comprehensive configuration including timing, staking, slashing, and reward parameters
209+
* @param _genesisState Initial state containing VK tree root, protocol contracts hash, and genesis archive
210+
* @param _config Comprehensive configuration including timing, staking, slashing, reward parameters, and unlock
211+
* timestamp
217212
*/
218213
constructor(
219214
IERC20 _feeAsset,
@@ -279,10 +274,11 @@ contract RollupCore is EIP712("Aztec Rollup", "1"), Ownable, IStakingCore, IVali
279274

280275
// If no booster is specifically provided, deploy one.
281276
if (address(_config.rewardConfig.booster) == address(0)) {
282-
_config.rewardConfig.booster = RewardDeploymentExtLib.deployRewardBooster(_config.rewardBoostConfig);
277+
_config.rewardConfig.booster = RewardExtLib.deployRewardBooster(_config.rewardBoostConfig);
283278
}
284279

285-
RewardLib.setConfig(_config.rewardConfig);
280+
RewardExtLib.initialize(_config.earliestRewardsClaimableTimestamp);
281+
RewardExtLib.setConfig(_config.rewardConfig);
286282

287283
L1_BLOCK_AT_GENESIS = block.number;
288284

@@ -312,7 +308,7 @@ contract RollupCore is EIP712("Aztec Rollup", "1"), Ownable, IStakingCore, IVali
312308
* @param _config The new reward configuration including rates and booster settings
313309
*/
314310
function setRewardConfig(RewardConfig memory _config) external override(IRollupCore) onlyOwner {
315-
RewardLib.setConfig(_config);
311+
RewardExtLib.setConfig(_config);
316312
emit RewardConfigUpdated(_config);
317313
}
318314

@@ -340,10 +336,11 @@ contract RollupCore is EIP712("Aztec Rollup", "1"), Ownable, IStakingCore, IVali
340336
/**
341337
* @notice Enables or disables reward claiming
342338
* @dev Only callable by owner. This is a safety mechanism to control when rewards can be withdrawn.
339+
* Cannot set rewards as claimable before the earliest reward claimable timestamp.
343340
* @param _isRewardsClaimable True to enable reward claims, false to disable
344341
*/
345342
function setRewardsClaimable(bool _isRewardsClaimable) external override(IRollupCore) onlyOwner {
346-
isRewardsClaimable = _isRewardsClaimable;
343+
RewardExtLib.setIsRewardsClaimable(_isRewardsClaimable);
347344
emit RewardsClaimableUpdated(_isRewardsClaimable);
348345
}
349346

@@ -391,8 +388,7 @@ contract RollupCore is EIP712("Aztec Rollup", "1"), Ownable, IStakingCore, IVali
391388
* @return The amount of rewards claimed
392389
*/
393390
function claimSequencerRewards(address _coinbase) external override(IRollupCore) returns (uint256) {
394-
require(isRewardsClaimable, Errors.Rollup__RewardsNotClaimable());
395-
return RewardLib.claimSequencerRewards(_coinbase);
391+
return RewardExtLib.claimSequencerRewards(_coinbase);
396392
}
397393

398394
/**
@@ -408,8 +404,7 @@ contract RollupCore is EIP712("Aztec Rollup", "1"), Ownable, IStakingCore, IVali
408404
override(IRollupCore)
409405
returns (uint256)
410406
{
411-
require(isRewardsClaimable, Errors.Rollup__RewardsNotClaimable());
412-
return RewardLib.claimProverRewards(_coinbase, _epochs);
407+
return RewardExtLib.claimProverRewards(_coinbase, _epochs);
413408
}
414409

415410
/**

l1-contracts/src/core/interfaces/IRollup.sol

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ struct RollupConfigInput {
7676
RewardBoostConfig rewardBoostConfig;
7777
StakingQueueConfig stakingQueueConfig;
7878
uint256 localEjectionThreshold;
79+
Timestamp earliestRewardsClaimableTimestamp;
7980
}
8081

8182
struct RollupConfig {
@@ -142,7 +143,6 @@ interface IRollupCore {
142143
function setRewardConfig(RewardConfig memory _config) external;
143144
function updateManaTarget(uint256 _manaTarget) external;
144145

145-
function isRewardsClaimable() external view returns (bool);
146146
// solhint-disable-next-line func-name-mixedcase
147147
function L1_BLOCK_AT_GENESIS() external view returns (uint256);
148148
}
@@ -228,4 +228,6 @@ interface IRollup is IRollupCore, IHaveVersion {
228228

229229
function getRewardConfig() external view returns (RewardConfig memory);
230230
function getBlockReward() external view returns (uint256);
231+
function getEarliestRewardsClaimableTimestamp() external view returns (Timestamp);
232+
function isRewardsClaimable() external view returns (bool);
231233
}

l1-contracts/src/core/libraries/Errors.sol

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ library Errors {
9090
error Rollup__InvalidManaTarget(uint256 minimum, uint256 provided);
9191
error Rollup__ManaLimitExceeded();
9292
error Rollup__RewardsNotClaimable();
93+
error Rollup__TooSoonToSetRewardsClaimable(uint256 earliestRewardsClaimableTimestamp, uint256 currentTimestamp);
9394
error Rollup__InvalidFirstEpochProof();
9495
error Rollup__InvalidCoinbase();
9596
error Rollup__UnavailableTempBlockLog(uint256 blockNumber, uint256 pendingBlockNumber, uint256 upperLimit);

l1-contracts/src/core/libraries/rollup/EpochProofLib.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ pragma solidity >=0.8.27;
44

55
import {SubmitEpochRootProofArgs, PublicInputArgs, IRollupCore, RollupStore} from "@aztec/core/interfaces/IRollup.sol";
66
import {CompressedTempBlockLog} from "@aztec/core/libraries/compressed-data/BlockLog.sol";
7+
import {CompressedFeeHeader, FeeHeaderLib} from "@aztec/core/libraries/compressed-data/fees/FeeStructs.sol";
78
import {ChainTipsLib, CompressedChainTips} from "@aztec/core/libraries/compressed-data/Tips.sol";
89
import {Constants} from "@aztec/core/libraries/ConstantsGen.sol";
910
import {Errors} from "@aztec/core/libraries/Errors.sol";
1011
import {AttestationLib, CommitteeAttestations} from "@aztec/core/libraries/rollup/AttestationLib.sol";
1112
import {BlobLib} from "@aztec/core/libraries/rollup/BlobLib.sol";
12-
import {CompressedFeeHeader, FeeHeaderLib} from "@aztec/core/libraries/rollup/FeeLib.sol";
1313
import {RewardLib} from "@aztec/core/libraries/rollup/RewardLib.sol";
1414
import {STFLib} from "@aztec/core/libraries/rollup/STFLib.sol";
1515
import {ValidatorSelectionLib} from "@aztec/core/libraries/rollup/ValidatorSelectionLib.sol";

l1-contracts/src/core/libraries/rollup/RewardDeploymentExtLib.sol

Lines changed: 0 additions & 29 deletions
This file was deleted.
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
// Copyright 2024 Aztec Labs.
3+
pragma solidity >=0.8.27;
4+
5+
import {RewardLib, RewardConfig} from "@aztec/core/libraries/rollup/RewardLib.sol";
6+
import {Epoch, Timestamp} from "@aztec/core/libraries/TimeLib.sol";
7+
8+
import {
9+
RewardBooster,
10+
RewardBoostConfig,
11+
IBoosterCore,
12+
IValidatorSelection
13+
} from "@aztec/core/reward-boost/RewardBooster.sol";
14+
15+
library RewardExtLib {
16+
function initialize(Timestamp _earliestRewardsClaimableTimestamp) external {
17+
RewardLib.initialize(_earliestRewardsClaimableTimestamp);
18+
}
19+
20+
function setConfig(RewardConfig memory _config) external {
21+
RewardLib.setConfig(_config);
22+
}
23+
24+
function setIsRewardsClaimable(bool _isRewardsClaimable) external {
25+
RewardLib.setIsRewardsClaimable(_isRewardsClaimable);
26+
}
27+
28+
function claimSequencerRewards(address _sequencer) external returns (uint256) {
29+
return RewardLib.claimSequencerRewards(_sequencer);
30+
}
31+
32+
function claimProverRewards(address _prover, Epoch[] memory _epochs) external returns (uint256) {
33+
return RewardLib.claimProverRewards(_prover, _epochs);
34+
}
35+
36+
function deployRewardBooster(RewardBoostConfig memory _config) external returns (IBoosterCore) {
37+
RewardBooster booster = new RewardBooster(IValidatorSelection(address(this)), _config);
38+
return IBoosterCore(address(booster));
39+
}
40+
}

l1-contracts/src/core/libraries/rollup/RewardLib.sol

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {STFLib} from "@aztec/core/libraries/rollup/STFLib.sol";
99
import {Epoch, Timestamp, TimeLib} from "@aztec/core/libraries/TimeLib.sol";
1010
import {IBoosterCore} from "@aztec/core/reward-boost/RewardBooster.sol";
1111
import {IRewardDistributor} from "@aztec/governance/interfaces/IRewardDistributor.sol";
12+
import {CompressedTimeMath, CompressedTimestamp} from "@aztec/shared/libraries/CompressedTimeMath.sol";
1213
import {IERC20} from "@oz/token/ERC20/IERC20.sol";
1314
import {SafeERC20} from "@oz/token/ERC20/utils/SafeERC20.sol";
1415
import {Math} from "@oz/utils/math/Math.sol";
@@ -46,6 +47,8 @@ struct RewardStorage {
4647
mapping(Epoch => EpochRewards) epochRewards;
4748
mapping(address prover => BitMaps.BitMap claimed) proverClaimed;
4849
RewardConfig config;
50+
CompressedTimestamp earliestRewardsClaimableTimestamp;
51+
bool isRewardsClaimable;
4952
}
5053

5154
struct Values {
@@ -64,7 +67,8 @@ struct Totals {
6467
library RewardLib {
6568
using SafeERC20 for IERC20;
6669
using BitMaps for BitMaps.BitMap;
67-
70+
using CompressedTimeMath for CompressedTimestamp;
71+
using CompressedTimeMath for Timestamp;
6872
using TimeLib for Timestamp;
6973
using TimeLib for Epoch;
7074
using FeeHeaderLib for CompressedFeeHeader;
@@ -76,14 +80,33 @@ library RewardLib {
7680
// such as sacrificial hearts, during rituals performed within temples.
7781
address public constant BURN_ADDRESS = address(bytes20("CUAUHXICALLI"));
7882

83+
function initialize(Timestamp _earliestRewardsClaimableTimestamp) internal {
84+
RewardStorage storage rewardStorage = getStorage();
85+
rewardStorage.earliestRewardsClaimableTimestamp = _earliestRewardsClaimableTimestamp.compress();
86+
rewardStorage.isRewardsClaimable = false;
87+
}
88+
7989
function setConfig(RewardConfig memory _config) internal {
8090
require(Bps.unwrap(_config.sequencerBps) <= 10_000, Errors.RewardLib__InvalidSequencerBps());
8191
RewardStorage storage rewardStorage = getStorage();
8292
rewardStorage.config = _config;
8393
}
8494

95+
function setIsRewardsClaimable(bool _isRewardsClaimable) internal {
96+
RewardStorage storage rewardStorage = getStorage();
97+
uint256 earliestRewardsClaimableTimestamp =
98+
Timestamp.unwrap(rewardStorage.earliestRewardsClaimableTimestamp.decompress());
99+
require(
100+
block.timestamp >= earliestRewardsClaimableTimestamp,
101+
Errors.Rollup__TooSoonToSetRewardsClaimable(earliestRewardsClaimableTimestamp, block.timestamp)
102+
);
103+
104+
rewardStorage.isRewardsClaimable = _isRewardsClaimable;
105+
}
106+
85107
function claimSequencerRewards(address _sequencer) internal returns (uint256) {
86108
RewardStorage storage rewardStorage = getStorage();
109+
require(rewardStorage.isRewardsClaimable, Errors.Rollup__RewardsNotClaimable());
87110

88111
RollupStore storage rollupStore = STFLib.getStorage();
89112
uint256 amount = rewardStorage.sequencerRewards[_sequencer];
@@ -102,6 +125,8 @@ library RewardLib {
102125

103126
RewardStorage storage rewardStorage = getStorage();
104127

128+
require(rewardStorage.isRewardsClaimable, Errors.Rollup__RewardsNotClaimable());
129+
105130
uint256 accumulatedRewards = 0;
106131
for (uint256 i = 0; i < _epochs.length; i++) {
107132
require(
@@ -268,6 +293,14 @@ library RewardLib {
268293
return (se.shares[_prover] * er.rewards / se.summedShares);
269294
}
270295

296+
function isRewardsClaimable() internal view returns (bool) {
297+
return getStorage().isRewardsClaimable;
298+
}
299+
300+
function getEarliestRewardsClaimableTimestamp() internal view returns (Timestamp) {
301+
return getStorage().earliestRewardsClaimableTimestamp.decompress();
302+
}
303+
271304
function getStorage() internal pure returns (RewardStorage storage storageStruct) {
272305
bytes32 position = REWARD_STORAGE_POSITION;
273306
assembly {

l1-contracts/test/harnesses/TestConstants.sol

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,8 @@ library TestConstants {
115115
stakingQueueConfig: getStakingQueueConfig(),
116116
slashAmounts: [AZTEC_SLASH_AMOUNT_SMALL, AZTEC_SLASH_AMOUNT_MEDIUM, AZTEC_SLASH_AMOUNT_LARGE],
117117
slasherFlavor: SlasherFlavor.EMPIRE,
118-
localEjectionThreshold: 0 // The same as it being off, and only using the global.
118+
localEjectionThreshold: 0, // The same as it being off, and only using the global.
119+
earliestRewardsClaimableTimestamp: Timestamp.wrap(0) // Default to 0 (no restriction)
119120
});
120121

121122
// For the version we derive it based on the config (with a 0 version)

0 commit comments

Comments
 (0)