1
1
// SPDX-License-Identifier: UNLICENSED
2
2
pragma solidity ^ 0.8.24 ;
3
3
4
- // import openzeppelin Role contracts
5
4
import {Passage} from "./Passage.sol " ;
6
5
7
6
contract Zenith is Passage {
7
+ /// @notice The address that is allowed to set/remove sequencers.
8
+ address public immutable sequencerAdmin;
9
+
8
10
/// @notice Block header information for the rollup block, signed by the sequencer.
9
11
/// @param rollupChainId - the chainId of the rollup chain. Any chainId is accepted by the contract.
10
12
/// @param sequence - the sequence number of the rollup block. Must be monotonically increasing. Enforced by the contract.
@@ -19,9 +21,6 @@ contract Zenith is Passage {
19
21
address rewardAddress;
20
22
}
21
23
22
- /// @notice Role that allows a key to sign commitments to rollup blocks.
23
- bytes32 public constant SEQUENCER_ROLE = bytes32 ("SEQUENCER_ROLE " );
24
-
25
24
/// @notice The sequence number of the next block that can be submitted for a given rollup chainId.
26
25
/// rollupChainId => nextSequence number
27
26
mapping (uint256 => uint256 ) public nextSequence;
@@ -30,6 +29,10 @@ contract Zenith is Passage {
30
29
/// rollupChainId => host blockNumber that block was last submitted at
31
30
mapping (uint256 => uint256 ) public lastSubmittedAtBlock;
32
31
32
+ /// @notice Registry of permissioned sequencers.
33
+ /// address => TRUE if it's a permissioned sequencer
34
+ mapping (address => bool ) public isSequencer;
35
+
33
36
/// @notice Thrown when a block submission is attempted with a sequence number that is not the next block for the rollup chainId.
34
37
/// @dev Blocks must be submitted in strict monotonic increasing order.
35
38
/// @param expected - the correct next sequence number for the given rollup chainId.
@@ -46,6 +49,9 @@ contract Zenith is Passage {
46
49
/// @notice Thrown when attempting to submit more than one rollup block per host block
47
50
error OneRollupBlockPerHostBlock ();
48
51
52
+ /// @notice Thrown when attempting to modify sequencer roles if not sequencerAdmin.
53
+ error OnlySequencerAdmin ();
54
+
49
55
/// @notice Emitted when a new rollup block is successfully submitted.
50
56
/// @param sequencer - the address of the sequencer that signed the block.
51
57
/// @param rollupChainId - the chainId of the rollup chain.
@@ -67,12 +73,36 @@ contract Zenith is Passage {
67
73
/// @notice Emit the entire block data for easy visibility
68
74
event BlockData (bytes blockData );
69
75
70
- /// @notice Initializes the Admin role.
71
- /// @dev See `AccessControlDefaultAdminRules` for information on contract administration.
72
- /// - Admin role can grant and revoke Sequencer roles.
73
- /// - Admin role can be transferred via two-step process with a 1 day timelock.
74
- /// @param admin - the address that will be the initial admin.
75
- constructor (uint256 defaultRollupChainId , address admin ) Passage (defaultRollupChainId, admin) {}
76
+ /// @notice Emitted when a sequencer is added or removed.
77
+ event SequencerSet (address indexed sequencer , bool indexed permissioned );
78
+
79
+ constructor (uint256 _defaultRollupChainId , address _withdrawalAdmin , address _sequencerAdmin )
80
+ Passage (_defaultRollupChainId, _withdrawalAdmin)
81
+ {
82
+ sequencerAdmin = _sequencerAdmin;
83
+ }
84
+
85
+ /// @notice Add a sequencer to the permissioned sequencer list.
86
+ /// @param sequencer - the address of the sequencer to add.
87
+ /// @custom:emits SequencerSet if the sequencer is added.
88
+ /// @custom:reverts OnlySequencerAdmin if the caller is not the sequencerAdmin.
89
+ function addSequencer (address sequencer ) external {
90
+ if (msg .sender != sequencerAdmin) revert OnlySequencerAdmin ();
91
+ if (isSequencer[sequencer]) return ;
92
+ isSequencer[sequencer] = true ;
93
+ emit SequencerSet (sequencer, true );
94
+ }
95
+
96
+ /// @notice Remove a sequencer from the permissioned sequencer list.
97
+ /// @param sequencer - the address of the sequencer to remove.
98
+ /// @custom:emits SequencerSet if the sequencer is removed.
99
+ /// @custom:reverts OnlySequencerAdmin if the caller is not the sequencerAdmin.
100
+ function removeSequencer (address sequencer ) external {
101
+ if (msg .sender != sequencerAdmin) revert OnlySequencerAdmin ();
102
+ if (! isSequencer[sequencer]) return ;
103
+ delete isSequencer[sequencer];
104
+ emit SequencerSet (sequencer, false );
105
+ }
76
106
77
107
/// @notice Submit a rollup block with block data submitted via calldata.
78
108
/// @dev Blocks are submitted by Builders, with an attestation to the block data signed by a Sequencer.
@@ -115,7 +145,7 @@ contract Zenith is Passage {
115
145
address sequencer = ecrecover (blockCommit, v, r, s);
116
146
117
147
// assert that signature is valid && sequencer is permissioned
118
- if (sequencer == address (0 ) || ! hasRole (SEQUENCER_ROLE, sequencer) ) revert BadSignature (sequencer);
148
+ if (sequencer == address (0 ) || ! isSequencer[ sequencer] ) revert BadSignature (sequencer);
119
149
120
150
// assert this is the first rollup block submitted for this host block
121
151
if (lastSubmittedAtBlock[header.rollupChainId] == block .number ) revert OneRollupBlockPerHostBlock ();
0 commit comments