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

     1  // SPDX-License-Identifier: MIT
     2  pragma solidity 0.8.15;
     3  
     4  // Testing utilities
     5  import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol";
     6  import { NextImpl } from "test/mocks/NextImpl.sol";
     7  import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol";
     8  
     9  // Target contract dependencies
    10  import { OptimismMintableERC20 } from "src/universal/OptimismMintableERC20.sol";
    11  import { Proxy } from "src/universal/Proxy.sol";
    12  
    13  // Target contract
    14  import { OptimismMintableERC20Factory } from "src/universal/OptimismMintableERC20Factory.sol";
    15  
    16  contract OptimismMintableTokenFactory_Test is Bridge_Initializer {
    17      event StandardL2TokenCreated(address indexed remoteToken, address indexed localToken);
    18      event OptimismMintableERC20Created(address indexed localToken, address indexed remoteToken, address deployer);
    19  
    20      /// @dev Tests that the constructor is initialized correctly.
    21      function test_constructor_succeeds() external {
    22          OptimismMintableERC20Factory impl = new OptimismMintableERC20Factory();
    23          assertEq(address(impl.BRIDGE()), address(0));
    24          assertEq(address(impl.bridge()), address(0));
    25      }
    26  
    27      /// @dev Tests that the proxy is initialized correctly.
    28      function test_initialize_succeeds() external {
    29          assertEq(address(l1OptimismMintableERC20Factory.BRIDGE()), address(l1StandardBridge));
    30          assertEq(address(l1OptimismMintableERC20Factory.bridge()), address(l1StandardBridge));
    31      }
    32  
    33      function test_upgrading_succeeds() external {
    34          Proxy proxy = Proxy(deploy.mustGetAddress("OptimismMintableERC20FactoryProxy"));
    35          // Check an unused slot before upgrading.
    36          bytes32 slot21Before = vm.load(address(l1OptimismMintableERC20Factory), bytes32(uint256(21)));
    37          assertEq(bytes32(0), slot21Before);
    38  
    39          NextImpl nextImpl = new NextImpl();
    40          vm.startPrank(EIP1967Helper.getAdmin(address(proxy)));
    41          // Reviewer note: the NextImpl() still uses reinitializer. If we want to remove that, we'll need to use a
    42          //   two step upgrade with the Storage lib.
    43          proxy.upgradeToAndCall(address(nextImpl), abi.encodeWithSelector(NextImpl.initialize.selector, 2));
    44          assertEq(proxy.implementation(), address(nextImpl));
    45  
    46          // Verify that the NextImpl contract initialized its values according as expected
    47          bytes32 slot21After = vm.load(address(l1OptimismMintableERC20Factory), bytes32(uint256(21)));
    48          bytes32 slot21Expected = NextImpl(address(l1OptimismMintableERC20Factory)).slot21Init();
    49          assertEq(slot21Expected, slot21After);
    50      }
    51  
    52      function test_createStandardL2Token_succeeds() external {
    53          address remote = address(4);
    54  
    55          // Defaults to 18 decimals
    56          address local = calculateTokenAddress(remote, "Beep", "BOOP", 18);
    57  
    58          vm.expectEmit(true, true, true, true);
    59          emit StandardL2TokenCreated(remote, local);
    60  
    61          vm.expectEmit(true, true, true, true);
    62          emit OptimismMintableERC20Created(local, remote, alice);
    63  
    64          vm.prank(alice);
    65          address addr = l2OptimismMintableERC20Factory.createStandardL2Token(remote, "Beep", "BOOP");
    66          assertTrue(addr == local);
    67          assertTrue(OptimismMintableERC20(local).decimals() == 18);
    68      }
    69  
    70      function test_createStandardL2TokenWithDecimals_succeeds() external {
    71          address remote = address(4);
    72          address local = calculateTokenAddress(remote, "Beep", "BOOP", 6);
    73  
    74          vm.expectEmit(true, true, true, true);
    75          emit StandardL2TokenCreated(remote, local);
    76  
    77          vm.expectEmit(true, true, true, true);
    78          emit OptimismMintableERC20Created(local, remote, alice);
    79  
    80          vm.prank(alice);
    81          address addr = l2OptimismMintableERC20Factory.createOptimismMintableERC20WithDecimals(remote, "Beep", "BOOP", 6);
    82          assertTrue(addr == local);
    83  
    84          assertTrue(OptimismMintableERC20(local).decimals() == 6);
    85      }
    86  
    87      function test_createStandardL2Token_sameTwice_reverts() external {
    88          address remote = address(4);
    89  
    90          vm.prank(alice);
    91          l2OptimismMintableERC20Factory.createStandardL2Token(remote, "Beep", "BOOP");
    92  
    93          vm.expectRevert(bytes(""));
    94  
    95          vm.prank(alice);
    96          l2OptimismMintableERC20Factory.createStandardL2Token(remote, "Beep", "BOOP");
    97      }
    98  
    99      function test_createStandardL2Token_remoteIsZero_reverts() external {
   100          address remote = address(0);
   101          vm.expectRevert("OptimismMintableERC20Factory: must provide remote token address");
   102          l2OptimismMintableERC20Factory.createStandardL2Token(remote, "Beep", "BOOP");
   103      }
   104  
   105      function calculateTokenAddress(
   106          address _remote,
   107          string memory _name,
   108          string memory _symbol,
   109          uint8 _decimals
   110      )
   111          internal
   112          view
   113          returns (address)
   114      {
   115          bytes memory constructorArgs = abi.encode(address(l2StandardBridge), _remote, _name, _symbol, _decimals);
   116          bytes memory bytecode = abi.encodePacked(type(OptimismMintableERC20).creationCode, constructorArgs);
   117          bytes32 salt = keccak256(abi.encode(_remote, _name, _symbol, _decimals));
   118          bytes32 hash = keccak256(
   119              abi.encodePacked(bytes1(0xff), address(l2OptimismMintableERC20Factory), salt, keccak256(bytecode))
   120          );
   121          return address(uint160(uint256(hash)));
   122      }
   123  }