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 }