diff --git a/packages/contracts-bedrock/scripts/DeployImplementations.s.sol b/packages/contracts-bedrock/scripts/DeployImplementations.s.sol index 78331677af86..3179ea3d6426 100644 --- a/packages/contracts-bedrock/scripts/DeployImplementations.s.sol +++ b/packages/contracts-bedrock/scripts/DeployImplementations.s.sol @@ -229,7 +229,7 @@ contract DeployImplementationsOutput is BaseDeployIO { function opcmProxy() public returns (OPContractsManager) { DeployUtils.assertValidContractAddress(address(_opcmProxy)); - DeployUtils.assertImplementationSet(address(_opcmProxy)); + DeployUtils.assertERC1967ImplementationSet(address(_opcmProxy)); return _opcmProxy; } diff --git a/packages/contracts-bedrock/scripts/DeployOPChain.s.sol b/packages/contracts-bedrock/scripts/DeployOPChain.s.sol index af05e74b2e13..f88469b7ead5 100644 --- a/packages/contracts-bedrock/scripts/DeployOPChain.s.sol +++ b/packages/contracts-bedrock/scripts/DeployOPChain.s.sol @@ -171,7 +171,7 @@ contract DeployOPChainInput is BaseDeployIO { function opcmProxy() public returns (OPContractsManager) { require(address(_opcmProxy) != address(0), "DeployOPChainInput: not set"); DeployUtils.assertValidContractAddress(address(_opcmProxy)); - DeployUtils.assertImplementationSet(address(_opcmProxy)); + DeployUtils.assertERC1967ImplementationSet(address(_opcmProxy)); return _opcmProxy; } @@ -286,43 +286,51 @@ contract DeployOPChainOutput is BaseDeployIO { return _addressManager; } - function l1ERC721BridgeProxy() public view returns (IL1ERC721Bridge) { + function l1ERC721BridgeProxy() public returns (IL1ERC721Bridge) { DeployUtils.assertValidContractAddress(address(_l1ERC721BridgeProxy)); + DeployUtils.assertERC1967ImplementationSet(address(_l1ERC721BridgeProxy)); return _l1ERC721BridgeProxy; } - function systemConfigProxy() public view returns (ISystemConfig) { + function systemConfigProxy() public returns (ISystemConfig) { DeployUtils.assertValidContractAddress(address(_systemConfigProxy)); + DeployUtils.assertERC1967ImplementationSet(address(_systemConfigProxy)); return _systemConfigProxy; } - function optimismMintableERC20FactoryProxy() public view returns (IOptimismMintableERC20Factory) { + function optimismMintableERC20FactoryProxy() public returns (IOptimismMintableERC20Factory) { DeployUtils.assertValidContractAddress(address(_optimismMintableERC20FactoryProxy)); + DeployUtils.assertERC1967ImplementationSet(address(_optimismMintableERC20FactoryProxy)); return _optimismMintableERC20FactoryProxy; } - function l1StandardBridgeProxy() public view returns (IL1StandardBridge) { + function l1StandardBridgeProxy() public returns (IL1StandardBridge) { DeployUtils.assertValidContractAddress(address(_l1StandardBridgeProxy)); + DeployUtils.assertL1ChugSplashImplementationSet(address(_l1StandardBridgeProxy)); return _l1StandardBridgeProxy; } function l1CrossDomainMessengerProxy() public view returns (IL1CrossDomainMessenger) { DeployUtils.assertValidContractAddress(address(_l1CrossDomainMessengerProxy)); + DeployUtils.assertResolvedDelegateProxyImplementationSet("OVM_L1CrossDomainMessenger", addressManager()); return _l1CrossDomainMessengerProxy; } - function optimismPortalProxy() public view returns (IOptimismPortal2) { + function optimismPortalProxy() public returns (IOptimismPortal2) { DeployUtils.assertValidContractAddress(address(_optimismPortalProxy)); + DeployUtils.assertERC1967ImplementationSet(address(_optimismPortalProxy)); return _optimismPortalProxy; } - function disputeGameFactoryProxy() public view returns (IDisputeGameFactory) { + function disputeGameFactoryProxy() public returns (IDisputeGameFactory) { DeployUtils.assertValidContractAddress(address(_disputeGameFactoryProxy)); + DeployUtils.assertERC1967ImplementationSet(address(_disputeGameFactoryProxy)); return _disputeGameFactoryProxy; } - function anchorStateRegistryProxy() public view returns (IAnchorStateRegistry) { + function anchorStateRegistryProxy() public returns (IAnchorStateRegistry) { DeployUtils.assertValidContractAddress(address(_anchorStateRegistryProxy)); + DeployUtils.assertERC1967ImplementationSet(address(_anchorStateRegistryProxy)); return _anchorStateRegistryProxy; } @@ -341,8 +349,9 @@ contract DeployOPChainOutput is BaseDeployIO { return _permissionedDisputeGame; } - function delayedWETHPermissionedGameProxy() public view returns (IDelayedWETH) { + function delayedWETHPermissionedGameProxy() public returns (IDelayedWETH) { DeployUtils.assertValidContractAddress(address(_delayedWETHPermissionedGameProxy)); + DeployUtils.assertERC1967ImplementationSet(address(_delayedWETHPermissionedGameProxy)); return _delayedWETHPermissionedGameProxy; } @@ -366,6 +375,8 @@ contract DeployOPChainOutput is BaseDeployIO { assertValidOptimismPortal(_doi); assertValidPermissionedDisputeGame(_doi); assertValidSystemConfig(_doi); + assertValidAddressManager(_doi); + assertValidOPChainProxyAdmin(_doi); } function assertValidPermissionedDisputeGame(DeployOPChainInput _doi) internal { @@ -416,7 +427,7 @@ contract DeployOPChainOutput is BaseDeployIO { require(Hash.unwrap(actualRoot) == expectedRoot, "ANCHORP-40"); } - function assertValidAnchorStateRegistryImpl(DeployOPChainInput) internal view { + function assertValidAnchorStateRegistryImpl(DeployOPChainInput) internal { IAnchorStateRegistry registry = anchorStateRegistryImpl(); DeployUtils.assertInitialized({ _contractAddress: address(registry), _slot: 0, _offset: 0 }); @@ -492,7 +503,7 @@ contract DeployOPChainOutput is BaseDeployIO { require(address(bridge.superchainConfig()) == address(_doi.opcmProxy().superchainConfig()), "L1SB-50"); } - function assertValidOptimismMintableERC20Factory(DeployOPChainInput) internal view { + function assertValidOptimismMintableERC20Factory(DeployOPChainInput) internal { IOptimismMintableERC20Factory factory = optimismMintableERC20FactoryProxy(); DeployUtils.assertInitialized({ _contractAddress: address(factory), _slot: 0, _offset: 0 }); @@ -530,7 +541,7 @@ contract DeployOPChainOutput is BaseDeployIO { require(vm.load(address(portal), bytes32(uint256(61))) == bytes32(0)); } - function assertValidDisputeGameFactory(DeployOPChainInput _doi) internal view { + function assertValidDisputeGameFactory(DeployOPChainInput _doi) internal { IDisputeGameFactory factory = disputeGameFactoryProxy(); DeployUtils.assertInitialized({ _contractAddress: address(factory), _slot: 0, _offset: 0 }); @@ -551,6 +562,61 @@ contract DeployOPChainOutput is BaseDeployIO { address admin = proxy.admin(); require(admin == address(opChainProxyAdmin()), "DWETH-20"); } + + function assertValidAddressManager(DeployOPChainInput) internal view { + require(addressManager().owner() == address(opChainProxyAdmin()), "AM-10"); + } + + function assertValidOPChainProxyAdmin(DeployOPChainInput _doi) internal { + IProxyAdmin admin = opChainProxyAdmin(); + require(admin.owner() == _doi.opChainProxyAdminOwner(), "OPCPA-10"); + require( + admin.getProxyImplementation(address(l1CrossDomainMessengerProxy())) + == DeployUtils.assertResolvedDelegateProxyImplementationSet("OVM_L1CrossDomainMessenger", addressManager()), + "OPCPA-20" + ); + require(address(admin.addressManager()) == address(addressManager()), "OPCPA-30"); + require( + admin.getProxyImplementation(address(l1StandardBridgeProxy())) + == DeployUtils.assertL1ChugSplashImplementationSet(address(l1StandardBridgeProxy())), + "OPCPA-40" + ); + require( + admin.getProxyImplementation(address(l1ERC721BridgeProxy())) + == DeployUtils.assertERC1967ImplementationSet(address(l1ERC721BridgeProxy())), + "OPCPA-50" + ); + require( + admin.getProxyImplementation(address(optimismPortalProxy())) + == DeployUtils.assertERC1967ImplementationSet(address(optimismPortalProxy())), + "OPCPA-60" + ); + require( + admin.getProxyImplementation(address(systemConfigProxy())) + == DeployUtils.assertERC1967ImplementationSet(address(systemConfigProxy())), + "OPCPA-70" + ); + require( + admin.getProxyImplementation(address(optimismMintableERC20FactoryProxy())) + == DeployUtils.assertERC1967ImplementationSet(address(optimismMintableERC20FactoryProxy())), + "OPCPA-80" + ); + require( + admin.getProxyImplementation(address(disputeGameFactoryProxy())) + == DeployUtils.assertERC1967ImplementationSet(address(disputeGameFactoryProxy())), + "OPCPA-90" + ); + require( + admin.getProxyImplementation(address(delayedWETHPermissionedGameProxy())) + == DeployUtils.assertERC1967ImplementationSet(address(delayedWETHPermissionedGameProxy())), + "OPCPA-100" + ); + require( + admin.getProxyImplementation(address(anchorStateRegistryProxy())) + == DeployUtils.assertERC1967ImplementationSet(address(anchorStateRegistryProxy())), + "OPCPA-110" + ); + } } contract DeployOPChain is Script { diff --git a/packages/contracts-bedrock/scripts/libraries/DeployUtils.sol b/packages/contracts-bedrock/scripts/libraries/DeployUtils.sol index 726c3d3686cd..669ebd0f65c7 100644 --- a/packages/contracts-bedrock/scripts/libraries/DeployUtils.sol +++ b/packages/contracts-bedrock/scripts/libraries/DeployUtils.sol @@ -9,9 +9,13 @@ import { Artifacts } from "scripts/Artifacts.s.sol"; // Libraries import { LibString } from "@solady/utils/LibString.sol"; import { Bytes } from "src/libraries/Bytes.sol"; +import { Constants } from "src/libraries/Constants.sol"; // Interfaces import { IProxy } from "src/universal/interfaces/IProxy.sol"; +import { IAddressManager } from "src/legacy/interfaces/IAddressManager.sol"; +import { IL1ChugSplashProxy, IStaticL1ChugSplashProxy } from "src/legacy/interfaces/IL1ChugSplashProxy.sol"; +import { IResolvedDelegateProxy } from "src/legacy/interfaces/IResolvedDelegateProxy.sol"; library DeployUtils { Vm internal constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); @@ -217,12 +221,99 @@ library DeployUtils { /// @notice Asserts that the given proxy has an implementation set. /// @param _proxy Proxy to check. - function assertImplementationSet(address _proxy) internal { + function assertERC1967ImplementationSet(address _proxy) internal returns (address implementation_) { // We prank as the zero address due to the Proxy's `proxyCallIfNotAdmin` modifier. // Pranking inside this function also means it can no longer be considered `view`. vm.prank(address(0)); - address implementation = IProxy(payable(_proxy)).implementation(); - assertValidContractAddress(implementation); + implementation_ = IProxy(payable(_proxy)).implementation(); + assertValidContractAddress(implementation_); + } + + /// @notice Asserts that the given L1ChugSplashProxy has an implementation set. + /// @param _proxy L1ChugSplashProxy to check. + function assertL1ChugSplashImplementationSet(address _proxy) internal returns (address implementation_) { + vm.prank(address(0)); + implementation_ = IStaticL1ChugSplashProxy(_proxy).getImplementation(); + assertValidContractAddress(implementation_); + } + + /// @notice Asserts that the given ResolvedDelegateProxy has an implementation set. + /// @param _implementationName Name of the implementation contract. + /// @param _addressManager AddressManager contract. + function assertResolvedDelegateProxyImplementationSet( + string memory _implementationName, + IAddressManager _addressManager + ) + internal + view + returns (address implementation_) + { + implementation_ = _addressManager.getAddress(_implementationName); + assertValidContractAddress(implementation_); + } + + /// @notice Builds an ERC1967 Proxy with a dummy implementation. + /// @param _proxyImplName Name of the implementation contract. + function buildERC1967ProxyWithImpl(string memory _proxyImplName) public returns (IProxy genericProxy_) { + genericProxy_ = IProxy( + create1({ + _name: "Proxy", + _args: DeployUtils.encodeConstructor(abi.encodeCall(IProxy.__constructor__, (address(0)))) + }) + ); + address implementation = address(vm.addr(uint256(keccak256(abi.encodePacked(_proxyImplName))))); + vm.etch(address(implementation), hex"01"); + vm.prank(address(0)); + genericProxy_.upgradeTo(address(implementation)); + vm.etch(address(genericProxy_), address(genericProxy_).code); + } + + /// @notice Builds an L1ChugSplashProxy with a dummy implementation. + /// @param _proxyImplName Name of the implementation contract. + function buildL1ChugSplashProxyWithImpl(string memory _proxyImplName) public returns (IL1ChugSplashProxy proxy_) { + proxy_ = IL1ChugSplashProxy( + create1({ + _name: "L1ChugSplashProxy", + _args: DeployUtils.encodeConstructor(abi.encodeCall(IL1ChugSplashProxy.__constructor__, (address(0)))) + }) + ); + address implementation = address(vm.addr(uint256(keccak256(abi.encodePacked(_proxyImplName))))); + vm.etch(address(implementation), hex"01"); + vm.prank(address(0)); + proxy_.setStorage(Constants.PROXY_IMPLEMENTATION_ADDRESS, bytes32(uint256(uint160(implementation)))); + } + + /// @notice Builds a ResolvedDelegateProxy with a dummy implementation. + /// @param _addressManager AddressManager contract. + /// @param _proxyImplName Name of the implementation contract. + function buildResolvedDelegateProxyWithImpl( + IAddressManager _addressManager, + string memory _proxyImplName + ) + public + returns (IResolvedDelegateProxy proxy_) + { + proxy_ = IResolvedDelegateProxy( + create1({ + _name: "ResolvedDelegateProxy", + _args: DeployUtils.encodeConstructor( + abi.encodeCall(IResolvedDelegateProxy.__constructor__, (_addressManager, _proxyImplName)) + ) + }) + ); + address implementation = address(vm.addr(uint256(keccak256(abi.encodePacked(_proxyImplName))))); + vm.etch(address(implementation), hex"01"); + _addressManager.setAddress(_proxyImplName, implementation); + } + + /// @notice Builds an AddressManager contract. + function buildAddressManager() public returns (IAddressManager addressManager_) { + addressManager_ = IAddressManager( + create1({ + _name: "AddressManager", + _args: DeployUtils.encodeConstructor(abi.encodeCall(IAddressManager.__constructor__, ())) + }) + ); } /// @notice Asserts that the given addresses are valid contract addresses. diff --git a/packages/contracts-bedrock/test/opcm/DeployOPChain.t.sol b/packages/contracts-bedrock/test/opcm/DeployOPChain.t.sol index 3beee87b1ee3..13460f35c632 100644 --- a/packages/contracts-bedrock/test/opcm/DeployOPChain.t.sol +++ b/packages/contracts-bedrock/test/opcm/DeployOPChain.t.sol @@ -16,21 +16,15 @@ import { DeployUtils } from "scripts/libraries/DeployUtils.sol"; import { IProxyAdmin } from "src/universal/interfaces/IProxyAdmin.sol"; import { IAddressManager } from "src/legacy/interfaces/IAddressManager.sol"; -import { IDelayedWETH } from "src/dispute/interfaces/IDelayedWETH.sol"; -import { IDisputeGameFactory } from "src/dispute/interfaces/IDisputeGameFactory.sol"; import { IAnchorStateRegistry } from "src/dispute/interfaces/IAnchorStateRegistry.sol"; import { IFaultDisputeGame } from "src/dispute/interfaces/IFaultDisputeGame.sol"; import { IPermissionedDisputeGame } from "src/dispute/interfaces/IPermissionedDisputeGame.sol"; +import { IL1ChugSplashProxy } from "src/legacy/interfaces/IL1ChugSplashProxy.sol"; +import { IResolvedDelegateProxy } from "src/legacy/interfaces/IResolvedDelegateProxy.sol"; import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; import { IProtocolVersions, ProtocolVersion } from "src/L1/interfaces/IProtocolVersions.sol"; import { OPContractsManager } from "src/L1/OPContractsManager.sol"; -import { IOptimismPortal2 } from "src/L1/interfaces/IOptimismPortal2.sol"; -import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol"; -import { IL1CrossDomainMessenger } from "src/L1/interfaces/IL1CrossDomainMessenger.sol"; -import { IL1ERC721Bridge } from "src/L1/interfaces/IL1ERC721Bridge.sol"; -import { IL1StandardBridge } from "src/L1/interfaces/IL1StandardBridge.sol"; -import { IOptimismMintableERC20Factory } from "src/universal/interfaces/IOptimismMintableERC20Factory.sol"; import { IProxy } from "src/universal/interfaces/IProxy.sol"; import { Claim, Duration, GameType, GameTypes, Hash, OutputRoot } from "src/dispute/lib/Types.sol"; @@ -55,20 +49,6 @@ contract DeployOPChainInput_Test is Test { doi = new DeployOPChainInput(); } - function buildOpcmProxy() public returns (IProxy opcmProxy) { - opcmProxy = IProxy( - DeployUtils.create1({ - _name: "Proxy", - _args: DeployUtils.encodeConstructor(abi.encodeCall(IProxy.__constructor__, (address(0)))) - }) - ); - OPContractsManager opcmImpl = OPContractsManager(address(makeAddr("opcmImpl"))); - vm.prank(address(0)); - opcmProxy.upgradeTo(address(opcmImpl)); - vm.etch(address(opcmProxy), address(opcmProxy).code); - vm.etch(address(opcmImpl), hex"01"); - } - function test_set_succeeds() public { doi.set(doi.opChainProxyAdminOwner.selector, opChainProxyAdminOwner); doi.set(doi.systemConfigOwner.selector, systemConfigOwner); @@ -80,7 +60,7 @@ contract DeployOPChainInput_Test is Test { doi.set(doi.blobBaseFeeScalar.selector, blobBaseFeeScalar); doi.set(doi.l2ChainId.selector, l2ChainId); - (IProxy opcmProxy) = buildOpcmProxy(); + (IProxy opcmProxy) = DeployUtils.buildERC1967ProxyWithImpl("opcmProxy"); doi.set(doi.opcmProxy.selector, address(opcmProxy)); // Compare the default inputs to the getter methods. @@ -131,27 +111,13 @@ contract DeployOPChainInput_Test is Test { contract DeployOPChainOutput_Test is Test { DeployOPChainOutput doo; - // Define default outputs to set. - // We set these in storage because doing it locally in test_set_succeeds results in stack too deep. - IProxyAdmin opChainProxyAdmin = IProxyAdmin(makeAddr("optimismPortal2Impl")); - IAddressManager addressManager = IAddressManager(makeAddr("delayedWETHImpl")); - IL1ERC721Bridge l1ERC721BridgeProxy = IL1ERC721Bridge(makeAddr("l1ERC721BridgeProxy")); - ISystemConfig systemConfigProxy = ISystemConfig(makeAddr("systemConfigProxy")); - IOptimismMintableERC20Factory optimismMintableERC20FactoryProxy = - IOptimismMintableERC20Factory(makeAddr("optimismMintableERC20FactoryProxy")); - IL1StandardBridge l1StandardBridgeProxy = IL1StandardBridge(payable(makeAddr("l1StandardBridgeProxy"))); - IL1CrossDomainMessenger l1CrossDomainMessengerProxy = - IL1CrossDomainMessenger(makeAddr("l1CrossDomainMessengerProxy")); - IOptimismPortal2 optimismPortalProxy = IOptimismPortal2(payable(makeAddr("optimismPortalProxy"))); - IDisputeGameFactory disputeGameFactoryProxy = IDisputeGameFactory(makeAddr("disputeGameFactoryProxy")); - IAnchorStateRegistry anchorStateRegistryProxy = IAnchorStateRegistry(makeAddr("anchorStateRegistryProxy")); + // We set the non proxy contracts in storage because doing it locally in 'test_set_succeeds' function results in + // stack too deep. + IAddressManager addressManager = DeployUtils.buildAddressManager(); + IProxyAdmin opChainProxyAdmin = IProxyAdmin(makeAddr("opChainProxyAdmin")); IAnchorStateRegistry anchorStateRegistryImpl = IAnchorStateRegistry(makeAddr("anchorStateRegistryImpl")); IFaultDisputeGame faultDisputeGame = IFaultDisputeGame(makeAddr("faultDisputeGame")); IPermissionedDisputeGame permissionedDisputeGame = IPermissionedDisputeGame(makeAddr("permissionedDisputeGame")); - IDelayedWETH delayedWETHPermissionedGameProxy = IDelayedWETH(payable(makeAddr("delayedWETHPermissionedGameProxy"))); - // TODO: Eventually switch from Permissioned to Permissionless. - // DelayedWETH delayedWETHPermissionlessGameProxy = - // DelayedWETH(payable(makeAddr("delayedWETHPermissionlessGameProxy"))); function setUp() public { doo = new DeployOPChainOutput(); @@ -159,21 +125,24 @@ contract DeployOPChainOutput_Test is Test { function test_set_succeeds() public { vm.etch(address(opChainProxyAdmin), hex"01"); - vm.etch(address(addressManager), hex"01"); - vm.etch(address(l1ERC721BridgeProxy), hex"01"); - vm.etch(address(systemConfigProxy), hex"01"); - vm.etch(address(optimismMintableERC20FactoryProxy), hex"01"); - vm.etch(address(l1StandardBridgeProxy), hex"01"); - vm.etch(address(l1CrossDomainMessengerProxy), hex"01"); - vm.etch(address(optimismPortalProxy), hex"01"); - vm.etch(address(disputeGameFactoryProxy), hex"01"); - vm.etch(address(anchorStateRegistryProxy), hex"01"); + (IProxy l1ERC721BridgeProxy) = DeployUtils.buildERC1967ProxyWithImpl("l1ERC721BridgeProxy"); + (IProxy systemConfigProxy) = DeployUtils.buildERC1967ProxyWithImpl("systemConfigProxy"); + (IProxy optimismMintableERC20FactoryProxy) = + DeployUtils.buildERC1967ProxyWithImpl("optimismMintableERC20FactoryProxy"); + (IL1ChugSplashProxy l1StandardBridgeProxy) = DeployUtils.buildL1ChugSplashProxyWithImpl("l1StandardBridgeProxy"); + (IResolvedDelegateProxy l1CrossDomainMessengerProxy) = + DeployUtils.buildResolvedDelegateProxyWithImpl(addressManager, "OVM_L1CrossDomainMessenger"); + (IProxy optimismPortalProxy) = DeployUtils.buildERC1967ProxyWithImpl("optimismPortalProxy"); + (IProxy disputeGameFactoryProxy) = DeployUtils.buildERC1967ProxyWithImpl("disputeGameFactoryProxy"); + (IProxy anchorStateRegistryProxy) = DeployUtils.buildERC1967ProxyWithImpl("anchorStateRegistryProxy"); vm.etch(address(anchorStateRegistryImpl), hex"01"); vm.etch(address(faultDisputeGame), hex"01"); vm.etch(address(permissionedDisputeGame), hex"01"); - vm.etch(address(delayedWETHPermissionedGameProxy), hex"01"); // TODO: Eventually switch from Permissioned to Permissionless. - // vm.etch(address(delayedWETHPermissionlessGameProxy), hex"01"); + // (IProxy delayedWETHPermissionlessGameProxy) = + // DeployUtils.buildERC1967ProxyWithImpl("delayedWETHPermissionlessGameProxy"); + (IProxy delayedWETHPermissionedGameProxy) = + DeployUtils.buildERC1967ProxyWithImpl("delayedWETHPermissionedGameProxy"); doo.set(doo.opChainProxyAdmin.selector, address(opChainProxyAdmin)); doo.set(doo.addressManager.selector, address(addressManager)); @@ -558,9 +527,9 @@ contract DeployOPChain_Test is DeployOPChain_TestBase { assertEq(doo.permissionedDisputeGame().splitDepth(), 30, "3400"); assertEq(doo.permissionedDisputeGame().maxGameDepth(), 73, "3500"); - // Most architecture assertions are handled within the OP Contracts Manager itself and therefore - // we only assert on the things that are not visible onchain. - // TODO add these assertions: AddressManager, Proxy, ProxyAdmin, etc. + assertEq(address(doo.opChainProxyAdmin().addressManager().owner()), address(doo.opChainProxyAdmin()), "3600"); + assertEq(address(doo.opChainProxyAdmin().addressManager()), address(doo.addressManager()), "3700"); + assertEq(address(doo.opChainProxyAdmin().owner()), opChainProxyAdminOwner, "3800"); } }