@@ -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,206 @@ 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, 1 , 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, 1 , 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, 1 , 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 =
362+ bound (_resolvedAtTimestamp, 0 , block .timestamp - optimismPortal2.disputeGameFinalityDelaySeconds () - 1 );
363+
364+ // Mock the resolvedAt timestamp.
365+ vm.mockCall (address (gameProxy), abi.encodeCall (gameProxy.resolvedAt, ()), abi.encode (_resolvedAtTimestamp));
366+
367+ // Game should be airgapped.
368+ assertTrue (anchorStateRegistry.isGameAirgapped (gameProxy));
369+ }
370+
371+ /// @notice Tests that isGameAirgapped will return false if the game is not airgapped.
372+ /// @param _resolvedAtTimestamp The resolvedAt timestamp to use for the test.
373+ function testFuzz_isGameAirgapped_isNotAirgapped_succeeds (uint256 _resolvedAtTimestamp ) public {
374+ // Warp forward by disputeGameFinalityDelaySeconds.
375+ vm.warp (block .timestamp + optimismPortal2.disputeGameFinalityDelaySeconds ());
376+
377+ // Bound resolvedAt to be less than disputeGameFinalityDelaySeconds in the past.
378+ _resolvedAtTimestamp = bound (
379+ _resolvedAtTimestamp, block .timestamp - optimismPortal2.disputeGameFinalityDelaySeconds (), block .timestamp
380+ );
381+
382+ // Mock the resolvedAt timestamp.
383+ vm.mockCall (address (gameProxy), abi.encodeCall (gameProxy.resolvedAt, ()), abi.encode (_resolvedAtTimestamp));
384+
385+ // Game should not be airgapped.
386+ assertFalse (anchorStateRegistry.isGameAirgapped (gameProxy));
387+ }
388+ }
389+
390+ contract AnchorStateRegistry_IsGameClaimValid_Test is AnchorStateRegistry_Init {
391+ /// @notice Tests that isGameClaimValid will return true if the game claim is valid.
392+ /// @param _resolvedAtTimestamp The resolvedAt timestamp to use for the test.
393+ function testFuzz_isGameClaimValid_claimIsValid_succeeds (uint256 _resolvedAtTimestamp ) public {
394+ // Warp forward by disputeGameFinalityDelaySeconds.
395+ vm.warp (block .timestamp + optimismPortal2.disputeGameFinalityDelaySeconds ());
396+
397+ // Bound resolvedAt to be at least disputeGameFinalityDelaySeconds in the past.
398+ _resolvedAtTimestamp =
399+ bound (_resolvedAtTimestamp, 1 , block .timestamp - optimismPortal2.disputeGameFinalityDelaySeconds () - 1 );
400+
401+ // Mock that the game was respected.
402+ vm.mockCall (address (gameProxy), abi.encodeCall (gameProxy.wasRespectedGameTypeWhenCreated, ()), abi.encode (true ));
403+
404+ // Mock the resolvedAt timestamp.
405+ vm.mockCall (address (gameProxy), abi.encodeCall (gameProxy.resolvedAt, ()), abi.encode (_resolvedAtTimestamp));
406+
407+ // Mock the status to be DEFENDER_WINS.
408+ vm.mockCall (address (gameProxy), abi.encodeCall (gameProxy.status, ()), abi.encode (GameStatus.DEFENDER_WINS));
409+
410+ // Claim should be valid.
411+ assertTrue (anchorStateRegistry.isGameClaimValid (gameProxy));
412+ }
413+
414+ /// @notice Tests that isGameClaimValid will return false if the game is not registered.
415+ function testFuzz_isGameClaimValid_notRegistered_succeeds () public {
416+ // Mock the DisputeGameFactory to make it seem that the game was not registered.
417+ vm.mockCall (
418+ address (disputeGameFactory),
419+ abi.encodeCall (
420+ disputeGameFactory.games, (gameProxy.gameType (), gameProxy.rootClaim (), gameProxy.extraData ())
421+ ),
422+ abi.encode (address (0 ), 0 )
423+ );
424+
425+ // Claim should not be valid.
426+ assertFalse (anchorStateRegistry.isGameClaimValid (gameProxy));
427+ }
428+
429+ /// @notice Tests that isGameClaimValid will return false if the game is not respected.
430+ /// @param _gameType The game type to use for the test.
431+ function testFuzz_isGameClaimValid_isNotRespected_succeeds (GameType _gameType ) public {
432+ if (_gameType.raw () == gameProxy.gameType ().raw ()) {
433+ _gameType = GameType.wrap (_gameType.raw () + 1 );
434+ }
435+
436+ // Mock that the game was not respected.
437+ vm.mockCall (
438+ address (gameProxy), abi.encodeCall (gameProxy.wasRespectedGameTypeWhenCreated, ()), abi.encode (false )
439+ );
440+
441+ // Claim should not be valid.
442+ assertFalse (anchorStateRegistry.isGameClaimValid (gameProxy));
443+ }
444+
445+ /// @notice Tests that isGameClaimValid will return false if the game is blacklisted.
446+ function testFuzz_isGameClaimValid_isBlacklisted_succeeds () public {
447+ // Mock the disputeGameBlacklist call to return true.
448+ vm.mockCall (
449+ address (optimismPortal2),
450+ abi.encodeCall (optimismPortal2.disputeGameBlacklist, (gameProxy)),
451+ abi.encode (true )
452+ );
453+
454+ // Claim should not be valid.
455+ assertFalse (anchorStateRegistry.isGameClaimValid (gameProxy));
456+ }
457+
458+ /// @notice Tests that isGameClaimValid will return false if the game is retired.
459+ /// @param _resolvedAtTimestamp The resolvedAt timestamp to use for the test.
460+ function testFuzz_isGameClaimValid_isRetired_succeeds (uint256 _resolvedAtTimestamp ) public {
461+ // Make sure retirement timestamp is later than the game's creation time.
462+ _resolvedAtTimestamp = uint64 (bound (_resolvedAtTimestamp, gameProxy.createdAt ().raw () + 1 , type (uint64 ).max));
463+
464+ // Mock the respectedGameTypeUpdatedAt call to be later than the game's creation time.
465+ vm.mockCall (
466+ address (optimismPortal2),
467+ abi.encodeCall (optimismPortal2.respectedGameTypeUpdatedAt, ()),
468+ abi.encode (_resolvedAtTimestamp)
469+ );
470+
471+ // Claim should not be valid.
472+ assertFalse (anchorStateRegistry.isGameClaimValid (gameProxy));
473+ }
474+
475+ /// @notice Tests that isGameClaimValid will return false if the game is not resolved.
476+ function testFuzz_isGameClaimValid_notResolved_succeeds () public {
477+ // Mock the status to be IN_PROGRESS.
478+ vm.mockCall (address (gameProxy), abi.encodeCall (gameProxy.status, ()), abi.encode (GameStatus.IN_PROGRESS));
479+
480+ // Claim should not be valid.
481+ assertFalse (anchorStateRegistry.isGameClaimValid (gameProxy));
482+ }
483+
484+ /// @notice Tests that isGameClaimValid will return false if the game is not airgapped.
485+ /// @param _resolvedAtTimestamp The resolvedAt timestamp to use for the test.
486+ function testFuzz_isGameClaimValid_notAirgapped_succeeds (uint256 _resolvedAtTimestamp ) public {
487+ // Warp forward by disputeGameFinalityDelaySeconds.
488+ vm.warp (block .timestamp + optimismPortal2.disputeGameFinalityDelaySeconds ());
489+
490+ // Bound resolvedAt to be less than disputeGameFinalityDelaySeconds in the past.
491+ _resolvedAtTimestamp = bound (
492+ _resolvedAtTimestamp, block .timestamp - optimismPortal2.disputeGameFinalityDelaySeconds (), block .timestamp
493+ );
494+
495+ // Mock the resolvedAt timestamp.
496+ vm.mockCall (address (gameProxy), abi.encodeCall (gameProxy.resolvedAt, ()), abi.encode (_resolvedAtTimestamp));
497+
498+ // Claim should not be valid.
499+ assertFalse (anchorStateRegistry.isGameClaimValid (gameProxy));
500+ }
501+ }
502+
301503contract AnchorStateRegistry_SetAnchorState_Test is AnchorStateRegistry_Init {
302504 /// @notice Tests that setAnchorState will succeed if the game is valid, the game block
303505 /// number is greater than the current anchor root block number, and the game is the
0 commit comments