Skip to content
Closed
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import { IDisputeGame } from "interfaces/dispute/IDisputeGame.sol";
import { ISuperFaultDisputeGame } from "interfaces/dispute/ISuperFaultDisputeGame.sol";
import { IAnchorStateRegistry } from "interfaces/dispute/IAnchorStateRegistry.sol";

/// @title IDelegatedDisputeGame
/// @notice Minimal interface for DelegatedDisputeGame, used by AnchorStateRegistry
/// to check SuperGame validity.
interface IDelegatedDisputeGame is IDisputeGame {
/// @notice Returns the super game this delegated game is linked to.
/// @return superGame_ The super fault dispute game.
function superGame() external view returns (ISuperFaultDisputeGame superGame_);

/// @notice Returns the chain ID this delegated game is for.
/// @return chainId_ The chain ID.
function chainId() external view returns (uint256 chainId_);

/// @notice Returns the anchor state registry.
/// @return registry_ The anchor state registry.
function anchorStateRegistry() external view returns (IAnchorStateRegistry registry_);

/// @notice Returns the superchain-level anchor state registry.
/// @return registry_ The superchain anchor state registry.
function superchainRegistry() external view returns (IAnchorStateRegistry registry_);
}
27 changes: 27 additions & 0 deletions packages/contracts-bedrock/src/dispute/AnchorStateRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ import { IDisputeGame } from "interfaces/dispute/IDisputeGame.sol";
import { IDisputeGameFactory } from "interfaces/dispute/IDisputeGameFactory.sol";
import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol";
import { ISuperchainConfig } from "interfaces/L1/ISuperchainConfig.sol";
import { ISuperFaultDisputeGame } from "interfaces/dispute/ISuperFaultDisputeGame.sol";
import { IAnchorStateRegistry } from "interfaces/dispute/IAnchorStateRegistry.sol";
import { IDelegatedDisputeGame } from "interfaces/dispute/IDelegatedDisputeGame.sol";

/// @custom:proxied true
/// @title AnchorStateRegistry
Expand Down Expand Up @@ -281,6 +284,30 @@ contract AnchorStateRegistry is ProxyAdminOwnedBase, Initializable, Reinitializa
return false;
}

// For DelegatedDisputeGames, also check SuperGame validity.
// If the SuperGame is not registered, blacklisted, or retired, the DelegatedDisputeGame is also invalid.
try IDelegatedDisputeGame(address(_game)).superGame() returns (ISuperFaultDisputeGame superGame) {
IAnchorStateRegistry superRegistry = superGame.anchorStateRegistry();

// SuperGame must be registered in the superchain DisputeGameFactory.
// This prevents fake SuperGames from being used.
if (!superRegistry.isGameRegistered(IDisputeGame(address(superGame)))) {
return false;
}

// SuperGame must not be blacklisted.
if (superRegistry.isGameBlacklisted(IDisputeGame(address(superGame)))) {
return false;
}

// SuperGame must not be retired.
if (superRegistry.isGameRetired(IDisputeGame(address(superGame)))) {
return false;
}
} catch {
// Not a DelegatedDisputeGame, that's fine.
}

return true;
}

Expand Down
Loading
Loading