Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
pragma solidity ^0.8.0;

import { IDisputeGame } from "interfaces/dispute/IDisputeGame.sol";
import { IFaultDisputeGame } from "interfaces/dispute/IFaultDisputeGame.sol";
import { IDisputeGameFactory } from "interfaces/dispute/IDisputeGameFactory.sol";
import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol";
import { GameType, Hash, Proposal } from "src/dispute/lib/Types.sol";
Expand All @@ -14,14 +13,14 @@ interface IAnchorStateRegistry is IProxyAdminOwnedBase {
error AnchorStateRegistry_Unauthorized();
error ReinitializableBase_ZeroInitVersion();

event AnchorUpdated(IFaultDisputeGame indexed game);
event AnchorUpdated(IDisputeGame indexed game);
event DisputeGameBlacklisted(IDisputeGame indexed disputeGame);
event Initialized(uint8 version);
event RespectedGameTypeSet(GameType gameType);
event RetirementTimestampSet(uint256 timestamp);

function initVersion() external view returns (uint8);
function anchorGame() external view returns (IFaultDisputeGame);
function anchorGame() external view returns (IDisputeGame);
function anchors(GameType) external view returns (Hash, uint256);
function blacklistDisputeGame(IDisputeGame _disputeGame) external;
function disputeGameBlacklist(IDisputeGame) external view returns (bool);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"name": "anchorGame",
"outputs": [
{
"internalType": "contract IFaultDisputeGame",
"internalType": "contract IDisputeGame",
"name": "",
"type": "address"
}
Expand Down Expand Up @@ -495,7 +495,7 @@
"inputs": [
{
"indexed": true,
"internalType": "contract IFaultDisputeGame",
"internalType": "contract IDisputeGame",
"name": "game",
"type": "address"
}
Expand Down
4 changes: 2 additions & 2 deletions packages/contracts-bedrock/snapshots/semver-lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,8 @@
"sourceCodeHash": "0x03c160168986ffc8d26a90c37366e7ad6da03f49d83449e1f8b3de0f4b590f6f"
},
"src/dispute/AnchorStateRegistry.sol:AnchorStateRegistry": {
"initCodeHash": "0xc00fdb1a4ae0ec8d7a96ebaad38ffaee9d96b942ab2a56e0ce2f76639f79ae7c",
"sourceCodeHash": "0xd2837ddf6992926ced31ef1916f95ebb8cc2006e94b82c2287997e5397edfeaf"
"initCodeHash": "0x7d85ca3f30f6526a62214a6ef876299dcf15e536afe4f5dd7b232a92120e170f",
"sourceCodeHash": "0x896011529b7fdb6623a0b3f72b099f38229168f54514e674c6b3aa7afc35e4fc"
},
"src/dispute/DelayedWETH.sol:DelayedWETH": {
"initCodeHash": "0xa8f60e142108b33675a8f6b6979c73b96eea247884842d796f9f878904c0a906",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"label": "anchorGame",
"offset": 0,
"slot": "2",
"type": "contract IFaultDisputeGame"
"type": "contract IDisputeGame"
},
{
"bytes": "64",
Expand Down
38 changes: 11 additions & 27 deletions packages/contracts-bedrock/src/dispute/AnchorStateRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import { GameType, Proposal, Claim, GameStatus, Hash } from "src/dispute/lib/Typ

// Interfaces
import { ISemver } from "interfaces/universal/ISemver.sol";
import { IFaultDisputeGame } from "interfaces/dispute/IFaultDisputeGame.sol";
import { IDisputeGame } from "interfaces/dispute/IDisputeGame.sol";
import { IDisputeGameFactory } from "interfaces/dispute/IDisputeGameFactory.sol";
import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol";
Expand All @@ -25,8 +24,8 @@ import { ISuperchainConfig } from "interfaces/L1/ISuperchainConfig.sol";
/// be initialized with a more recent starting state which reduces the amount of required offchain computation.
contract AnchorStateRegistry is ProxyAdminOwnedBase, Initializable, ReinitializableBase, ISemver {
/// @notice Semantic version.
/// @custom:semver 3.7.0
string public constant version = "3.7.0";
/// @custom:semver 3.8.0
string public constant version = "3.8.0";

/// @notice The dispute game finality delay in seconds.
uint256 internal immutable DISPUTE_GAME_FINALITY_DELAY_SECONDS;
Expand All @@ -38,7 +37,7 @@ contract AnchorStateRegistry is ProxyAdminOwnedBase, Initializable, Reinitializa
IDisputeGameFactory public disputeGameFactory;

/// @notice The game whose claim is currently being used as the anchor state.
IFaultDisputeGame public anchorGame;
IDisputeGame public anchorGame;

/// @notice The starting anchor root.
Proposal internal startingAnchorRoot;
Expand All @@ -56,7 +55,7 @@ contract AnchorStateRegistry is ProxyAdminOwnedBase, Initializable, Reinitializa

/// @notice Emitted when an anchor state is updated.
/// @param game Game that was used as the new anchor game.
event AnchorUpdated(IFaultDisputeGame indexed game);
event AnchorUpdated(IDisputeGame indexed game);

/// @notice Emitted when the respected game type is set.
/// @param gameType The new respected game type.
Expand Down Expand Up @@ -190,7 +189,7 @@ contract AnchorStateRegistry is ProxyAdminOwnedBase, Initializable, Reinitializa
}

/// @notice Determines whether a game is registered by checking that it was created by the
/// DisputeGameFactory and that it uses this AnchorStateRegistry.
/// DisputeGameFactory.
/// @param _game The game to check.
/// @return Whether the game is registered.
function isGameRegistered(IDisputeGame _game) public view returns (bool) {
Expand All @@ -201,16 +200,8 @@ contract AnchorStateRegistry is ProxyAdminOwnedBase, Initializable, Reinitializa
(IDisputeGame factoryRegisteredGame,) =
disputeGameFactory.games({ _gameType: gameType, _rootClaim: rootClaim, _extraData: extraData });

// Grab the AnchorStateRegistry from the game. Awkward type conversion here but
// IDisputeGame probably needs to have this function eventually anyway.
address asr = address(IFaultDisputeGame(address(_game)).anchorStateRegistry());

// Return whether the game is factory registered and uses this AnchorStateRegistry. We
// check for both of these conditions because the game could be using a different
// AnchorStateRegistry if the registry was updated at some point. We mitigate the risks of
// an outdated AnchorStateRegistry by invalidating all previous games in the initializer of
// this contract, but an explicit check avoids potential footguns in the future.
return address(factoryRegisteredGame) == address(_game) && asr == address(this);
// Return whether the game is factory registered.
return address(factoryRegisteredGame) == address(_game);
}

/// @notice Determines whether a game is of a respected game type.
Expand Down Expand Up @@ -332,27 +323,20 @@ contract AnchorStateRegistry is ProxyAdminOwnedBase, Initializable, Reinitializa
/// @notice Updates the anchor game.
/// @param _game New candidate anchor game.
function setAnchorState(IDisputeGame _game) public {
// Convert game to FaultDisputeGame.
// We can't use FaultDisputeGame in the interface because this function is called from the
// FaultDisputeGame contract which can't import IFaultDisputeGame by convention. We should
// likely introduce a new interface (e.g., StateDisputeGame) that can act as a more useful
// version of IDisputeGame in the future.
IFaultDisputeGame game = IFaultDisputeGame(address(_game));

// Check if the candidate game claim is valid.
if (!isGameClaimValid(game)) {
if (!isGameClaimValid(_game)) {
revert AnchorStateRegistry_InvalidAnchorGame();
}

// Must be newer than the current anchor game.
(, uint256 anchorL2BlockNumber) = getAnchorRoot();
if (game.l2SequenceNumber() <= anchorL2BlockNumber) {
if (_game.l2SequenceNumber() <= anchorL2BlockNumber) {
revert AnchorStateRegistry_InvalidAnchorGame();
}

// Update the anchor game.
anchorGame = game;
emit AnchorUpdated(game);
anchorGame = _game;
emit AnchorUpdated(_game);
}

/// @notice Asserts that the caller is the Guardian.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -516,22 +516,6 @@ contract AnchorStateRegistry_IsGameRegistered_Test is AnchorStateRegistry_TestIn
// Game should not be registered.
assertFalse(anchorStateRegistry.isGameRegistered(gameProxy));
}

/// @notice Tests that isGameRegistered will return false if the game is not using the same
/// AnchorStateRegistry as the one checking the registration.
/// @param _anchorStateRegistry The AnchorStateRegistry to use for the test.
function test_isGameRegistered_isNotSameAnchorStateRegistry_succeeds(address _anchorStateRegistry) public {
// Make sure the AnchorStateRegistry is different.
vm.assume(_anchorStateRegistry != address(anchorStateRegistry));

// Mock the gameProxy's AnchorStateRegistry to be a different address.
vm.mockCall(
address(gameProxy), abi.encodeCall(gameProxy.anchorStateRegistry, ()), abi.encode(_anchorStateRegistry)
);

// Game should not be registered.
assertFalse(anchorStateRegistry.isGameRegistered(gameProxy));
}
}

/// @title AnchorStateRegistry_IsGameRespected_Test
Expand Down Expand Up @@ -970,7 +954,7 @@ contract AnchorStateRegistry_SetAnchorState_Test is AnchorStateRegistry_TestInit
assertEq(root.raw(), gameProxy.rootClaim().raw());

// Confirm that the anchor game is now set.
IFaultDisputeGame anchorGame = anchorStateRegistry.anchorGame();
IDisputeGame anchorGame = anchorStateRegistry.anchorGame();
assertEq(address(anchorGame), address(gameProxy));
}

Expand Down