diff --git a/contracts/v2/consensus/validium/PolygonValidiumEtrog.sol b/contracts/v2/consensus/validium/PolygonValidiumEtrog.sol index e9123335b..3dda2c85b 100644 --- a/contracts/v2/consensus/validium/PolygonValidiumEtrog.sol +++ b/contracts/v2/consensus/validium/PolygonValidiumEtrog.sol @@ -5,6 +5,8 @@ import "../../lib/PolygonRollupBaseEtrog.sol"; import "../../interfaces/IDataAvailabilityProtocol.sol"; import "../../interfaces/IPolygonValidium.sol"; +// MAKvalidum upgradable D: TTT +// Make a reiniitalize that's able to get teh previosu data commitee and set to 0 afterwarfs /** * Contract responsible for managing the states and the updates of L2 network. * There will be a trusted sequencer, which is able to send transactions. @@ -77,6 +79,10 @@ contract PolygonValidiumEtrog is PolygonRollupBaseEtrog, IPolygonValidium { /** * @notice Allows a sequencer to send multiple batches * @param batches Struct array which holds the necessary data to append new batches to the sequence + * @param maxSequenceTimestamp Max timestamp of the sequence. This timestamp must be inside a safety range (actual + 36 seconds). + * This timestamp should be equal or higher of the last block inside the sequence, otherwise this batch will be invalidated by circuit. + * @param currentSequenceNumber This parameter must match the current sequenceNumber, which will be a counter of sequences. + * This will be a protection for the sequencer to avoid sending undesired data * @param l2Coinbase Address that will receive the fees from L2 * @param dataAvailabilityMessage Byte array containing the signatures and all the addresses of the committee in ascending order * [signature 0, ..., signature requiredAmountOfSignatures -1, address 0, ... address N] @@ -85,6 +91,8 @@ contract PolygonValidiumEtrog is PolygonRollupBaseEtrog, IPolygonValidium { */ function sequenceBatchesValidium( ValidiumBatchData[] calldata batches, + uint64 maxSequenceTimestamp, + uint256 currentSequenceNumber, address l2Coinbase, bytes calldata dataAvailabilityMessage ) external onlyTrustedSequencer { @@ -97,6 +105,21 @@ contract PolygonValidiumEtrog is PolygonRollupBaseEtrog, IPolygonValidium { revert ExceedMaxVerifyBatches(); } + // Check sequence Number + if (sequenceNumber != currentSequenceNumber) { + revert SequenceNumberInvalid(); + } + + // Check max sequence timestamp inside of range + if ( + uint256(maxSequenceTimestamp) > (block.timestamp + TIMESTAMP_RANGE) + ) { + revert MaxTimestampSequenceInvalid(); + } + + // Update sequence number + sequenceNumber++; + // Update global exit root if there are new deposits bridgeAddress.updateGlobalExitRoot(); @@ -170,7 +193,7 @@ contract PolygonValidiumEtrog is PolygonRollupBaseEtrog, IPolygonValidium { currentAccInputHash, currentBatch.transactionsHash, l1InfoRoot, - uint64(block.timestamp), + maxSequenceTimestamp, l2Coinbase, bytes32(0) ) @@ -236,12 +259,19 @@ contract PolygonValidiumEtrog is PolygonRollupBaseEtrog, IPolygonValidium { */ function sequenceBatches( BatchData[] calldata batches, + uint64 maxSequenceTimestamp, + uint256 currentSequenceNumber, address l2Coinbase ) public override { if (!isSequenceWithDataAvailabilityAllowed) { revert SequenceWithDataAvailabilityNotAllowed(); } - super.sequenceBatches(batches, l2Coinbase); + super.sequenceBatches( + batches, + maxSequenceTimestamp, + currentSequenceNumber, + l2Coinbase + ); } ////////////////// diff --git a/contracts/v2/interfaces/IPolygonZkEVMVEtrogErrors.sol b/contracts/v2/interfaces/IPolygonZkEVMVEtrogErrors.sol index 7ae9c705f..f997c2f4c 100644 --- a/contracts/v2/interfaces/IPolygonZkEVMVEtrogErrors.sol +++ b/contracts/v2/interfaces/IPolygonZkEVMVEtrogErrors.sol @@ -43,4 +43,14 @@ interface IPolygonZkEVMVEtrogErrors is IPolygonZkEVMErrors { * @dev Thrown when the try to update the force batch address once is set to address(0) */ error ForceBatchesDecentralized(); + + /** + * @dev Thrown when the sequence number does not match with the one on the contract + */ + error SequenceNumberInvalid(); + + /** + * @dev Thrown when the max timestamp is out of range + */ + error MaxTimestampSequenceInvalid(); } diff --git a/contracts/v2/lib/PolygonRollupBaseEtrog.sol b/contracts/v2/lib/PolygonRollupBaseEtrog.sol index 00eb9e6c6..8d42f48fa 100644 --- a/contracts/v2/lib/PolygonRollupBaseEtrog.sol +++ b/contracts/v2/lib/PolygonRollupBaseEtrog.sol @@ -133,6 +133,9 @@ contract PolygonRollupBaseEtrog is 0xa40D5f56745a118D0906a34E69aeC8C0Db1cB8fA ); + // Timestamp range that's given to the sequencer as a safety measure to avoid reverts if the transaction is mined to quickly + uint256 public constant TIMESTAMP_RANGE = 36; + // POL token address IERC20Upgradeable public immutable pol; @@ -188,6 +191,15 @@ contract PolygonRollupBaseEtrog is // Native network of the token address of the gas tokena address. This variable it's just for read purposes uint32 public gasTokenNetwork; + // Sequence number, usedas a safety measure for the sequencer, to avoid possible problems with reorgs + uint256 public sequenceNumber; + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + */ + uint256[50] private _gap; + /** * @dev Emitted when the trusted sequencer sends a new batch of transactions */ @@ -406,11 +418,17 @@ contract PolygonRollupBaseEtrog is /** * @notice Allows a sequencer to send multiple batches * @param batches Struct array which holds the necessary data to append new batches to the sequence + * @param maxSequenceTimestamp Max timestamp of the sequence. This timestamp must be inside a safety range (actual + 36 seconds). + * This timestamp should be equal or higher of the last block inside the sequence, otherwise this batch will be invalidated by circuit. + * @param currentSequenceNumber This parameter must match the current sequenceNumber, which will be a counter of sequences. + * This will be a protection for the sequencer to avoid sending undesired data * @param l2Coinbase Address that will receive the fees from L2 * note Pol is not a reentrant token */ function sequenceBatches( BatchData[] calldata batches, + uint64 maxSequenceTimestamp, + uint256 currentSequenceNumber, address l2Coinbase ) public virtual onlyTrustedSequencer { uint256 batchesNum = batches.length; @@ -422,12 +440,26 @@ contract PolygonRollupBaseEtrog is revert ExceedMaxVerifyBatches(); } + // Check sequence Number + if (sequenceNumber != currentSequenceNumber) { + revert SequenceNumberInvalid(); + } + + // Check max sequence timestamp inside of range + if ( + uint256(maxSequenceTimestamp) > (block.timestamp + TIMESTAMP_RANGE) + ) { + revert MaxTimestampSequenceInvalid(); + } + + // Update sequence number + sequenceNumber++; + // Update global exit root if there are new deposits bridgeAddress.updateGlobalExitRoot(); // Get global batch variables bytes32 l1InfoRoot = globalExitRootManager.getRoot(); - uint64 currentTimestamp = uint64(block.timestamp); // Store storage variables in memory, to save gas, because will be overrided multiple times uint64 currentLastForceBatchSequenced = lastForceBatchSequenced; @@ -496,7 +528,7 @@ contract PolygonRollupBaseEtrog is currentAccInputHash, currentTransactionsHash, l1InfoRoot, - currentTimestamp, + maxSequenceTimestamp, l2Coinbase, bytes32(0) )