Skip to content

Commit e88ecdf

Browse files
authored
feat: remove isRewardClaimable (#21765)
## Summary Remove the reward-claimability lock from `l1-contracts`. Reward claims no longer depend on a governance-controlled flag or an unlock timestamp. Claims now succeed or fail only based on the existing reward/accounting rules, such as whether rewards exist and whether prover claims are past the proof deadline. ## What Changed - Removed `isRewardsClaimable` and `earliestRewardsClaimableTimestamp` from reward storage. - Removed the related ABI/config surface: - getters - setter - event - errors - rollup forwarding methods - Removed reward-claimability checks from: - `claimSequencerRewards` - `claimProverRewards` - `FlushRewarder.claimRewards` - Removed deploy/test config plumbing for the unlock timestamp. - Rewrote the affected tests to cover the simplified behavior directly. - Updated the current operator docs for claiming rewards.
2 parents adf587b + 7e6c33f commit e88ecdf

File tree

14 files changed

+36
-252
lines changed

14 files changed

+36
-252
lines changed

docs/docs-operate/operators/sequencer-management/claiming-rewards.md

Lines changed: 2 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,8 @@ Rewards are not automatically sent to your coinbase address. You must explicitly
3737

3838
Before claiming, verify these conditions:
3939

40-
1. **Rewards must be claimable**: A governance vote must pass to enable the claiming of rewards (only possible after a minimum configured timestamp) and governance must have called `setRewardsClaimable(true)` on the rollup contract.
41-
2. **Rewards have accumulated**: Query your pending rewards before attempting to claim.
42-
3. **Sufficient gas**: Ensure you have ETH to pay transaction gas costs.
40+
1. **Rewards have accumulated**: Query your pending rewards before attempting to claim.
41+
2. **Sufficient gas**: Ensure you have ETH to pay transaction gas costs.
4342

4443
## Checking Reward Status
4544

@@ -54,26 +53,6 @@ export ROLLUP_ADDRESS="[YOUR_ROLLUP_CONTRACT_ADDRESS]"
5453

5554
Replace `[YOUR_ROLLUP_CONTRACT_ADDRESS]` with your actual Rollup contract address.
5655

57-
### Check if Rewards Are Claimable
58-
59-
Verify reward claiming is enabled before attempting to claim:
60-
61-
```bash
62-
cast call $ROLLUP_ADDRESS "isRewardsClaimable()" --rpc-url $RPC_URL
63-
```
64-
65-
**Expected output:**
66-
- `0x0000000000000000000000000000000000000000000000000000000000000001` - Rewards are claimable (true)
67-
- `0x0000000000000000000000000000000000000000000000000000000000000000` - Rewards are not yet claimable (false)
68-
69-
If rewards are not claimable, check when they will become claimable:
70-
71-
```bash
72-
cast call $ROLLUP_ADDRESS "getEarliestRewardsClaimableTimestamp()" --rpc-url $RPC_URL
73-
```
74-
75-
This returns a Unix timestamp indicating the earliest time when governance can enable reward claiming.
76-
7756
### Query Your Pending Rewards
7857

7958
Check accumulated rewards:
@@ -161,15 +140,6 @@ cast call $ROLLUP_ADDRESS "getSequencerRewards(address)" [COINBASE_ADDRESS] --rp
161140

162141
## Troubleshooting
163142

164-
### "Rewards not claimable" Error
165-
166-
**Symptom**: Transaction reverts with "Rewards not claimable" error.
167-
168-
**Solution**:
169-
1. Check if rewards are claimable using `isRewardsClaimable()`
170-
2. If `false`, wait until governance enables claiming via `setRewardsClaimable(true)`
171-
3. Check the earliest claimable timestamp using `getEarliestRewardsClaimableTimestamp()`
172-
173143
### No Pending Rewards
174144

175145
**Symptom**: `getSequencerRewards()` returns zero.

l1-contracts/gas_benchmark.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
| Function | Avg Gas | Max Gas | Calldata Size | Calldata Gas |
1616
|----------------------|---------|---------|---------------|--------------|
1717
| propose | 195,201 | 221,411 | 932 | 14,912 |
18-
| submitEpochRootProof | 698,954 | 744,754 | 2,820 | 45,120 |
19-
| setupEpoch | 32,010 | 113,661 | - | - |
18+
| submitEpochRootProof | 698,976 | 744,776 | 2,820 | 45,120 |
19+
| setupEpoch | 31,965 | 113,616 | - | - |
2020

2121
**Avg Gas Cost per Second**: 3,331.7 gas/second
2222
*Epoch duration*: 0h 38m 24s
@@ -26,9 +26,9 @@
2626
| Function | Avg Gas | Max Gas | Calldata Size | Calldata Gas |
2727
|----------------------|---------|---------|---------------|--------------|
2828
| propose | 322,945 | 350,085 | 4,452 | 71,232 |
29-
| submitEpochRootProof | 897,128 | 942,932 | 5,316 | 85,056 |
30-
| aggregate3 | 371,446 | 384,876 | - | - |
31-
| setupEpoch | 46,471 | 547,494 | - | - |
29+
| submitEpochRootProof | 897,150 | 942,954 | 5,316 | 85,056 |
30+
| aggregate3 | 371,401 | 384,831 | - | - |
31+
| setupEpoch | 46,426 | 547,449 | - | - |
3232

3333
**Avg Gas Cost per Second**: 5,284.3 gas/second
3434
*Epoch duration*: 0h 38m 24s

l1-contracts/gas_benchmark_results.json

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,17 @@
1111
},
1212
"setupEpoch": {
1313
"calls": 150,
14-
"min": 29281,
15-
"mean": 32010,
16-
"median": 29281,
17-
"max": 113661
14+
"min": 29236,
15+
"mean": 31965,
16+
"median": 29236,
17+
"max": 113616
1818
},
1919
"submitEpochRootProof": {
2020
"calls": 4,
21-
"min": 677906,
22-
"mean": 698954,
23-
"median": 686579,
24-
"max": 744754,
21+
"min": 677928,
22+
"mean": 698976,
23+
"median": 686601,
24+
"max": 744776,
2525
"calldata_size": 2820,
2626
"calldata_gas": 45120
2727
}
@@ -38,26 +38,26 @@
3838
},
3939
"setupEpoch": {
4040
"calls": 150,
41-
"min": 29281,
42-
"mean": 46471,
43-
"median": 29281,
44-
"max": 547494
41+
"min": 29236,
42+
"mean": 46426,
43+
"median": 29236,
44+
"max": 547449
4545
},
4646
"submitEpochRootProof": {
4747
"calls": 4,
48-
"min": 876090,
49-
"mean": 897128,
50-
"median": 884745,
51-
"max": 942932,
48+
"min": 876112,
49+
"mean": 897150,
50+
"median": 884767,
51+
"max": 942954,
5252
"calldata_size": 5316,
5353
"calldata_gas": 85056
5454
},
5555
"aggregate3": {
5656
"calls": 55,
57-
"min": 360343,
58-
"mean": 371446,
59-
"median": 371210,
60-
"max": 384876
57+
"min": 360298,
58+
"mean": 371401,
59+
"median": 371165,
60+
"max": 384831
6161
}
6262
}
6363
}

