@@ -257,6 +257,7 @@ contract AnchorStateRegistry_IsGameProper_Test is AnchorStateRegistry_Init {
257257 }
258258
259259 /// @notice Tests that isGameProper will return false if the game is not the respected game type.
260+ /// @param _gameType The game type to use for the test.
260261 function testFuzz_isGameProper_isNotRespected_succeeds (GameType _gameType ) public {
261262 if (_gameType.raw () == gameProxy.gameType ().raw ()) {
262263 _gameType = GameType.wrap (_gameType.raw () + 1 );
@@ -283,6 +284,7 @@ contract AnchorStateRegistry_IsGameProper_Test is AnchorStateRegistry_Init {
283284 }
284285
285286 /// @notice Tests that isGameProper will return false if the game is retired.
287+ /// @param _retirementTimestamp The retirement timestamp to use for the test.
286288 function testFuzz_isGameProper_isRetired_succeeds (uint64 _retirementTimestamp ) public {
287289 // Make sure retirement timestamp is later than the game's creation time.
288290 _retirementTimestamp = uint64 (bound (_retirementTimestamp, gameProxy.createdAt ().raw () + 1 , type (uint64 ).max));
@@ -298,6 +300,200 @@ contract AnchorStateRegistry_IsGameProper_Test is AnchorStateRegistry_Init {
298300 }
299301}
300302
303+ contract AnchorStateRegistry_IsGameResolved_Test is AnchorStateRegistry_Init {
304+ /// @notice Tests that isGameResolved will return true if the game is resolved.
305+ /// @param _resolvedAtTimestamp The resolvedAt timestamp to use for the test.
306+ function testFuzz_isGameResolved_challengerWins_succeeds (uint256 _resolvedAtTimestamp ) public {
307+ // Bound resolvedAt to be less than or equal to current timestamp.
308+ _resolvedAtTimestamp = bound (_resolvedAtTimestamp, 0 , block .timestamp );
309+
310+ // Mock the resolvedAt timestamp.
311+ vm.mockCall (address (gameProxy), abi.encodeCall (gameProxy.resolvedAt, ()), abi.encode (_resolvedAtTimestamp));
312+
313+ // Mock the status to be CHALLENGER_WINS.
314+ vm.mockCall (address (gameProxy), abi.encodeCall (gameProxy.status, ()), abi.encode (GameStatus.CHALLENGER_WINS));
315+
316+ // Game should be resolved.
317+ assertTrue (anchorStateRegistry.isGameResolved (gameProxy));
318+ }
319+
320+ /// @notice Tests that isGameResolved will return true if the game is resolved.
321+ /// @param _resolvedAtTimestamp The resolvedAt timestamp to use for the test.
322+ function testFuzz_isGameResolved_defenderWins_succeeds (uint256 _resolvedAtTimestamp ) public {
323+ // Bound resolvedAt to be less than or equal to current timestamp.
324+ _resolvedAtTimestamp = bound (_resolvedAtTimestamp, 0 , block .timestamp );
325+
326+ // Mock the resolvedAt timestamp.
327+ vm.mockCall (address (gameProxy), abi.encodeCall (gameProxy.resolvedAt, ()), abi.encode (_resolvedAtTimestamp));
328+
329+ // Mock the status to be DEFENDER_WINS.
330+ vm.mockCall (address (gameProxy), abi.encodeCall (gameProxy.status, ()), abi.encode (GameStatus.DEFENDER_WINS));
331+
332+ // Game should be resolved.
333+ assertTrue (anchorStateRegistry.isGameResolved (gameProxy));
334+ }
335+
336+ /// @notice Tests that isGameResolved will return false if the game is in progress and not resolved.
337+ /// @param _resolvedAtTimestamp The resolvedAt timestamp to use for the test.
338+ function testFuzz_isGameResolved_inProgressNotResolved_succeeds (uint256 _resolvedAtTimestamp ) public {
339+ // Bound resolvedAt to be less than or equal to current timestamp.
340+ _resolvedAtTimestamp = bound (_resolvedAtTimestamp, 0 , block .timestamp );
341+
342+ // Mock the resolvedAt timestamp.
343+ vm.mockCall (address (gameProxy), abi.encodeCall (gameProxy.resolvedAt, ()), abi.encode (_resolvedAtTimestamp));
344+
345+ // Mock the status to be IN_PROGRESS.
346+ vm.mockCall (address (gameProxy), abi.encodeCall (gameProxy.status, ()), abi.encode (GameStatus.IN_PROGRESS));
347+
348+ // Game should not be resolved.
349+ assertFalse (anchorStateRegistry.isGameResolved (gameProxy));
350+ }
351+ }
352+
353+ contract AnchorStateRegistry_IsGameAirgapped_TestFail is AnchorStateRegistry_Init {
354+ /// @notice Tests that isGameAirgapped will return true if the game is airgapped.
355+ /// @param _resolvedAtTimestamp The resolvedAt timestamp to use for the test.
356+ function testFuzz_isGameAirgapped_isAirgapped_succeeds (uint256 _resolvedAtTimestamp ) public {
357+ // Warp forward by disputeGameFinalityDelaySeconds.
358+ vm.warp (block .timestamp + optimismPortal2.disputeGameFinalityDelaySeconds ());
359+
360+ // Bound resolvedAt to be at least disputeGameFinalityDelaySeconds in the past.
361+ _resolvedAtTimestamp = bound (_resolvedAtTimestamp, 0 , block .timestamp - optimismPortal2.disputeGameFinalityDelaySeconds () - 1 );
362+
363+ // Mock the resolvedAt timestamp.
364+ vm.mockCall (address (gameProxy), abi.encodeCall (gameProxy.resolvedAt, ()), abi.encode (_resolvedAtTimestamp));
365+
366+ // Game should be airgapped.
367+ assertTrue (anchorStateRegistry.isGameAirgapped (gameProxy));
368+ }
369+
370+ /// @notice Tests that isGameAirgapped will return false if the game is not airgapped.
371+ /// @param _resolvedAtTimestamp The resolvedAt timestamp to use for the test.
372+ function testFuzz_isGameAirgapped_isNotAirgapped_succeeds (uint256 _resolvedAtTimestamp ) public {
373+ // Warp forward by disputeGameFinalityDelaySeconds.
374+ vm.warp (block .timestamp + optimismPortal2.disputeGameFinalityDelaySeconds ());
375+
376+ // Bound resolvedAt to be less than disputeGameFinalityDelaySeconds in the past.
377+ _resolvedAtTimestamp = bound (_resolvedAtTimestamp, block .timestamp - optimismPortal2.disputeGameFinalityDelaySeconds (), block .timestamp );
378+
379+ // Mock the resolvedAt timestamp.
380+ vm.mockCall (address (gameProxy), abi.encodeCall (gameProxy.resolvedAt, ()), abi.encode (_resolvedAtTimestamp));
381+
382+ // Game should not be airgapped.
383+ assertFalse (anchorStateRegistry.isGameAirgapped (gameProxy));
384+ }
385+ }
386+
387+ contract AnchorStateRegistry_IsGameClaimValid_Test is AnchorStateRegistry_Init {
388+ /// @notice Tests that isGameClaimValid will return true if the game claim is valid.
389+ /// @param _resolvedAtTimestamp The resolvedAt timestamp to use for the test.
390+ function testFuzz_isGameClaimValid_claimIsValid_succeeds (uint256 _resolvedAtTimestamp ) public {
391+ // Warp forward by disputeGameFinalityDelaySeconds.
392+ vm.warp (block .timestamp + optimismPortal2.disputeGameFinalityDelaySeconds ());
393+
394+ // Bound resolvedAt to be at least disputeGameFinalityDelaySeconds in the past.
395+ _resolvedAtTimestamp = bound (_resolvedAtTimestamp, 0 , block .timestamp - optimismPortal2.disputeGameFinalityDelaySeconds () - 1 );
396+
397+ // Mock that the game was respected.
398+ vm.mockCall (address (gameProxy), abi.encodeCall (gameProxy.wasRespectedGameTypeWhenCreated, ()), abi.encode (true ));
399+
400+ // Mock the resolvedAt timestamp.
401+ vm.mockCall (address (gameProxy), abi.encodeCall (gameProxy.resolvedAt, ()), abi.encode (_resolvedAtTimestamp));
402+
403+ // Mock the status to be DEFENDER_WINS.
404+ vm.mockCall (address (gameProxy), abi.encodeCall (gameProxy.status, ()), abi.encode (GameStatus.DEFENDER_WINS));
405+
406+ // Claim should be valid.
407+ assertTrue (anchorStateRegistry.isGameClaimValid (gameProxy));
408+ }
409+
410+ /// @notice Tests that isGameClaimValid will return false if the game is not registered.
411+ function testFuzz_isGameClaimValid_notRegistered_succeeds () public {
412+ // Mock the DisputeGameFactory to make it seem that the game was not registered.
413+ vm.mockCall (
414+ address (disputeGameFactory),
415+ abi.encodeCall (
416+ disputeGameFactory.games, (gameProxy.gameType (), gameProxy.rootClaim (), gameProxy.extraData ())
417+ ),
418+ abi.encode (address (0 ), 0 )
419+ );
420+
421+ // Claim should not be valid.
422+ assertFalse (anchorStateRegistry.isGameClaimValid (gameProxy));
423+ }
424+
425+ /// @notice Tests that isGameClaimValid will return false if the game is not respected.
426+ /// @param _gameType The game type to use for the test.
427+ function testFuzz_isGameClaimValid_isNotRespected_succeeds (GameType _gameType ) public {
428+ if (_gameType.raw () == gameProxy.gameType ().raw ()) {
429+ _gameType = GameType.wrap (_gameType.raw () + 1 );
430+ }
431+
432+ // Mock that the game was not respected.
433+ vm.mockCall (
434+ address (gameProxy), abi.encodeCall (gameProxy.wasRespectedGameTypeWhenCreated, ()), abi.encode (false )
435+ );
436+
437+ // Claim should not be valid.
438+ assertFalse (anchorStateRegistry.isGameClaimValid (gameProxy));
439+ }
440+
441+ /// @notice Tests that isGameClaimValid will return false if the game is blacklisted.
442+ function testFuzz_isGameClaimValid_isBlacklisted_succeeds () public {
443+ // Mock the disputeGameBlacklist call to return true.
444+ vm.mockCall (
445+ address (optimismPortal2),
446+ abi.encodeCall (optimismPortal2.disputeGameBlacklist, (gameProxy)),
447+ abi.encode (true )
448+ );
449+
450+ // Claim should not be valid.
451+ assertFalse (anchorStateRegistry.isGameClaimValid (gameProxy));
452+ }
453+
454+ /// @notice Tests that isGameClaimValid will return false if the game is retired.
455+ /// @param _resolvedAtTimestamp The resolvedAt timestamp to use for the test.
456+ function testFuzz_isGameClaimValid_isRetired_succeeds (uint256 _resolvedAtTimestamp ) public {
457+ // Make sure retirement timestamp is later than the game's creation time.
458+ _resolvedAtTimestamp = uint64 (bound (_resolvedAtTimestamp, gameProxy.createdAt ().raw () + 1 , type (uint64 ).max));
459+
460+ // Mock the respectedGameTypeUpdatedAt call to be later than the game's creation time.
461+ vm.mockCall (
462+ address (optimismPortal2),
463+ abi.encodeCall (optimismPortal2.respectedGameTypeUpdatedAt, ()),
464+ abi.encode (_resolvedAtTimestamp)
465+ );
466+
467+ // Claim should not be valid.
468+ assertFalse (anchorStateRegistry.isGameClaimValid (gameProxy));
469+ }
470+
471+ /// @notice Tests that isGameClaimValid will return false if the game is not resolved.
472+ function testFuzz_isGameClaimValid_notResolved_succeeds () public {
473+ // Mock the status to be IN_PROGRESS.
474+ vm.mockCall (address (gameProxy), abi.encodeCall (gameProxy.status, ()), abi.encode (GameStatus.IN_PROGRESS));
475+
476+ // Claim should not be valid.
477+ assertFalse (anchorStateRegistry.isGameClaimValid (gameProxy));
478+ }
479+
480+ /// @notice Tests that isGameClaimValid will return false if the game is not airgapped.
481+ /// @param _resolvedAtTimestamp The resolvedAt timestamp to use for the test.
482+ function testFuzz_isGameClaimValid_notAirgapped_succeeds (uint256 _resolvedAtTimestamp ) public {
483+ // Warp forward by disputeGameFinalityDelaySeconds.
484+ vm.warp (block .timestamp + optimismPortal2.disputeGameFinalityDelaySeconds ());
485+
486+ // Bound resolvedAt to be less than disputeGameFinalityDelaySeconds in the past.
487+ _resolvedAtTimestamp = bound (_resolvedAtTimestamp, block .timestamp - optimismPortal2.disputeGameFinalityDelaySeconds (), block .timestamp );
488+
489+ // Mock the resolvedAt timestamp.
490+ vm.mockCall (address (gameProxy), abi.encodeCall (gameProxy.resolvedAt, ()), abi.encode (_resolvedAtTimestamp));
491+
492+ // Claim should not be valid.
493+ assertFalse (anchorStateRegistry.isGameClaimValid (gameProxy));
494+ }
495+ }
496+
301497contract AnchorStateRegistry_SetAnchorState_Test is AnchorStateRegistry_Init {
302498 /// @notice Tests that setAnchorState will succeed if the game is valid, the game block
303499 /// number is greater than the current anchor root block number, and the game is the
0 commit comments