@@ -124,9 +124,6 @@ contract ScrollChain is OwnableUpgradeable, PausableUpgradeable, IScrollChain {
124124 /// @dev Thrown when update size for finalized batch.
125125 error ErrorUseFinalizedBatch ();
126126
127- /// @dev Thrown when batch index is smaller than previous `BundleSizeStruct.batchIndex`.
128- error ErrorBatchIndexSmallerThanPreviousOne ();
129-
130127 /// @dev Thrown when batch index delta is not multiple of previous `BundleSizeStruct.bundleSize`.
131128 error ErrorBatchIndexDeltaNotMultipleOfBundleSize ();
132129
@@ -159,7 +156,7 @@ contract ScrollChain is OwnableUpgradeable, PausableUpgradeable, IScrollChain {
159156
160157 /// @notice The duration to delay proof when we only has one proof type.
161158 /// @dev This is enabled after Euclid upgrade.
162- uint256 public emergencyFinalizationDelay;
159+ uint256 public immutable emergencyFinalizationDelay;
163160
164161 /*********
165162 * Enums *
@@ -900,7 +897,8 @@ contract ScrollChain is OwnableUpgradeable, PausableUpgradeable, IScrollChain {
900897 if (last.batchIndex > cachedLastTeeVerifiedBatchIndex && last.batchIndex > cachedLastZkpVerifiedBatchIndex) {
901898 // last is future batch index, we override the last one
902899 BundleSizeStruct memory prev = bundleSize[index - 1 ];
903- if (batchIndex <= prev.batchIndex) revert ErrorBatchIndexSmallerThanPreviousOne ();
900+ // since prev.batchIndex <= max(lastTeeVerifiedBatchIndex, lastZkpVerifiedBatchIndex)
901+ // we always have batchIndex > prev.batchIndex
904902 if ((batchIndex - prev.batchIndex) % prev.bundleSize != 0 ) {
905903 revert ErrorBatchIndexDeltaNotMultipleOfBundleSize ();
906904 }
@@ -909,7 +907,9 @@ contract ScrollChain is OwnableUpgradeable, PausableUpgradeable, IScrollChain {
909907 bundleSize[index] = last;
910908 } else {
911909 // last is past batch index, we append a new one
912- if (batchIndex <= last.batchIndex) revert ErrorBatchIndexSmallerThanPreviousOne ();
910+ // since batchIndex > max(lastTeeVerifiedBatchIndex, lastZkpVerifiedBatchIndex) and
911+ // last.batchIndex <= max(lastTeeVerifiedBatchIndex, lastZkpVerifiedBatchIndex)
912+ // we always have batchIndex > last.batchIndex
913913 if ((batchIndex - last.batchIndex) % last.bundleSize != 0 ) {
914914 revert ErrorBatchIndexDeltaNotMultipleOfBundleSize ();
915915 }
@@ -1054,28 +1054,50 @@ contract ScrollChain is OwnableUpgradeable, PausableUpgradeable, IScrollChain {
10541054 bytes32 _withdrawRoot ,
10551055 uint256 _totalL1MessagesPoppedOverall
10561056 ) internal {
1057- uint256 counterpartVerifiedBatchIndex = _proofType == ProofType.ZkProof
1058- ? lastTeeVerifiedBatchIndex
1059- : lastZkpVerifiedBatchIndex;
1060- if (_batchIndex <= counterpartVerifiedBatchIndex) {
1061- // The zk proof is behind tee proof, we compare state roots here
1062- if (_postStateRoot != finalizedStateRoots[_batchIndex] || withdrawRoots[_batchIndex] != _withdrawRoot) {
1063- unresolvedState.proofType = _proofType;
1064- unresolvedState.batchIndex = uint248 (_batchIndex);
1065- unresolvedState.stateRoot = _postStateRoot;
1066- unresolvedState.withdrawRoot = _withdrawRoot;
1067- emit StateMismatch (_batchIndex, _postStateRoot, _withdrawRoot);
1057+ bool counterpartProofEnabled;
1058+ {
1059+ uint256 mask = enabledProofTypeMask;
1060+ mask ^= 1 << uint256 (uint8 (_proofType));
1061+ counterpartProofEnabled = mask > 0 ;
1062+ }
1063+ bool overrideStateRoot = false ;
1064+ bool finalizeBundle = false ;
1065+ if (counterpartProofEnabled) {
1066+ uint256 counterpartVerifiedBatchIndex = _proofType == ProofType.ZkProof
1067+ ? lastTeeVerifiedBatchIndex
1068+ : lastZkpVerifiedBatchIndex;
1069+ if (_batchIndex <= counterpartVerifiedBatchIndex) {
1070+ // The current proof is behind counterpart proof, we compare state roots here
1071+ if (_postStateRoot != finalizedStateRoots[_batchIndex] || withdrawRoots[_batchIndex] != _withdrawRoot) {
1072+ unresolvedState.proofType = _proofType;
1073+ unresolvedState.batchIndex = uint248 (_batchIndex);
1074+ unresolvedState.stateRoot = _postStateRoot;
1075+ unresolvedState.withdrawRoot = _withdrawRoot;
1076+ emit StateMismatch (_batchIndex, _postStateRoot, _withdrawRoot);
1077+ } else {
1078+ finalizeBundle = true ;
1079+ }
10681080 } else {
1069- // state roots matched, mark bundle finalized.
1070- _finalizePoppedL1Messages (_totalL1MessagesPoppedOverall);
1071- emit FinalizeBatch (_batchIndex, _batchHash, _postStateRoot, _withdrawRoot);
1081+ overrideStateRoot = true ;
10721082 }
10731083 } else {
1074- // The current proof is ahead counterpart proof, we record state roots here.
1075- // And we do not store intermediate finalized roots.
1084+ overrideStateRoot = true ;
1085+ finalizeBundle = true ;
1086+ }
1087+ // override state root, when
1088+ // 1. we only has this type proof enabled; or
1089+ // 2. current proof ahead counterpart proof.
1090+ if (overrideStateRoot) {
10761091 finalizedStateRoots[_batchIndex] = _postStateRoot;
10771092 withdrawRoots[_batchIndex] = _withdrawRoot;
10781093 }
1094+ // finalize bundle, when
1095+ // 1. we only has this type proof enabled; or
1096+ // 2. current proof behind counterpart proof and state root matches.
1097+ if (finalizeBundle) {
1098+ _finalizePoppedL1Messages (_totalL1MessagesPoppedOverall);
1099+ emit FinalizeBatch (_batchIndex, _batchHash, _postStateRoot, _withdrawRoot);
1100+ }
10791101 }
10801102
10811103 /* This function will never be used since we already upgrade to Darwin. We comment out the codes for reference.
0 commit comments