l1-contracts/script/deploy/RollupConfiguration.sol

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import {IRewardDistributor} from "@aztec/governance/interfaces/IRewardDistributo
1010
import {IBoosterCore} from "@aztec/core/reward-boost/RewardBooster.sol";
1111
import {EthValue, EthPerFeeAssetE12} from "@aztec/core/libraries/rollup/FeeLib.sol";
1212
import {GenesisState, RollupConfigInput} from "@aztec/core/interfaces/IRollup.sol";
13-
import {Timestamp} from "@aztec/core/libraries/TimeLib.sol";
1413
import {RewardBoostConfig} from "@aztec/core/reward-boost/RewardBooster.sol";
1514
import {StakingQueueConfig} from "@aztec/core/libraries/compressed-data/StakingQueueConfig.sol";
1615
import {RewardConfig, Bps} from "@aztec/core/libraries/rollup/RewardLib.sol";
@@ -19,7 +18,6 @@ interface IRollupConfiguration {
1918
function loadConfig() external;
2019
function useRealVerifier() external view returns (bool);
2120
function getFeeJuicePortalInitialBalance() external view returns (uint256);
22-
function getEarliestRewardsClaimableTimestamp() external view returns (Timestamp);
2321
function getGenesisState() external view returns (GenesisState memory);
2422
function getRewardConfiguration(IRewardDistributor rewardDistributor) external view returns (RewardConfig memory);
2523
function getRewardBoostConfiguration() external pure returns (RewardBoostConfig memory);
@@ -48,16 +46,6 @@ contract RollupConfiguration is IRollupConfiguration, Test {
4846
return vm.envOr("FEE_JUICE_PORTAL_INITIAL_BALANCE", uint256(0));
4947
}
5048

51-
function getEarliestRewardsClaimableTimestamp() public view returns (Timestamp) {
52-
// We only set a delay on mainnet.
53-
// Since we don't plan to redeploy on mainnet (knock on wood), this is mostly documentation in code form.
54-
if (block.chainid == 1) {
55-
return Timestamp.wrap(block.timestamp + 90 days);
56-
} else {
57-
return Timestamp.wrap(0);
58-
}
59-
}
60-
6149
function getGenesisState() external view returns (GenesisState memory) {
6250
return GenesisState({
6351
vkTreeRoot: bytes32(vm.envOr("VK_TREE_ROOT", uint256(0))),
@@ -105,7 +93,6 @@ contract RollupConfiguration is IRollupConfiguration, Test {
10593
config.rewardConfig = this.getRewardConfiguration(_rewardDistributor);
10694
config.rewardBoostConfig = this.getRewardBoostConfiguration();
10795
config.stakingQueueConfig = this.getStakingQueueConfiguration();
108-
config.earliestRewardsClaimableTimestamp = getEarliestRewardsClaimableTimestamp();
10996

11097
// Compute version as first 4 bytes of hash(abi.encode(config, genesisState))
11198
config.version = _computeConfigVersion(config, this.getGenesisState());

l1-contracts/src/core/Rollup.sol

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -570,14 +570,6 @@ contract Rollup is IStaking, IValidatorSelection, IRollup, RollupCore {
570570
return RewardExtLib.getCheckpointReward();
571571
}
572572

573-
function isRewardsClaimable() external view override(IRollup) returns (bool) {
574-
return RewardExtLib.isRewardsClaimable();
575-
}
576-
577-
function getEarliestRewardsClaimableTimestamp() external view override(IRollup) returns (Timestamp) {
578-
return RewardExtLib.getEarliestRewardsClaimableTimestamp();
579-
}
580-
581573
function getAvailableValidatorFlushes() external view override(IStaking) returns (uint256) {
582574
return ValidatorOperationsExtLib.getAvailableValidatorFlushes();
583575
}

l1-contracts/src/core/RollupCore.sol

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -280,17 +280,6 @@ contract RollupCore is EIP712("Aztec Rollup", "1"), Ownable, IStakingCore, IVali
280280
emit IRollupCore.ManaTargetUpdated(_manaTarget);
281281
}
282282

283-
/**
284-
* @notice Enables or disables reward claiming
285-
* @dev Only callable by owner. This is a safety mechanism to control when rewards can be withdrawn.
286-
* Cannot set rewards as claimable before the earliest reward claimable timestamp.
287-
* @param _isRewardsClaimable True to enable reward claims, false to disable
288-
*/
289-
function setRewardsClaimable(bool _isRewardsClaimable) external override(IRollupCore) onlyOwner {
290-
RewardExtLib.setIsRewardsClaimable(_isRewardsClaimable);
291-
emit RewardsClaimableUpdated(_isRewardsClaimable);
292-
}
293-
294283
/**
295284
* @notice Updates the slasher contract address
296285
* @dev Only callable by owner. The slasher handles punishment for validator misbehavior.
@@ -341,7 +330,7 @@ contract RollupCore is EIP712("Aztec Rollup", "1"), Ownable, IStakingCore, IVali
341330

342331
/**
343332
* @notice Claims accumulated rewards for a sequencer (checkpoint proposer)
344-
* @dev Rewards must be enabled via isRewardsClaimable. Transfers all accumulated rewards to the recipient.
333+
* @dev Transfers all accumulated rewards to the recipient.
345334
* @param _coinbase The address that has accumulated the rewards - rewards are sent to this address
346335
* @return The amount of rewards claimed
347336
*/
@@ -351,8 +340,8 @@ contract RollupCore is EIP712("Aztec Rollup", "1"), Ownable, IStakingCore, IVali
351340

352341
/**
353342
* @notice Claims prover rewards for specified epochs
354-
* @dev Rewards must be enabled. Provers earn rewards for successfully proving epoch transitions.
355-
* Each epoch can only be claimed once per prover.
343+
* @dev Provers earn rewards for successfully proving epoch transitions. Each epoch can only be claimed once per
344+
* prover.
356345
* @param _coinbase The address that has accumulated the rewards - rewards are sent to this address
357346
* @param _epochs Array of epochs to claim rewards for
358347
* @return The total amount of rewards claimed
@@ -598,7 +587,6 @@ contract RollupCore is EIP712("Aztec Rollup", "1"), Ownable, IStakingCore, IVali
598587
rewardConfig.booster = RewardExtLib.deployRewardBooster(_config.rewardBoostConfig);
599588
}
600589

601-
RewardExtLib.initialize(_config.earliestRewardsClaimableTimestamp);
602590
RewardExtLib.setConfig(rewardConfig);
603591
}
604592

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

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ struct RollupConfigInput {
7979
RewardBoostConfig rewardBoostConfig;
8080
StakingQueueConfig stakingQueueConfig;
8181
uint256 localEjectionThreshold;
82-
Timestamp earliestRewardsClaimableTimestamp;
8382
uint256 inboxLag;
8483
}
8584

@@ -115,9 +114,7 @@ interface IRollupCore {
115114
event RewardConfigUpdated(RewardConfig rewardConfig);
116115
event ManaTargetUpdated(uint256 indexed manaTarget);
117116
event PrunedPending(uint256 provenCheckpointNumber, uint256 pendingCheckpointNumber);
118-
event RewardsClaimableUpdated(bool isRewardsClaimable);
119117

120-
function setRewardsClaimable(bool _isRewardsClaimable) external;
121118
function claimSequencerRewards(address _recipient) external returns (uint256);
122119
function claimProverRewards(address _recipient, Epoch[] memory _epochs) external returns (uint256);
123120

@@ -237,6 +234,4 @@ interface IRollup is IRollupCore, IHaveVersion {
237234

238235
function getRewardConfig() external view returns (RewardConfig memory);
239236
function getCheckpointReward() external view returns (uint256);
240-
function getEarliestRewardsClaimableTimestamp() external view returns (Timestamp);
241-
function isRewardsClaimable() external view returns (bool);
242237
}

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,6 @@ library Errors {
8787
error Rollup__ProverHaveAlreadySubmitted(address prover, Epoch epoch);
8888
error Rollup__InvalidManaTarget(uint256 minimum, uint256 provided);
8989
error Rollup__ManaLimitExceeded();
90-
error Rollup__RewardsNotClaimable();
91-
error Rollup__TooSoonToSetRewardsClaimable(uint256 earliestRewardsClaimableTimestamp, uint256 currentTimestamp);
9290
error Rollup__InvalidFirstEpochProof();
9391
error Rollup__InvalidCoinbase();
9492
error Rollup__UnavailableTempCheckpointLog(

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

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,10 @@ import {
2222
import {IRewardDistributor} from "@aztec/governance/interfaces/IRewardDistributor.sol";
2323

2424
library RewardExtLib {
25-
function initialize(Timestamp _earliestRewardsClaimableTimestamp) external {
26-
RewardLib.initialize(_earliestRewardsClaimableTimestamp);
27-
}
28-
2925
function setConfig(RewardConfig memory _config) external {
3026
RewardLib.setConfig(_config);
3127
}
3228

33-
function setIsRewardsClaimable(bool _isRewardsClaimable) external {
34-
RewardLib.setIsRewardsClaimable(_isRewardsClaimable);
35-
}
36-
3729
function claimSequencerRewards(address _sequencer) external returns (uint256) {
3830
return RewardLib.claimSequencerRewards(_sequencer);
3931
}
@@ -77,14 +69,6 @@ library RewardExtLib {
7769
return RewardLib.getCheckpointReward();
7870
}
7971

80-
function isRewardsClaimable() external view returns (bool) {
81-
return RewardLib.isRewardsClaimable();
82-
}
83-
84-
function getEarliestRewardsClaimableTimestamp() external view returns (Timestamp) {
85-
return RewardLib.getEarliestRewardsClaimableTimestamp();
86-
}
87-
8872
function getRewardConfig() external view returns (RewardConfig memory) {
8973
return RewardLib.getStorage().config;
9074
}

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

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ 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";
1312
import {IERC20} from "@oz/token/ERC20/IERC20.sol";
1413
import {SafeERC20} from "@oz/token/ERC20/utils/SafeERC20.sol";
1514
import {Math} from "@oz/utils/math/Math.sol";
@@ -47,8 +46,6 @@ struct RewardStorage {
4746
mapping(Epoch => EpochRewards) epochRewards;
4847
mapping(address prover => BitMaps.BitMap claimed) proverClaimed;
4948
RewardConfig config;
50-
CompressedTimestamp earliestRewardsClaimableTimestamp;
51-
bool isRewardsClaimable;
5249
}
5350

5451
struct Values {
@@ -67,8 +64,6 @@ struct Totals {
6764
library RewardLib {
6865
using SafeERC20 for IERC20;
6966
using BitMaps for BitMaps.BitMap;
70-
using CompressedTimeMath for CompressedTimestamp;
71-
using CompressedTimeMath for Timestamp;
7267
using TimeLib for Timestamp;
7368
using TimeLib for Epoch;
7469
using FeeHeaderLib for CompressedFeeHeader;
@@ -81,34 +76,14 @@ library RewardLib {
8176
// such as sacrificial hearts, during rituals performed within temples.
8277
address public constant BURN_ADDRESS = address(bytes20("CUAUHXICALLI"));
8378

84-
function initialize(Timestamp _earliestRewardsClaimableTimestamp) internal {
85-
RewardStorage storage rewardStorage = getStorage();
86-
rewardStorage.earliestRewardsClaimableTimestamp = _earliestRewardsClaimableTimestamp.compress();
87-
rewardStorage.isRewardsClaimable = false;
88-
}
89-
9079
function setConfig(RewardConfig memory _config) internal {
9180
require(Bps.unwrap(_config.sequencerBps) <= 10_000, Errors.RewardLib__InvalidSequencerBps());
9281
RewardStorage storage rewardStorage = getStorage();
9382
rewardStorage.config = _config;
9483
}
9584

96-
function setIsRewardsClaimable(bool _isRewardsClaimable) internal {
97-
RewardStorage storage rewardStorage = getStorage();
98-
uint256 earliestRewardsClaimableTimestamp =
99-
Timestamp.unwrap(rewardStorage.earliestRewardsClaimableTimestamp.decompress());
100-
require(
101-
block.timestamp >= earliestRewardsClaimableTimestamp,
102-
Errors.Rollup__TooSoonToSetRewardsClaimable(earliestRewardsClaimableTimestamp, block.timestamp)
103-
);
104-
105-
rewardStorage.isRewardsClaimable = _isRewardsClaimable;
106-
}
107-
10885
function claimSequencerRewards(address _sequencer) internal returns (uint256) {
10986
RewardStorage storage rewardStorage = getStorage();
110-
require(rewardStorage.isRewardsClaimable, Errors.Rollup__RewardsNotClaimable());
111-
11287
RollupStore storage rollupStore = STFLib.getStorage();
11388
uint256 amount = rewardStorage.sequencerRewards[_sequencer];
11489

@@ -126,8 +101,6 @@ library RewardLib {
126101

127102
RewardStorage storage rewardStorage = getStorage();
128103

129-
require(rewardStorage.isRewardsClaimable, Errors.Rollup__RewardsNotClaimable());
130-
131104
uint256 accumulatedRewards = 0;
132105
for (uint256 i = 0; i < _epochs.length; i++) {
133106
require(
@@ -296,14 +269,6 @@ library RewardLib {
296269
return (se.shares[_prover] * er.rewards / se.summedShares);
297270
}
298271

299-
function isRewardsClaimable() internal view returns (bool) {
300-
return getStorage().isRewardsClaimable;
301-
}
302-
303-
function getEarliestRewardsClaimableTimestamp() internal view returns (Timestamp) {
304-
return getStorage().earliestRewardsClaimableTimestamp.decompress();
305-
}
306-
307272
function getStorage() internal pure returns (RewardStorage storage storageStruct) {
308273
bytes32 position = REWARD_STORAGE_POSITION;
309274
assembly {

0 commit comments

Comments
 (0)