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

     1  // SPDX-License-Identifier: MIT
     2  pragma solidity 0.8.15;
     3  
     4  import { StandardBridge } from "src/universal/StandardBridge.sol";
     5  import { CommonTest } from "test/setup/CommonTest.sol";
     6  import { OptimismMintableERC20, ILegacyMintableERC20 } from "src/universal/OptimismMintableERC20.sol";
     7  import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
     8  
     9  /// @title StandardBridgeTester
    10  /// @notice Simple wrapper around the StandardBridge contract that exposes
    11  ///         internal functions so they can be more easily tested directly.
    12  contract StandardBridgeTester is StandardBridge {
    13      constructor() StandardBridge() { }
    14  
    15      function isOptimismMintableERC20(address _token) external view returns (bool) {
    16          return _isOptimismMintableERC20(_token);
    17      }
    18  
    19      function isCorrectTokenPair(address _mintableToken, address _otherToken) external view returns (bool) {
    20          return _isCorrectTokenPair(_mintableToken, _otherToken);
    21      }
    22  
    23      receive() external payable override { }
    24  }
    25  
    26  /// @title LegacyMintable
    27  /// @notice Simple implementation of the legacy OptimismMintableERC20.
    28  contract LegacyMintable is ERC20, ILegacyMintableERC20 {
    29      constructor(string memory _name, string memory _ticker) ERC20(_name, _ticker) { }
    30  
    31      function l1Token() external pure returns (address) {
    32          return address(0);
    33      }
    34  
    35      function mint(address _to, uint256 _amount) external pure { }
    36  
    37      function burn(address _from, uint256 _amount) external pure { }
    38  
    39      /// @notice Implements ERC165. This implementation should not be changed as
    40      ///         it is how the actual legacy optimism mintable token does the
    41      ///         check. Allows for testing against code that is has been deployed,
    42      ///         assuming different compiler version is no problem.
    43      function supportsInterface(bytes4 _interfaceId) external pure returns (bool) {
    44          bytes4 firstSupportedInterface = bytes4(keccak256("supportsInterface(bytes4)")); // ERC165
    45          bytes4 secondSupportedInterface = ILegacyMintableERC20.l1Token.selector ^ ILegacyMintableERC20.mint.selector
    46              ^ ILegacyMintableERC20.burn.selector;
    47          return _interfaceId == firstSupportedInterface || _interfaceId == secondSupportedInterface;
    48      }
    49  }
    50  
    51  /// @title StandardBridge_Stateless_Test
    52  /// @notice Tests internal functions that require no existing state or contract
    53  ///         interactions with the messenger.
    54  contract StandardBridge_Stateless_Test is CommonTest {
    55      StandardBridgeTester internal bridge;
    56      OptimismMintableERC20 internal mintable;
    57      ERC20 internal erc20;
    58      LegacyMintable internal legacy;
    59  
    60      function setUp() public override {
    61          super.setUp();
    62  
    63          bridge = new StandardBridgeTester();
    64  
    65          mintable = new OptimismMintableERC20({
    66              _bridge: address(0),
    67              _remoteToken: address(0),
    68              _name: "Stonks",
    69              _symbol: "STONK",
    70              _decimals: 18
    71          });
    72  
    73          erc20 = new ERC20("Altcoin", "ALT");
    74          legacy = new LegacyMintable("Legacy", "LEG");
    75      }
    76  
    77      /// @notice Test coverage for identifying OptimismMintableERC20 tokens.
    78      ///         This function should return true for both modern and legacy
    79      ///         OptimismMintableERC20 tokens and false for any accounts that
    80      ///         do not implement the interface.
    81      function test_isOptimismMintableERC20_succeeds() external {
    82          // Both the modern and legacy mintable tokens should return true
    83          assertTrue(bridge.isOptimismMintableERC20(address(mintable)));
    84          assertTrue(bridge.isOptimismMintableERC20(address(legacy)));
    85          // A regular ERC20 should return false
    86          assertFalse(bridge.isOptimismMintableERC20(address(erc20)));
    87          // Non existent contracts should return false and not revert
    88          assertEq(address(0x20).code.length, 0);
    89          assertFalse(bridge.isOptimismMintableERC20(address(0x20)));
    90      }
    91  
    92      /// @notice Test coverage of isCorrectTokenPair under different types of
    93      ///         tokens.
    94      function test_isCorrectTokenPair_succeeds() external {
    95          // Modern + known to be correct remote token
    96          assertTrue(bridge.isCorrectTokenPair(address(mintable), mintable.remoteToken()));
    97          // Modern + known to be correct l1Token (legacy interface)
    98          assertTrue(bridge.isCorrectTokenPair(address(mintable), mintable.l1Token()));
    99          // Modern + known to be incorrect remote token
   100          assertTrue(mintable.remoteToken() != address(0x20));
   101          assertFalse(bridge.isCorrectTokenPair(address(mintable), address(0x20)));
   102          // Legacy + known to be correct l1Token
   103          assertTrue(bridge.isCorrectTokenPair(address(legacy), legacy.l1Token()));
   104          // Legacy + known to be incorrect l1Token
   105          assertTrue(legacy.l1Token() != address(0x20));
   106          assertFalse(bridge.isCorrectTokenPair(address(legacy), address(0x20)));
   107          // A token that doesn't support either modern or legacy interface
   108          // will revert
   109          vm.expectRevert(bytes(""));
   110          bridge.isCorrectTokenPair(address(erc20), address(1));
   111      }
   112  
   113      /// @notice The bridge by default should be unpaused.
   114      function test_paused_succeeds() external {
   115          assertFalse(bridge.paused());
   116      }
   117  }