@@ -514,40 +514,44 @@ contract KlerosCore is IArbitrator {
514514 }
515515
516516 /** @dev Switches the phases between Staking and Freezing, also signal the switch to the dispute kits.
517- * Note: Invariant: do not emit a `NewPhase` event if the phase is unchanged.
518517 */
519518 function passPhase () external {
520519 if (phase == Phase.staking) {
521520 require (block .timestamp - lastPhaseChange >= minStakingTime, "The minimal staking time has not passed yet " );
522521 require (disputesKitIDsThatNeedFreezing.length > 0 , "There are no dispute kit which need freezing " );
523-
524522 phase = Phase.freezing;
525523 freezeBlock = block .number ;
526- lastPhaseChange = block . timestamp ;
527- emit NewPhase ( phase);
528- } else if (phase == Phase.freezing) {
529- bool freezingPhaseFinished = block . timestamp - lastPhaseChange >= maxFreezingTime;
530- for ( uint256 i = disputesKitIDsThatNeedFreezing. length - 1 ; i >= 0 ; -- i) {
531- IDisputeKit disputeKit = disputeKitNodes[disputesKitIDsThatNeedFreezing[i ]].disputeKit;
524+ } else {
525+ // phase == Phase.freezing
526+ bool freezingPhaseFinished = this . freezingPhaseTimeout ();
527+ for ( int256 i = int256 (disputesKitIDsThatNeedFreezing. length ) - 1 ; i >= 0 ; -- i) {
528+ uint256 disputeKitID = disputesKitIDsThatNeedFreezing[ uint256 (i)];
529+ IDisputeKit disputeKit = disputeKitNodes[disputesKitIDsThatNeedFreezing[uint256 (i) ]].disputeKit;
532530 if (freezingPhaseFinished && ! disputeKit.isResolving ()) {
533531 // Force the dispute kit to be ready for Staking phase.
534- disputeKit.passPhase (); // Warning: don't call if already in Resolving phase, because it reverts.
532+ disputeKit.passPhase (); // Should not be called if already in Resolving phase, because it reverts.
535533 require (disputeKit.isResolving (), "A dispute kit has not passed to Resolving phase " );
536534 } else {
537535 // Check if the dispute kit is ready for Staking phase.
538536 require (disputeKit.isResolving (), "A dispute kit has not passed to Resolving phase " );
539-
540537 if (disputeKit.disputesWithoutJurors () == 0 ) {
541538 // The dispute kit had time to finish drawing jurors for all its disputes.
542- disputeKitNodes[disputesKitIDsThatNeedFreezing[i]].needsFreezing = false ;
539+ disputeKitNodes[disputeKitID].needsFreezing = false ;
540+ if (i < int256 (disputesKitIDsThatNeedFreezing.length ) - 1 ) {
541+ // This is not the last element so copy the last element to the current one, then pop.
542+ disputesKitIDsThatNeedFreezing[uint256 (i)] = disputesKitIDsThatNeedFreezing[
543+ disputesKitIDsThatNeedFreezing.length - 1
544+ ];
545+ }
543546 disputesKitIDsThatNeedFreezing.pop ();
544547 }
545548 }
546549 }
547550 phase = Phase.staking;
548- lastPhaseChange = block .timestamp ;
549- emit NewPhase (phase);
550551 }
552+ // Should not be reached if the phase is unchanged.
553+ lastPhaseChange = block .timestamp ;
554+ emit NewPhase (phase);
551555 }
552556
553557 /** @dev Passes the period of a specified dispute.
@@ -1002,8 +1006,8 @@ contract KlerosCore is IArbitrator {
10021006 return freezeBlock;
10031007 }
10041008
1005- function isFreezingPhaseFinished () external view returns (bool ) {
1006- return block .timestamp - lastPhaseChange >= maxFreezingTime;
1009+ function freezingPhaseTimeout () external view returns (bool ) {
1010+ return phase == Phase.freezing && block .timestamp - lastPhaseChange >= maxFreezingTime;
10071011 }
10081012
10091013 /** @dev Returns true if the dispute kit will be switched to a parent DK.
0 commit comments