@@ -28,6 +28,10 @@ contract Zenith is HostPassage, AccessControlDefaultAdminRules {
28
28
/// rollupChainId => nextSequence number
29
29
mapping (uint256 => uint256 ) public nextSequence;
30
30
31
+ /// @notice The host block number that a block was last submitted at for a given rollup chainId.
32
+ /// rollupChainId => host blockNumber that block was last submitted at
33
+ mapping (uint256 => uint256 ) public lastSubmittedAtBlock;
34
+
31
35
/// @notice Thrown when a block submission is attempted with a sequence number that is not the next block for the rollup chainId.
32
36
/// @dev Blocks must be submitted in strict monotonic increasing order.
33
37
/// @param expected - the correct next sequence number for the given rollup chainId.
@@ -41,6 +45,9 @@ contract Zenith is HostPassage, AccessControlDefaultAdminRules {
41
45
/// @param derivedSequencer - the derived signer of the block data that is not a permissioned sequencer.
42
46
error BadSignature (address derivedSequencer );
43
47
48
+ /// @notice Thrown when attempting to submit more than one rollup block per host block
49
+ error OneRollupBlockPerHostBlock ();
50
+
44
51
/// @notice Emitted when a new rollup block is successfully submitted.
45
52
/// @param sequencer - the address of the sequencer that signed the block.
46
53
/// @param header - the block header information for the block.
@@ -100,6 +107,9 @@ contract Zenith is HostPassage, AccessControlDefaultAdminRules {
100
107
// assert that signature is valid && sequencer is permissioned
101
108
if (! hasRole (SEQUENCER_ROLE, sequencer)) revert BadSignature (sequencer);
102
109
110
+ // assert this is the first rollup block submitted for this host block
111
+ if (lastSubmittedAtBlock[header.rollupChainId] == block .number ) revert OneRollupBlockPerHostBlock ();
112
+ lastSubmittedAtBlock[header.rollupChainId] = block .number ;
103
113
104
114
// emit event
105
115
emit BlockSubmitted (sequencer, header, blockDataHash);
0 commit comments