github.com/ethereum-optimism/optimism@v1.7.2/packages/contracts-bedrock/src/dispute/AnchorStateRegistry.sol (about) 1 // SPDX-License-Identifier: MIT 2 pragma solidity 0.8.15; 3 4 import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; 5 import { ISemver } from "src/universal/ISemver.sol"; 6 7 import { IAnchorStateRegistry } from "src/dispute/interfaces/IAnchorStateRegistry.sol"; 8 import { IFaultDisputeGame } from "src/dispute/interfaces/IFaultDisputeGame.sol"; 9 import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; 10 import { IDisputeGameFactory } from "src/dispute/interfaces/IDisputeGameFactory.sol"; 11 12 import "src/libraries/DisputeTypes.sol"; 13 14 /// @title AnchorStateRegistry 15 /// @notice The AnchorStateRegistry is a contract that stores the latest "anchor" state for each available 16 /// FaultDisputeGame type. The anchor state is the latest state that has been proposed on L1 and was not 17 /// challenged within the challenge period. By using stored anchor states, new FaultDisputeGame instances can 18 /// be initialized with a more recent starting state which reduces the amount of required offchain computation. 19 contract AnchorStateRegistry is Initializable, IAnchorStateRegistry, ISemver { 20 /// @notice Describes an initial anchor state for a game type. 21 struct StartingAnchorRoot { 22 GameType gameType; 23 OutputRoot outputRoot; 24 } 25 26 /// @notice Semantic version. 27 /// @custom:semver 0.1.0 28 string public constant version = "0.1.0"; 29 30 /// @notice DisputeGameFactory address. 31 IDisputeGameFactory internal immutable DISPUTE_GAME_FACTORY; 32 33 /// @inheritdoc IAnchorStateRegistry 34 mapping(GameType => OutputRoot) public anchors; 35 36 /// @param _disputeGameFactory DisputeGameFactory address. 37 constructor(IDisputeGameFactory _disputeGameFactory) { 38 DISPUTE_GAME_FACTORY = _disputeGameFactory; 39 40 // Initialize the implementation with an empty array of starting anchor roots. 41 initialize(new StartingAnchorRoot[](0)); 42 } 43 44 /// @notice Initializes the contract. 45 /// @param _startingAnchorRoots An array of starting anchor roots. 46 function initialize(StartingAnchorRoot[] memory _startingAnchorRoots) public initializer { 47 for (uint256 i = 0; i < _startingAnchorRoots.length; i++) { 48 StartingAnchorRoot memory startingAnchorRoot = _startingAnchorRoots[i]; 49 anchors[startingAnchorRoot.gameType] = startingAnchorRoot.outputRoot; 50 } 51 } 52 53 /// @inheritdoc IAnchorStateRegistry 54 function disputeGameFactory() external view returns (IDisputeGameFactory) { 55 return DISPUTE_GAME_FACTORY; 56 } 57 58 /// @inheritdoc IAnchorStateRegistry 59 function tryUpdateAnchorState() external { 60 // Grab the game and game data. 61 IFaultDisputeGame game = IFaultDisputeGame(msg.sender); 62 (GameType gameType, Claim rootClaim, bytes memory extraData) = game.gameData(); 63 64 // Grab the verified address of the game based on the game data. 65 // slither-disable-next-line unused-return 66 (IDisputeGame factoryRegisteredGame,) = 67 DISPUTE_GAME_FACTORY.games({ _gameType: gameType, _rootClaim: rootClaim, _extraData: extraData }); 68 69 // Must be a valid game. 70 require( 71 address(factoryRegisteredGame) == address(game), 72 "AnchorStateRegistry: fault dispute game not registered with factory" 73 ); 74 75 // No need to update anything if the anchor state is already newer. 76 if (game.l2BlockNumber() <= anchors[gameType].l2BlockNumber) { 77 return; 78 } 79 80 // Must be a game that resolved in favor of the state. 81 if (game.status() != GameStatus.DEFENDER_WINS) { 82 return; 83 } 84 85 // Actually update the anchor state. 86 anchors[gameType] = OutputRoot({ l2BlockNumber: game.l2BlockNumber(), root: Hash.wrap(game.rootClaim().raw()) }); 87 } 88 }