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

     1  // SPDX-License-Identifier: MIT
     2  pragma solidity 0.8.15;
     3  
     4  import { ERC721, IERC721 } from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
     5  import { IERC721Enumerable } from "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
     6  import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
     7  import { Strings } from "@openzeppelin/contracts/utils/Strings.sol";
     8  import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol";
     9  import { OptimismMintableERC721, IOptimismMintableERC721 } from "src/universal/OptimismMintableERC721.sol";
    10  
    11  contract OptimismMintableERC721_Test is Bridge_Initializer {
    12      ERC721 internal L1NFT;
    13      OptimismMintableERC721 internal L2NFT;
    14  
    15      event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
    16  
    17      event Mint(address indexed account, uint256 tokenId);
    18  
    19      event Burn(address indexed account, uint256 tokenId);
    20  
    21      function setUp() public override {
    22          super.setUp();
    23  
    24          // Set up the token pair.
    25          L1NFT = new ERC721("L1NFT", "L1T");
    26          L2NFT = new OptimismMintableERC721(address(l2ERC721Bridge), 1, address(L1NFT), "L2NFT", "L2T");
    27  
    28          // Label the addresses for nice traces.
    29          vm.label(address(L1NFT), "L1ERC721Token");
    30          vm.label(address(L2NFT), "L2ERC721Token");
    31      }
    32  
    33      function test_constructor_succeeds() external {
    34          assertEq(L2NFT.name(), "L2NFT");
    35          assertEq(L2NFT.symbol(), "L2T");
    36          assertEq(L2NFT.remoteToken(), address(L1NFT));
    37          assertEq(L2NFT.bridge(), address(l2ERC721Bridge));
    38          assertEq(L2NFT.remoteChainId(), 1);
    39          assertEq(L2NFT.REMOTE_TOKEN(), address(L1NFT));
    40          assertEq(L2NFT.BRIDGE(), address(l2ERC721Bridge));
    41          assertEq(L2NFT.REMOTE_CHAIN_ID(), 1);
    42      }
    43  
    44      /// @notice Ensure that the contract supports the expected interfaces.
    45      function test_supportsInterfaces_succeeds() external {
    46          // Checks if the contract supports the IOptimismMintableERC721 interface.
    47          assertTrue(L2NFT.supportsInterface(type(IOptimismMintableERC721).interfaceId));
    48          // Checks if the contract supports the IERC721Enumerable interface.
    49          assertTrue(L2NFT.supportsInterface(type(IERC721Enumerable).interfaceId));
    50          // Checks if the contract supports the IERC721 interface.
    51          assertTrue(L2NFT.supportsInterface(type(IERC721).interfaceId));
    52          // Checks if the contract supports the IERC165 interface.
    53          assertTrue(L2NFT.supportsInterface(type(IERC165).interfaceId));
    54      }
    55  
    56      function test_safeMint_succeeds() external {
    57          // Expect a transfer event.
    58          vm.expectEmit(true, true, true, true);
    59          emit Transfer(address(0), alice, 1);
    60  
    61          // Expect a mint event.
    62          vm.expectEmit(true, true, true, true);
    63          emit Mint(alice, 1);
    64  
    65          // Mint the token.
    66          vm.prank(address(l2ERC721Bridge));
    67          L2NFT.safeMint(alice, 1);
    68  
    69          // Token should be owned by alice.
    70          assertEq(L2NFT.ownerOf(1), alice);
    71      }
    72  
    73      function test_safeMint_notBridge_reverts() external {
    74          // Try to mint the token.
    75          vm.expectRevert("OptimismMintableERC721: only bridge can call this function");
    76          vm.prank(address(alice));
    77          L2NFT.safeMint(alice, 1);
    78      }
    79  
    80      function test_burn_succeeds() external {
    81          // Mint the token first.
    82          vm.prank(address(l2ERC721Bridge));
    83          L2NFT.safeMint(alice, 1);
    84  
    85          // Expect a transfer event.
    86          vm.expectEmit(true, true, true, true);
    87          emit Transfer(alice, address(0), 1);
    88  
    89          // Expect a burn event.
    90          vm.expectEmit(true, true, true, true);
    91          emit Burn(alice, 1);
    92  
    93          // Burn the token.
    94          vm.prank(address(l2ERC721Bridge));
    95          L2NFT.burn(alice, 1);
    96  
    97          // Token should be owned by address(0).
    98          vm.expectRevert("ERC721: invalid token ID");
    99          L2NFT.ownerOf(1);
   100      }
   101  
   102      function test_burn_notBridge_reverts() external {
   103          // Mint the token first.
   104          vm.prank(address(l2ERC721Bridge));
   105          L2NFT.safeMint(alice, 1);
   106  
   107          // Try to burn the token.
   108          vm.expectRevert("OptimismMintableERC721: only bridge can call this function");
   109          vm.prank(address(alice));
   110          L2NFT.burn(alice, 1);
   111      }
   112  
   113      function test_tokenURI_succeeds() external {
   114          // Mint the token first.
   115          vm.prank(address(l2ERC721Bridge));
   116          L2NFT.safeMint(alice, 1);
   117  
   118          // Token URI should be correct.
   119          assertEq(
   120              L2NFT.tokenURI(1),
   121              string(
   122                  abi.encodePacked(
   123                      "ethereum:",
   124                      Strings.toHexString(uint160(address(L1NFT)), 20),
   125                      "@",
   126                      Strings.toString(1),
   127                      "/tokenURI?uint256=",
   128                      Strings.toString(1)
   129                  )
   130              )
   131          );
   132      }
   133  }