github.com/ethereum-optimism/optimism@v1.7.2/packages/contracts-bedrock/test/universal/ProxyAdmin.t.sol (about)

     1  // SPDX-License-Identifier: MIT
     2  pragma solidity 0.8.15;
     3  
     4  import { Test } from "forge-std/Test.sol";
     5  import { Proxy } from "src/universal/Proxy.sol";
     6  import { ProxyAdmin } from "src/universal/ProxyAdmin.sol";
     7  import { SimpleStorage } from "test/universal/Proxy.t.sol";
     8  import { L1ChugSplashProxy } from "src/legacy/L1ChugSplashProxy.sol";
     9  import { ResolvedDelegateProxy } from "src/legacy/ResolvedDelegateProxy.sol";
    10  import { AddressManager } from "src/legacy/AddressManager.sol";
    11  
    12  contract ProxyAdmin_Test is Test {
    13      address alice = address(64);
    14  
    15      Proxy proxy;
    16      L1ChugSplashProxy chugsplash;
    17      ResolvedDelegateProxy resolved;
    18  
    19      AddressManager addressManager;
    20  
    21      ProxyAdmin admin;
    22  
    23      SimpleStorage implementation;
    24  
    25      function setUp() external {
    26          // Deploy the proxy admin
    27          admin = new ProxyAdmin(alice);
    28          // Deploy the standard proxy
    29          proxy = new Proxy(address(admin));
    30  
    31          // Deploy the legacy L1ChugSplashProxy with the admin as the owner
    32          chugsplash = new L1ChugSplashProxy(address(admin));
    33  
    34          // Deploy the legacy AddressManager
    35          addressManager = new AddressManager();
    36          // The proxy admin must be the new owner of the address manager
    37          addressManager.transferOwnership(address(admin));
    38          // Deploy a legacy ResolvedDelegateProxy with the name `a`.
    39          // Whatever `a` is set to in AddressManager will be the address
    40          // that is used for the implementation.
    41          resolved = new ResolvedDelegateProxy(addressManager, "a");
    42  
    43          // Impersonate alice for setting up the admin.
    44          vm.startPrank(alice);
    45          // Set the address of the address manager in the admin so that it
    46          // can resolve the implementation address of legacy
    47          // ResolvedDelegateProxy based proxies.
    48          admin.setAddressManager(addressManager);
    49          // Set the reverse lookup of the ResolvedDelegateProxy
    50          // proxy
    51          admin.setImplementationName(address(resolved), "a");
    52  
    53          // Set the proxy types
    54          admin.setProxyType(address(proxy), ProxyAdmin.ProxyType.ERC1967);
    55          admin.setProxyType(address(chugsplash), ProxyAdmin.ProxyType.CHUGSPLASH);
    56          admin.setProxyType(address(resolved), ProxyAdmin.ProxyType.RESOLVED);
    57          vm.stopPrank();
    58  
    59          implementation = new SimpleStorage();
    60      }
    61  
    62      function test_setImplementationName_succeeds() external {
    63          vm.prank(alice);
    64          admin.setImplementationName(address(1), "foo");
    65          assertEq(admin.implementationName(address(1)), "foo");
    66      }
    67  
    68      function test_setAddressManager_notOwner_reverts() external {
    69          vm.expectRevert("Ownable: caller is not the owner");
    70          admin.setAddressManager(AddressManager((address(0))));
    71      }
    72  
    73      function test_setImplementationName_notOwner_reverts() external {
    74          vm.expectRevert("Ownable: caller is not the owner");
    75          admin.setImplementationName(address(0), "foo");
    76      }
    77  
    78      function test_setProxyType_notOwner_reverts() external {
    79          vm.expectRevert("Ownable: caller is not the owner");
    80          admin.setProxyType(address(0), ProxyAdmin.ProxyType.CHUGSPLASH);
    81      }
    82  
    83      function test_owner_succeeds() external {
    84          assertEq(admin.owner(), alice);
    85      }
    86  
    87      function test_proxyType_succeeds() external {
    88          assertEq(uint256(admin.proxyType(address(proxy))), uint256(ProxyAdmin.ProxyType.ERC1967));
    89          assertEq(uint256(admin.proxyType(address(chugsplash))), uint256(ProxyAdmin.ProxyType.CHUGSPLASH));
    90          assertEq(uint256(admin.proxyType(address(resolved))), uint256(ProxyAdmin.ProxyType.RESOLVED));
    91      }
    92  
    93      function test_erc1967GetProxyImplementation_succeeds() external {
    94          getProxyImplementation(payable(proxy));
    95      }
    96  
    97      function test_chugsplashGetProxyImplementation_succeeds() external {
    98          getProxyImplementation(payable(chugsplash));
    99      }
   100  
   101      function test_delegateResolvedGetProxyImplementation_succeeds() external {
   102          getProxyImplementation(payable(resolved));
   103      }
   104  
   105      function getProxyImplementation(address payable _proxy) internal {
   106          {
   107              address impl = admin.getProxyImplementation(_proxy);
   108              assertEq(impl, address(0));
   109          }
   110  
   111          vm.prank(alice);
   112          admin.upgrade(_proxy, address(implementation));
   113  
   114          {
   115              address impl = admin.getProxyImplementation(_proxy);
   116              assertEq(impl, address(implementation));
   117          }
   118      }
   119  
   120      function test_erc1967GetProxyAdmin_succeeds() external {
   121          getProxyAdmin(payable(proxy));
   122      }
   123  
   124      function test_chugsplashGetProxyAdmin_succeeds() external {
   125          getProxyAdmin(payable(chugsplash));
   126      }
   127  
   128      function test_delegateResolvedGetProxyAdmin_succeeds() external {
   129          getProxyAdmin(payable(resolved));
   130      }
   131  
   132      function getProxyAdmin(address payable _proxy) internal {
   133          address owner = admin.getProxyAdmin(_proxy);
   134          assertEq(owner, address(admin));
   135      }
   136  
   137      function test_erc1967ChangeProxyAdmin_succeeds() external {
   138          changeProxyAdmin(payable(proxy));
   139      }
   140  
   141      function test_chugsplashChangeProxyAdmin_succeeds() external {
   142          changeProxyAdmin(payable(chugsplash));
   143      }
   144  
   145      function test_delegateResolvedChangeProxyAdmin_succeeds() external {
   146          changeProxyAdmin(payable(resolved));
   147      }
   148  
   149      function changeProxyAdmin(address payable _proxy) internal {
   150          ProxyAdmin.ProxyType proxyType = admin.proxyType(address(_proxy));
   151  
   152          vm.prank(alice);
   153          admin.changeProxyAdmin(_proxy, address(128));
   154  
   155          // The proxy is no longer the admin and can
   156          // no longer call the proxy interface except for
   157          // the ResolvedDelegate type on which anybody can
   158          // call the admin interface.
   159          if (proxyType == ProxyAdmin.ProxyType.ERC1967) {
   160              vm.expectRevert("Proxy: implementation not initialized");
   161              admin.getProxyAdmin(_proxy);
   162          } else if (proxyType == ProxyAdmin.ProxyType.CHUGSPLASH) {
   163              vm.expectRevert("L1ChugSplashProxy: implementation is not set yet");
   164              admin.getProxyAdmin(_proxy);
   165          } else if (proxyType == ProxyAdmin.ProxyType.RESOLVED) {
   166              // Just an empty block to show that all cases are covered
   167          } else {
   168              vm.expectRevert("ProxyAdmin: unknown proxy type");
   169          }
   170  
   171          // Call the proxy contract directly to get the admin.
   172          // Different proxy types have different interfaces.
   173          vm.prank(address(128));
   174          if (proxyType == ProxyAdmin.ProxyType.ERC1967) {
   175              assertEq(Proxy(payable(_proxy)).admin(), address(128));
   176          } else if (proxyType == ProxyAdmin.ProxyType.CHUGSPLASH) {
   177              assertEq(L1ChugSplashProxy(payable(_proxy)).getOwner(), address(128));
   178          } else if (proxyType == ProxyAdmin.ProxyType.RESOLVED) {
   179              assertEq(addressManager.owner(), address(128));
   180          } else {
   181              assert(false);
   182          }
   183      }
   184  
   185      function test_erc1967Upgrade_succeeds() external {
   186          upgrade(payable(proxy));
   187      }
   188  
   189      function test_chugsplashUpgrade_succeeds() external {
   190          upgrade(payable(chugsplash));
   191      }
   192  
   193      function test_delegateResolvedUpgrade_succeeds() external {
   194          upgrade(payable(resolved));
   195      }
   196  
   197      function upgrade(address payable _proxy) internal {
   198          vm.prank(alice);
   199          admin.upgrade(_proxy, address(implementation));
   200  
   201          address impl = admin.getProxyImplementation(_proxy);
   202          assertEq(impl, address(implementation));
   203      }
   204  
   205      function test_erc1967UpgradeAndCall_succeeds() external {
   206          upgradeAndCall(payable(proxy));
   207      }
   208  
   209      function test_chugsplashUpgradeAndCall_succeeds() external {
   210          upgradeAndCall(payable(chugsplash));
   211      }
   212  
   213      function test_delegateResolvedUpgradeAndCall_succeeds() external {
   214          upgradeAndCall(payable(resolved));
   215      }
   216  
   217      function upgradeAndCall(address payable _proxy) internal {
   218          vm.prank(alice);
   219          admin.upgradeAndCall(_proxy, address(implementation), abi.encodeWithSelector(SimpleStorage.set.selector, 1, 1));
   220  
   221          address impl = admin.getProxyImplementation(_proxy);
   222          assertEq(impl, address(implementation));
   223  
   224          uint256 got = SimpleStorage(address(_proxy)).get(1);
   225          assertEq(got, 1);
   226      }
   227  
   228      function test_onlyOwner_notOwner_reverts() external {
   229          vm.expectRevert("Ownable: caller is not the owner");
   230          admin.changeProxyAdmin(payable(proxy), address(0));
   231  
   232          vm.expectRevert("Ownable: caller is not the owner");
   233          admin.upgrade(payable(proxy), address(implementation));
   234  
   235          vm.expectRevert("Ownable: caller is not the owner");
   236          admin.upgradeAndCall(payable(proxy), address(implementation), hex"");
   237      }
   238  
   239      function test_isUpgrading_succeeds() external {
   240          assertEq(false, admin.isUpgrading());
   241  
   242          vm.prank(alice);
   243          admin.setUpgrading(true);
   244          assertEq(true, admin.isUpgrading());
   245      }
   246  }