Skip to content

Commit d218045

Browse files
committed
feat: improvements to the passPhase() logic, thanks to feedback from @unknownunknown1
1 parent b79179b commit d218045

File tree

3 files changed

+25
-21
lines changed

3 files changed

+25
-21
lines changed

contracts/src/arbitration/KlerosCore.sol

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -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.

contracts/src/arbitration/dispute-kits/DisputeKitClassic.sol

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -185,10 +185,9 @@ contract DisputeKitClassic is BaseDisputeKit, IEvidence {
185185
}
186186

187187
/** @dev Passes the phase.
188-
* Note: Invariant: do not emit a `NewPhaseDisputeKit` event if the phase is unchanged.
189188
*/
190189
function passPhase() external override {
191-
if (core.phase() == KlerosCore.Phase.staking || core.isFreezingPhaseFinished()) {
190+
if (core.phase() == KlerosCore.Phase.staking || core.freezingPhaseTimeout()) {
192191
require(phase != Phase.resolving, "Already in Resolving phase");
193192
phase = Phase.resolving; // Safety net.
194193
} else if (core.phase() == KlerosCore.Phase.freezing) {
@@ -204,10 +203,11 @@ contract DisputeKitClassic is BaseDisputeKit, IEvidence {
204203
require(RN != 0, "Random number is not ready yet");
205204
phase = Phase.drawing;
206205
} else if (phase == Phase.drawing) {
207-
require(disputesWithoutJurors == 0 || core.isFreezingPhaseFinished(), "Not ready for Resolving phase");
206+
require(disputesWithoutJurors == 0, "Not ready for Resolving phase");
208207
phase = Phase.resolving;
209208
}
210209
}
210+
// Should not be reached if the phase is unchanged.
211211
emit NewPhaseDisputeKit(phase);
212212
}
213213

contracts/src/arbitration/dispute-kits/DisputeKitSybilResistant.sol

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -203,10 +203,9 @@ contract DisputeKitSybilResistant is BaseDisputeKit, IEvidence {
203203
}
204204

205205
/** @dev Passes the phase.
206-
* Note: Invariant: do not emit a `NewPhaseDisputeKit` event if the phase is unchanged.
207206
*/
208207
function passPhase() external override {
209-
if (core.phase() == KlerosCore.Phase.staking || core.isFreezingPhaseFinished()) {
208+
if (core.phase() == KlerosCore.Phase.staking || core.freezingPhaseTimeout()) {
210209
require(phase != Phase.resolving, "Already in Resolving phase");
211210
phase = Phase.resolving; // Safety net.
212211
} else if (core.phase() == KlerosCore.Phase.freezing) {
@@ -222,10 +221,11 @@ contract DisputeKitSybilResistant is BaseDisputeKit, IEvidence {
222221
require(RN != 0, "Random number is not ready yet");
223222
phase = Phase.drawing;
224223
} else if (phase == Phase.drawing) {
225-
require(disputesWithoutJurors == 0 || core.isFreezingPhaseFinished(), "Not ready for Resolving phase");
224+
require(disputesWithoutJurors == 0, "Not ready for Resolving phase");
226225
phase = Phase.resolving;
227226
}
228227
}
228+
// Should not be reached if the phase is unchanged.
229229
emit NewPhaseDisputeKit(phase);
230230
}
231231

0 commit comments

Comments
 (0)