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

     1  // SPDX-License-Identifier: MIT
     2  pragma solidity 0.8.15;
     3  
     4  import { ERC721Enumerable } from "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
     5  import { ERC721 } from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
     6  import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
     7  import { Strings } from "@openzeppelin/contracts/utils/Strings.sol";
     8  import { IOptimismMintableERC721 } from "src/universal/IOptimismMintableERC721.sol";
     9  import { ISemver } from "src/universal/ISemver.sol";
    10  
    11  /// @title OptimismMintableERC721
    12  /// @notice This contract is the remote representation for some token that lives on another network,
    13  ///         typically an Optimism representation of an Ethereum-based token. Standard reference
    14  ///         implementation that can be extended or modified according to your needs.
    15  contract OptimismMintableERC721 is ERC721Enumerable, IOptimismMintableERC721, ISemver {
    16      /// @inheritdoc IOptimismMintableERC721
    17      uint256 public immutable REMOTE_CHAIN_ID;
    18  
    19      /// @inheritdoc IOptimismMintableERC721
    20      address public immutable REMOTE_TOKEN;
    21  
    22      /// @inheritdoc IOptimismMintableERC721
    23      address public immutable BRIDGE;
    24  
    25      /// @notice Base token URI for this token.
    26      string public baseTokenURI;
    27  
    28      /// @notice Modifier that prevents callers other than the bridge from calling the function.
    29      modifier onlyBridge() {
    30          require(msg.sender == BRIDGE, "OptimismMintableERC721: only bridge can call this function");
    31          _;
    32      }
    33  
    34      /// @notice Semantic version.
    35      /// @custom:semver 1.3.0
    36      string public constant version = "1.3.0";
    37  
    38      /// @param _bridge        Address of the bridge on this network.
    39      /// @param _remoteChainId Chain ID where the remote token is deployed.
    40      /// @param _remoteToken   Address of the corresponding token on the other network.
    41      /// @param _name          ERC721 name.
    42      /// @param _symbol        ERC721 symbol.
    43      constructor(
    44          address _bridge,
    45          uint256 _remoteChainId,
    46          address _remoteToken,
    47          string memory _name,
    48          string memory _symbol
    49      )
    50          ERC721(_name, _symbol)
    51      {
    52          require(_bridge != address(0), "OptimismMintableERC721: bridge cannot be address(0)");
    53          require(_remoteChainId != 0, "OptimismMintableERC721: remote chain id cannot be zero");
    54          require(_remoteToken != address(0), "OptimismMintableERC721: remote token cannot be address(0)");
    55  
    56          REMOTE_CHAIN_ID = _remoteChainId;
    57          REMOTE_TOKEN = _remoteToken;
    58          BRIDGE = _bridge;
    59  
    60          // Creates a base URI in the format specified by EIP-681:
    61          // https://eips.ethereum.org/EIPS/eip-681
    62          baseTokenURI = string(
    63              abi.encodePacked(
    64                  "ethereum:",
    65                  Strings.toHexString(uint160(_remoteToken), 20),
    66                  "@",
    67                  Strings.toString(_remoteChainId),
    68                  "/tokenURI?uint256="
    69              )
    70          );
    71      }
    72  
    73      /// @inheritdoc IOptimismMintableERC721
    74      function remoteChainId() external view returns (uint256) {
    75          return REMOTE_CHAIN_ID;
    76      }
    77  
    78      /// @inheritdoc IOptimismMintableERC721
    79      function remoteToken() external view returns (address) {
    80          return REMOTE_TOKEN;
    81      }
    82  
    83      /// @inheritdoc IOptimismMintableERC721
    84      function bridge() external view returns (address) {
    85          return BRIDGE;
    86      }
    87  
    88      /// @inheritdoc IOptimismMintableERC721
    89      function safeMint(address _to, uint256 _tokenId) external virtual onlyBridge {
    90          _safeMint(_to, _tokenId);
    91  
    92          emit Mint(_to, _tokenId);
    93      }
    94  
    95      /// @inheritdoc IOptimismMintableERC721
    96      function burn(address _from, uint256 _tokenId) external virtual onlyBridge {
    97          _burn(_tokenId);
    98  
    99          emit Burn(_from, _tokenId);
   100      }
   101  
   102      /// @notice Checks if a given interface ID is supported by this contract.
   103      /// @param _interfaceId The interface ID to check.
   104      /// @return True if the interface ID is supported, false otherwise.
   105      function supportsInterface(bytes4 _interfaceId) public view override(ERC721Enumerable, IERC165) returns (bool) {
   106          bytes4 iface = type(IOptimismMintableERC721).interfaceId;
   107          return _interfaceId == iface || super.supportsInterface(_interfaceId);
   108      }
   109  
   110      /// @notice Returns the base token URI.
   111      /// @return Base token URI.
   112      function _baseURI() internal view virtual override returns (string memory) {
   113          return baseTokenURI;
   114      }
   115  }