Commit 3dff3bc7 authored by Inphi's avatar Inphi Committed by Adrian Sutton

fix(ctb): Set Anchor State (#280)

Allow the `DeputyGuardian` to set the Anchor State for brick prevention.

---------
Co-authored-by: default avatarclabby <ben@clab.by>
Co-authored-by: default avatarrefcell <abigger87@gmail.com>
parent f1a52e94
......@@ -990,6 +990,7 @@ contract Deploy is Deployer {
console.log("Upgrading and initializing AnchorStateRegistry proxy");
address anchorStateRegistryProxy = mustGetAddress("AnchorStateRegistryProxy");
address anchorStateRegistry = mustGetAddress("AnchorStateRegistry");
SuperchainConfig superchainConfig = SuperchainConfig(mustGetAddress("SuperchainConfigProxy"));
AnchorStateRegistry.StartingAnchorRoot[] memory roots = new AnchorStateRegistry.StartingAnchorRoot[](5);
roots[0] = AnchorStateRegistry.StartingAnchorRoot({
......@@ -1031,7 +1032,7 @@ contract Deploy is Deployer {
_upgradeAndCallViaSafe({
_proxy: payable(anchorStateRegistryProxy),
_implementation: anchorStateRegistry,
_innerCallData: abi.encodeCall(AnchorStateRegistry.initialize, (roots))
_innerCallData: abi.encodeCall(AnchorStateRegistry.initialize, (roots, superchainConfig))
});
string memory version = AnchorStateRegistry(payable(anchorStateRegistryProxy)).version();
......
......@@ -92,6 +92,8 @@ contract FPACOPS is Deploy, StdAssertions {
function initializeAnchorStateRegistryProxy() internal broadcast {
console.log("Initializing AnchorStateRegistryProxy with AnchorStateRegistry.");
address superchainConfigProxy = mustGetAddress("SuperchainConfigProxy");
SuperchainConfig superchainConfig = SuperchainConfig(superchainConfigProxy);
AnchorStateRegistry.StartingAnchorRoot[] memory roots = new AnchorStateRegistry.StartingAnchorRoot[](2);
roots[0] = AnchorStateRegistry.StartingAnchorRoot({
......@@ -111,7 +113,8 @@ contract FPACOPS is Deploy, StdAssertions {
address asrProxy = mustGetAddress("AnchorStateRegistryProxy");
Proxy(payable(asrProxy)).upgradeToAndCall(
mustGetAddress("AnchorStateRegistry"), abi.encodeCall(AnchorStateRegistry.initialize, (roots))
mustGetAddress("AnchorStateRegistry"),
abi.encodeCall(AnchorStateRegistry.initialize, (roots, superchainConfig))
);
}
......
......@@ -170,8 +170,10 @@ contract FPACOPS2 is Deploy, StdAssertions {
});
address asrProxy = mustGetAddress("AnchorStateRegistryProxy");
address superchainConfigProxy = mustGetAddress("SuperchainConfigProxy");
Proxy(payable(asrProxy)).upgradeToAndCall(
mustGetAddress("AnchorStateRegistry"), abi.encodeCall(AnchorStateRegistry.initialize, (roots))
mustGetAddress("AnchorStateRegistry"),
abi.encodeCall(AnchorStateRegistry.initialize, (roots, SuperchainConfig(superchainConfigProxy)))
);
}
......
......@@ -128,8 +128,8 @@
"sourceCodeHash": "0xbe200a6cb297a3ca1a7d174a9c886e3f17eb8edf617ad014a2ac4f6c2e2ac7f1"
},
"src/Safe/DeputyGuardianModule.sol": {
"initCodeHash": "0x433eb7488e613a51c7ff05a76bbecf47f5beac8b8614f5c50001f99e39ae7ed2",
"sourceCodeHash": "0x5b415dc432a83fb1d5c41585539245997c62acb6bd77c489bf57e9b59be5f983"
"initCodeHash": "0x23ecfc6ff42575058b51b3bde8449f62ee929fd5881f707a904fa3eb8f628053",
"sourceCodeHash": "0x904ff08bf288dc257501dc0a60539791c7a2dc5fba508a3523521c39009e7d5e"
},
"src/Safe/LivenessGuard.sol": {
"initCodeHash": "0xf54289de5cef7ba0044e0d63310937fa231d6528aac91e13e531c845af42afac",
......@@ -152,8 +152,8 @@
"sourceCodeHash": "0xb1f0d6f26c2e6a2c3b635eaf8f327e91a8d22ef7479b1ebb93427b88f73ed163"
},
"src/dispute/AnchorStateRegistry.sol": {
"initCodeHash": "0x0305c21e50829b9e07d43358d8c2c82f1449534c90d4391400d46e76d0503a49",
"sourceCodeHash": "0x56b069b33d080c2a45ee6fd340e5c5824ab4dc866eadb5b481b9026ebb12aa7c"
"initCodeHash": "0x92aa16ad6c88b8c2842fea07ec69afe45e7d0dcb49cdfad7ce4693e03c3bbc47",
"sourceCodeHash": "0x0383f33a1cbf41ceb010a1bf79ddd14880f55c13512e4704f82d5587fff16826"
},
"src/dispute/DisputeGameFactory.sol": {
"initCodeHash": "0x7a7cb8f2c95df2f9afb3ce9eaefe4a6f997ccce7ed8ffda5d425a65a2474a792",
......
......@@ -77,6 +77,11 @@
"internalType": "struct AnchorStateRegistry.StartingAnchorRoot[]",
"name": "_startingAnchorRoots",
"type": "tuple[]"
},
{
"internalType": "contract SuperchainConfig",
"name": "_superchainConfig",
"type": "address"
}
],
"name": "initialize",
......@@ -84,6 +89,32 @@
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "contract IFaultDisputeGame",
"name": "_game",
"type": "address"
}
],
"name": "setAnchorState",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "superchainConfig",
"outputs": [
{
"internalType": "contract SuperchainConfig",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "tryUpdateAnchorState",
......@@ -116,5 +147,20 @@
],
"name": "Initialized",
"type": "event"
},
{
"inputs": [],
"name": "InvalidGameStatus",
"type": "error"
},
{
"inputs": [],
"name": "Unauthorized",
"type": "error"
},
{
"inputs": [],
"name": "UnregisteredGame",
"type": "error"
}
]
\ No newline at end of file
......@@ -71,6 +71,24 @@
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "contract AnchorStateRegistry",
"name": "_registry",
"type": "address"
},
{
"internalType": "contract IFaultDisputeGame",
"name": "_game",
"type": "address"
}
],
"name": "setAnchorState",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
......
......@@ -19,5 +19,12 @@
"offset": 0,
"slot": "1",
"type": "mapping(GameType => struct OutputRoot)"
},
{
"bytes": "20",
"label": "superchainConfig",
"offset": 0,
"slot": "2",
"type": "contract SuperchainConfig"
}
]
\ No newline at end of file
......@@ -4,11 +4,13 @@ pragma solidity 0.8.15;
import { GnosisSafe as Safe } from "safe-contracts/GnosisSafe.sol";
import { Enum } from "safe-contracts/common/Enum.sol";
import { IFaultDisputeGame } from "src/dispute/interfaces/IFaultDisputeGame.sol";
import { SuperchainConfig } from "src/L1/SuperchainConfig.sol";
import { OptimismPortal2 } from "src/L1/OptimismPortal2.sol";
import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol";
import { ISemver } from "src/universal/ISemver.sol";
import { Unauthorized } from "src/libraries/PortalErrors.sol";
import { AnchorStateRegistry } from "src/dispute/AnchorStateRegistry.sol";
import "src/dispute/lib/Types.sol";
......@@ -43,8 +45,8 @@ contract DeputyGuardianModule is ISemver {
address internal immutable DEPUTY_GUARDIAN;
/// @notice Semantic version.
/// @custom:semver 1.1.0
string public constant version = "1.1.0";
/// @custom:semver 2.0.0-beta.1
string public constant version = "2.0.0-beta.1";
// Constructor to initialize the Safe and baseModule instances
constructor(Safe _safe, SuperchainConfig _superchainConfig, address _deputyGuardian) {
......@@ -108,6 +110,22 @@ contract DeputyGuardianModule is ISemver {
emit Unpaused();
}
/// @notice Calls the Security Council Safe's `execTransactionFromModuleReturnData()`, with the arguments
/// necessary to call `setAnchorState()` on the `AnchorStateRegistry` contract.
/// Only the deputy guardian can call this function.
/// @param _registry The `AnchorStateRegistry` contract instance.
/// @param _game The `IFaultDisputeGame` contract instance.
function setAnchorState(AnchorStateRegistry _registry, IFaultDisputeGame _game) external {
_onlyDeputyGuardian();
bytes memory data = abi.encodeCall(AnchorStateRegistry.setAnchorState, (_game));
(bool success, bytes memory returnData) =
SAFE.execTransactionFromModuleReturnData(address(_registry), 0, data, Enum.Operation.Call);
if (!success) {
revert ExecutionFailed(string(returnData));
}
}
/// @notice Calls the Security Council Safe's `execTransactionFromModuleReturnData()`, with the arguments
/// necessary to call `blacklistDisputeGame()` on the `OptimismPortal2` contract.
/// Only the deputy guardian can call this function.
......
......@@ -8,8 +8,11 @@ import { IAnchorStateRegistry } from "src/dispute/interfaces/IAnchorStateRegistr
import { IFaultDisputeGame } from "src/dispute/interfaces/IFaultDisputeGame.sol";
import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol";
import { IDisputeGameFactory } from "src/dispute/interfaces/IDisputeGameFactory.sol";
import { SuperchainConfig } from "src/L1/SuperchainConfig.sol";
import "src/dispute/lib/Types.sol";
import { Unauthorized } from "src/libraries/errors/CommonErrors.sol";
import { UnregisteredGame, InvalidGameStatus } from "src/dispute/lib/Errors.sol";
/// @title AnchorStateRegistry
/// @notice The AnchorStateRegistry is a contract that stores the latest "anchor" state for each available
......@@ -24,8 +27,8 @@ contract AnchorStateRegistry is Initializable, IAnchorStateRegistry, ISemver {
}
/// @notice Semantic version.
/// @custom:semver 1.0.0
string public constant version = "1.0.0";
/// @custom:semver 1.1.0-beta.1
string public constant version = "2.0.0-beta.1";
/// @notice DisputeGameFactory address.
IDisputeGameFactory internal immutable DISPUTE_GAME_FACTORY;
......@@ -33,21 +36,30 @@ contract AnchorStateRegistry is Initializable, IAnchorStateRegistry, ISemver {
/// @inheritdoc IAnchorStateRegistry
mapping(GameType => OutputRoot) public anchors;
/// @notice Address of the SuperchainConfig contract.
SuperchainConfig public superchainConfig;
/// @param _disputeGameFactory DisputeGameFactory address.
constructor(IDisputeGameFactory _disputeGameFactory) {
DISPUTE_GAME_FACTORY = _disputeGameFactory;
// Initialize the implementation with an empty array of starting anchor roots.
initialize(new StartingAnchorRoot[](0));
_disableInitializers();
}
/// @notice Initializes the contract.
/// @param _startingAnchorRoots An array of starting anchor roots.
function initialize(StartingAnchorRoot[] memory _startingAnchorRoots) public initializer {
/// @param _superchainConfig The address of the SuperchainConfig contract.
function initialize(
StartingAnchorRoot[] memory _startingAnchorRoots,
SuperchainConfig _superchainConfig
)
public
initializer
{
for (uint256 i = 0; i < _startingAnchorRoots.length; i++) {
StartingAnchorRoot memory startingAnchorRoot = _startingAnchorRoots[i];
anchors[startingAnchorRoot.gameType] = startingAnchorRoot.outputRoot;
}
superchainConfig = _superchainConfig;
}
/// @inheritdoc IAnchorStateRegistry
......@@ -67,10 +79,7 @@ contract AnchorStateRegistry is Initializable, IAnchorStateRegistry, ISemver {
DISPUTE_GAME_FACTORY.games({ _gameType: gameType, _rootClaim: rootClaim, _extraData: extraData });
// Must be a valid game.
require(
address(factoryRegisteredGame) == address(game),
"AnchorStateRegistry: fault dispute game not registered with factory"
);
if (address(factoryRegisteredGame) != address(game)) revert UnregisteredGame();
// No need to update anything if the anchor state is already newer.
if (game.l2BlockNumber() <= anchors[gameType].l2BlockNumber) {
......@@ -85,4 +94,27 @@ contract AnchorStateRegistry is Initializable, IAnchorStateRegistry, ISemver {
// Actually update the anchor state.
anchors[gameType] = OutputRoot({ l2BlockNumber: game.l2BlockNumber(), root: Hash.wrap(game.rootClaim().raw()) });
}
/// @inheritdoc IAnchorStateRegistry
function setAnchorState(IFaultDisputeGame _game) external {
if (msg.sender != superchainConfig.guardian()) revert Unauthorized();
// Get the metadata of the game.
(GameType gameType, Claim rootClaim, bytes memory extraData) = _game.gameData();
// Grab the verified address of the game based on the game data.
// slither-disable-next-line unused-return
(IDisputeGame factoryRegisteredGame,) =
DISPUTE_GAME_FACTORY.games({ _gameType: gameType, _rootClaim: rootClaim, _extraData: extraData });
// Must be a valid game.
if (address(factoryRegisteredGame) != address(_game)) revert UnregisteredGame();
// The game must have resolved in favor of the root claim.
if (_game.status() != GameStatus.DEFENDER_WINS) revert InvalidGameStatus();
// Update the anchor.
anchors[gameType] =
OutputRoot({ l2BlockNumber: _game.l2BlockNumber(), root: Hash.wrap(_game.rootClaim().raw()) });
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { IFaultDisputeGame } from "src/dispute/interfaces/IFaultDisputeGame.sol";
import { IDisputeGameFactory } from "src/dispute/interfaces/IDisputeGameFactory.sol";
import "src/dispute/lib/Types.sol";
......@@ -21,4 +22,8 @@ interface IAnchorStateRegistry {
/// the FaultDisputeGame contract and stores it in the registry if the new anchor state is valid and the
/// state is newer than the current anchor state.
function tryUpdateAnchorState() external;
/// @notice Sets the anchor state given the game.
/// @param _game The game to set the anchor state for.
function setAnchorState(IFaultDisputeGame _game) external;
}
......@@ -126,3 +126,13 @@ error L2BlockNumberChallenged();
/// @notice Thrown when an unauthorized address attempts to interact with the game.
error BadAuth();
////////////////////////////////////////////////////////////////
// `AnchorStateRegistry` Errors //
////////////////////////////////////////////////////////////////
/// @notice Thrown when attempting to set an anchor state using an unregistered game.
error UnregisteredGame();
/// @notice Thrown when attempting to set an anchor state using an invalid game result.
error InvalidGameStatus();
......@@ -7,6 +7,8 @@ import { GnosisSafe as Safe } from "safe-contracts/GnosisSafe.sol";
import "test/safe-tools/SafeTestTools.sol";
import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol";
import { IFaultDisputeGame } from "src/dispute/interfaces/IFaultDisputeGame.sol";
import { AnchorStateRegistry } from "src/dispute/AnchorStateRegistry.sol";
import { DeputyGuardianModule } from "src/Safe/DeputyGuardianModule.sol";
import "src/dispute/lib/Types.sol";
......@@ -148,6 +150,43 @@ contract DeputyGuardianModule_Unpause_TestFail is DeputyGuardianModule_Unpause_T
}
}
contract DeputyGuardianModule_SetAnchorState_TestFail is DeputyGuardianModule_TestInit {
function test_setAnchorState_notDeputyGuardian_reverts() external {
AnchorStateRegistry asr = AnchorStateRegistry(makeAddr("asr"));
vm.expectRevert(abi.encodeWithSelector(Unauthorized.selector));
deputyGuardianModule.setAnchorState(asr, IFaultDisputeGame(address(0)));
}
function test_setAnchorState_targetReverts_reverts() external {
AnchorStateRegistry asr = AnchorStateRegistry(makeAddr("asr"));
vm.mockCallRevert(
address(asr),
abi.encodeWithSelector(asr.setAnchorState.selector),
"AnchorStateRegistry: setAnchorState reverted"
);
vm.prank(address(deputyGuardian));
vm.expectRevert(
abi.encodeWithSelector(ExecutionFailed.selector, "AnchorStateRegistry: setAnchorState reverted")
);
deputyGuardianModule.setAnchorState(asr, IFaultDisputeGame(address(0)));
}
}
contract DeputyGuardianModule_SetAnchorState_Test is DeputyGuardianModule_TestInit {
function test_setAnchorState_succeeds() external {
AnchorStateRegistry asr = AnchorStateRegistry(makeAddr("asr"));
vm.mockCall(
address(asr),
abi.encodeWithSelector(AnchorStateRegistry.setAnchorState.selector, IFaultDisputeGame(address(0))),
""
);
vm.expectEmit(address(safeInstance.safe));
emit ExecutionFromModuleSuccess(address(deputyGuardianModule));
vm.prank(address(deputyGuardian));
deputyGuardianModule.setAnchorState(asr, IFaultDisputeGame(address(0)));
}
}
contract DeputyGuardianModule_BlacklistDisputeGame_Test is DeputyGuardianModule_TestInit {
/// @dev Tests that `blacklistDisputeGame` successfully blacklists a dispute game when called by the deputy
/// guardian.
......
......@@ -617,9 +617,11 @@ contract Specification_Test is CommonTest {
// AnchorStateRegistry
_addSpec({ _name: "AnchorStateRegistry", _sel: _getSel("anchors(uint32)") });
_addSpec({ _name: "AnchorStateRegistry", _sel: _getSel("disputeGameFactory()") });
_addSpec({ _name: "AnchorStateRegistry", _sel: _getSel("initialize((uint32,(bytes32,uint256))[])") });
_addSpec({ _name: "AnchorStateRegistry", _sel: _getSel("initialize((uint32,(bytes32,uint256))[],address)") });
_addSpec({ _name: "AnchorStateRegistry", _sel: _getSel("tryUpdateAnchorState()") });
_addSpec({ _name: "AnchorStateRegistry", _sel: _getSel("setAnchorState(address)"), _auth: Role.GUARDIAN });
_addSpec({ _name: "AnchorStateRegistry", _sel: _getSel("version()") });
_addSpec({ _name: "AnchorStateRegistry", _sel: _getSel("superchainConfig()") });
// PermissionedDisputeGame
_addSpec({ _name: "PermissionedDisputeGame", _sel: _getSel("absolutePrestate()") });
......@@ -826,6 +828,11 @@ contract Specification_Test is CommonTest {
_sel: _getSel("setRespectedGameType(address,uint32)"),
_auth: Role.DEPUTYGUARDIAN
});
_addSpec({
_name: "DeputyGuardianModule",
_sel: _getSel("setAnchorState(address,address)"),
_auth: Role.DEPUTYGUARDIAN
});
_addSpec({ _name: "DeputyGuardianModule", _sel: _getSel("pause()"), _auth: Role.DEPUTYGUARDIAN });
_addSpec({ _name: "DeputyGuardianModule", _sel: _getSel("unpause()"), _auth: Role.DEPUTYGUARDIAN });
_addSpec({ _name: "DeputyGuardianModule", _sel: _getSel("deputyGuardian()") });
......@@ -940,11 +947,12 @@ contract Specification_Test is CommonTest {
/// @notice Ensures that the DeputyGuardian is authorized to take all Guardian actions.
function testDeputyGuardianAuth() public view {
assertEq(specsByRole[Role.DEPUTYGUARDIAN].length, specsByRole[Role.GUARDIAN].length);
assertEq(specsByRole[Role.DEPUTYGUARDIAN].length, 4);
assertEq(specsByRole[Role.DEPUTYGUARDIAN].length, 5);
mapping(bytes4 => Spec) storage dgmFuncSpecs = specs["DeputyGuardianModule"];
mapping(bytes4 => Spec) storage superchainConfigFuncSpecs = specs["SuperchainConfig"];
mapping(bytes4 => Spec) storage portal2FuncSpecs = specs["OptimismPortal2"];
mapping(bytes4 => Spec) storage anchorRegFuncSpecs = specs["AnchorStateRegistry"];
// Ensure that for each of the DeputyGuardianModule's methods there is a corresponding method on another
// system contract authed to the Guardian role.
......@@ -959,5 +967,8 @@ contract Specification_Test is CommonTest {
_assertRolesEq(dgmFuncSpecs[_getSel("setRespectedGameType(address,uint32)")].auth, Role.DEPUTYGUARDIAN);
_assertRolesEq(portal2FuncSpecs[_getSel("setRespectedGameType(uint32)")].auth, Role.GUARDIAN);
_assertRolesEq(dgmFuncSpecs[_getSel("setAnchorState(address,address)")].auth, Role.DEPUTYGUARDIAN);
_assertRolesEq(anchorRegFuncSpecs[_getSel("setAnchorState(address)")].auth, Role.GUARDIAN);
}
}
......@@ -5,7 +5,7 @@ import "src/dispute/lib/Types.sol";
import "src/dispute/lib/Errors.sol";
import { Test } from "forge-std/Test.sol";
import { FaultDisputeGame_Init, _changeClaimStatus } from "test/dispute/FaultDisputeGame.t.sol";
import { FaultDisputeGame_Init, IDisputeGame, _changeClaimStatus } from "test/dispute/FaultDisputeGame.t.sol";
contract AnchorStateRegistry_Init is FaultDisputeGame_Init {
function setUp() public virtual override {
......@@ -124,7 +124,7 @@ contract AnchorStateRegistry_TryUpdateAnchorState_Test is AnchorStateRegistry_In
// Try to update the anchor state.
vm.prank(address(gameProxy));
vm.expectRevert("AnchorStateRegistry: fault dispute game not registered with factory");
vm.expectRevert(UnregisteredGame.selector);
anchorStateRegistry.tryUpdateAnchorState();
// Confirm that the anchor state has not updated.
......@@ -132,4 +132,88 @@ contract AnchorStateRegistry_TryUpdateAnchorState_Test is AnchorStateRegistry_In
assertEq(updatedL2BlockNumber, l2BlockNumber);
assertEq(updatedRoot.raw(), root.raw());
}
function test_setAnchorState_invalidGame_fails() public {
// Confirm that the anchor state is older than the game state.
(Hash root, uint256 l2BlockNumber) = anchorStateRegistry.anchors(gameProxy.gameType());
require(l2BlockNumber < gameProxy.l2BlockNumber(), "l2BlockNumber < gameProxy.l2BlockNumber()");
// Mock the state that we want.
vm.mockCall(
address(disputeGameFactory),
abi.encodeWithSelector(
disputeGameFactory.games.selector, gameProxy.gameType(), gameProxy.rootClaim(), gameProxy.extraData()
),
abi.encode(address(0), 0)
);
// Try to update the anchor state.
vm.prank(superchainConfig.guardian());
vm.expectRevert(UnregisteredGame.selector);
anchorStateRegistry.setAnchorState(gameProxy);
// Confirm that the anchor state has not updated.
(Hash updatedRoot, uint256 updatedL2BlockNumber) = anchorStateRegistry.anchors(gameProxy.gameType());
assertEq(updatedL2BlockNumber, l2BlockNumber);
assertEq(updatedRoot.raw(), root.raw());
}
/// @dev Tests that setting the anchor state fails if the challenger wins.
function test_setAnchorState_challengerWins_fails() public {
(Hash root, uint256 l2BlockNumber) = anchorStateRegistry.anchors(gameProxy.gameType());
// Mock the state that we want.
vm.mockCall(
address(gameProxy),
abi.encodeWithSelector(gameProxy.status.selector),
abi.encode(GameStatus.CHALLENGER_WINS)
);
// Set the anchor state.
vm.prank(superchainConfig.guardian());
vm.expectRevert(InvalidGameStatus.selector);
anchorStateRegistry.setAnchorState(gameProxy);
// Confirm that the anchor state has not updated.
(Hash updatedRoot, uint256 updatedL2BlockNumber) = anchorStateRegistry.anchors(gameProxy.gameType());
assertEq(updatedL2BlockNumber, l2BlockNumber);
assertEq(updatedRoot.raw(), root.raw());
}
/// @dev Tests that setting the anchor state fails if the game is in progress.
function test_setAnchorState_gameInProgress_fails() public {
(Hash root, uint256 l2BlockNumber) = anchorStateRegistry.anchors(gameProxy.gameType());
// Mock the state that we want.
vm.mockCall(
address(gameProxy), abi.encodeWithSelector(gameProxy.status.selector), abi.encode(GameStatus.IN_PROGRESS)
);
// Set the anchor state.
vm.prank(superchainConfig.guardian());
vm.expectRevert(InvalidGameStatus.selector);
anchorStateRegistry.setAnchorState(gameProxy);
// Confirm that the anchor state has not updated.
(Hash updatedRoot, uint256 updatedL2BlockNumber) = anchorStateRegistry.anchors(gameProxy.gameType());
assertEq(updatedL2BlockNumber, l2BlockNumber);
assertEq(updatedRoot.raw(), root.raw());
}
/// @dev Tests that setting the anchor state succeeds.
function test_setAnchorState_succeeds() public {
// Mock the state that we want.
vm.mockCall(
address(gameProxy), abi.encodeWithSelector(gameProxy.status.selector), abi.encode(GameStatus.DEFENDER_WINS)
);
// Set the anchor state.
vm.prank(superchainConfig.guardian());
anchorStateRegistry.setAnchorState(gameProxy);
// Confirm that the anchor state has updated.
(Hash updatedRoot, uint256 updatedL2BlockNumber) = anchorStateRegistry.anchors(gameProxy.gameType());
assertEq(updatedL2BlockNumber, gameProxy.l2BlockNumber());
assertEq(updatedRoot.raw(), gameProxy.rootClaim().raw());
}
}
......@@ -13,7 +13,7 @@ contract DeploymentSummary is DeploymentSummaryCode {
Vm private constant vm = Vm(VM_ADDRESS);
address internal constant addressManagerAddress = 0x50EEf481cae4250d252Ae577A09bF514f224C6C4;
address internal constant anchorStateRegistryAddress = 0xE2a80256d1dAFe06683F231F8e9561639Aa0e9b9;
address internal constant anchorStateRegistryAddress = 0x18AdFeBA1BcE3eCa45E563944759E2d6eCaF7BA2;
address internal constant anchorStateRegistryProxyAddress = 0x970670459734a83899773A0fd45941B5afC1200e;
address internal constant delayedWETHAddress = 0x90b505357aFad15A1fb8F1098B3295b7cfac1c24;
address internal constant delayedWETHProxyAddress = 0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92;
......@@ -424,13 +424,7 @@ contract DeploymentSummary is DeploymentSummaryCode {
vm.etch(mipsAddress, mipsCode);
vm.etch(anchorStateRegistryAddress, anchorStateRegistryCode);
slot = hex"0000000000000000000000000000000000000000000000000000000000000000";
value = hex"0000000000000000000000000000000000000000000000000000000000000001";
vm.store(anchorStateRegistryAddress, slot, value);
slot = hex"0000000000000000000000000000000000000000000000000000000000000000";
value = hex"0000000000000000000000000000000000000000000000000000000000000101";
vm.store(anchorStateRegistryAddress, slot, value);
slot = hex"0000000000000000000000000000000000000000000000000000000000000000";
value = hex"0000000000000000000000000000000000000000000000000000000000000001";
value = hex"00000000000000000000000000000000000000000000000000000000000000ff";
vm.store(anchorStateRegistryAddress, slot, value);
slot = hex"0000000000000000000000000000000000000000000000000000000000000005";
value = hex"0000000000000000000000000000000000000000000000000000000000000003";
......@@ -751,7 +745,7 @@ contract DeploymentSummary is DeploymentSummaryCode {
value = hex"0000000000000000000000000000000000000000000000000000000000000010";
vm.store(systemOwnerSafeAddress, slot, value);
slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc";
value = hex"000000000000000000000000e2a80256d1dafe06683f231f8e9561639aa0e9b9";
value = hex"00000000000000000000000018adfeba1bce3eca45e563944759e2d6ecaf7ba2";
vm.store(anchorStateRegistryProxyAddress, slot, value);
slot = hex"0000000000000000000000000000000000000000000000000000000000000000";
value = hex"0000000000000000000000000000000000000000000000000000000000000001";
......@@ -774,6 +768,9 @@ contract DeploymentSummary is DeploymentSummaryCode {
slot = hex"1d32deecea32fd1365d10df47fc6666a05871102e61a115a5c569bca7e5de14d";
value = hex"deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef";
vm.store(anchorStateRegistryProxyAddress, slot, value);
slot = hex"0000000000000000000000000000000000000000000000000000000000000002";
value = hex"0000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab0351";
vm.store(anchorStateRegistryProxyAddress, slot, value);
slot = hex"0000000000000000000000000000000000000000000000000000000000000000";
value = hex"0000000000000000000000000000000000000000000000000000000000000001";
vm.store(anchorStateRegistryProxyAddress, slot, value);
......
......@@ -13,7 +13,7 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode {
Vm private constant vm = Vm(VM_ADDRESS);
address internal constant addressManagerAddress = 0x50EEf481cae4250d252Ae577A09bF514f224C6C4;
address internal constant anchorStateRegistryAddress = 0xE2a80256d1dAFe06683F231F8e9561639Aa0e9b9;
address internal constant anchorStateRegistryAddress = 0x18AdFeBA1BcE3eCa45E563944759E2d6eCaF7BA2;
address internal constant anchorStateRegistryProxyAddress = 0x970670459734a83899773A0fd45941B5afC1200e;
address internal constant delayedWETHAddress = 0x90b505357aFad15A1fb8F1098B3295b7cfac1c24;
address internal constant delayedWETHProxyAddress = 0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92;
......@@ -424,13 +424,7 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode {
vm.etch(mipsAddress, mipsCode);
vm.etch(anchorStateRegistryAddress, anchorStateRegistryCode);
slot = hex"0000000000000000000000000000000000000000000000000000000000000000";
value = hex"0000000000000000000000000000000000000000000000000000000000000001";
vm.store(anchorStateRegistryAddress, slot, value);
slot = hex"0000000000000000000000000000000000000000000000000000000000000000";
value = hex"0000000000000000000000000000000000000000000000000000000000000101";
vm.store(anchorStateRegistryAddress, slot, value);
slot = hex"0000000000000000000000000000000000000000000000000000000000000000";
value = hex"0000000000000000000000000000000000000000000000000000000000000001";
value = hex"00000000000000000000000000000000000000000000000000000000000000ff";
vm.store(anchorStateRegistryAddress, slot, value);
slot = hex"0000000000000000000000000000000000000000000000000000000000000005";
value = hex"0000000000000000000000000000000000000000000000000000000000000003";
......@@ -754,7 +748,7 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode {
value = hex"0000000000000000000000000000000000000000000000000000000000000010";
vm.store(systemOwnerSafeAddress, slot, value);
slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc";
value = hex"000000000000000000000000e2a80256d1dafe06683f231f8e9561639aa0e9b9";
value = hex"00000000000000000000000018adfeba1bce3eca45e563944759e2d6ecaf7ba2";
vm.store(anchorStateRegistryProxyAddress, slot, value);
slot = hex"0000000000000000000000000000000000000000000000000000000000000000";
value = hex"0000000000000000000000000000000000000000000000000000000000000001";
......@@ -777,6 +771,9 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode {
slot = hex"1d32deecea32fd1365d10df47fc6666a05871102e61a115a5c569bca7e5de14d";
value = hex"deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef";
vm.store(anchorStateRegistryProxyAddress, slot, value);
slot = hex"0000000000000000000000000000000000000000000000000000000000000002";
value = hex"0000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab0351";
vm.store(anchorStateRegistryProxyAddress, slot, value);
slot = hex"0000000000000000000000000000000000000000000000000000000000000000";
value = hex"0000000000000000000000000000000000000000000000000000000000000001";
vm.store(anchorStateRegistryProxyAddress, slot, value);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment