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 }