github.com/ethereum-optimism/optimism@v1.7.2/packages/contracts-bedrock/src/universal/OptimismMintableERC20.sol (about) 1 // SPDX-License-Identifier: MIT 2 pragma solidity 0.8.15; 3 4 import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 5 import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; 6 import { ILegacyMintableERC20, IOptimismMintableERC20 } from "src/universal/IOptimismMintableERC20.sol"; 7 import { ISemver } from "src/universal/ISemver.sol"; 8 9 /// @title OptimismMintableERC20 10 /// @notice OptimismMintableERC20 is a standard extension of the base ERC20 token contract designed 11 /// to allow the StandardBridge contracts to mint and burn tokens. This makes it possible to 12 /// use an OptimismMintablERC20 as the L2 representation of an L1 token, or vice-versa. 13 /// Designed to be backwards compatible with the older StandardL2ERC20 token which was only 14 /// meant for use on L2. 15 contract OptimismMintableERC20 is IOptimismMintableERC20, ILegacyMintableERC20, ERC20, ISemver { 16 /// @notice Address of the corresponding version of this token on the remote chain. 17 address public immutable REMOTE_TOKEN; 18 19 /// @notice Address of the StandardBridge on this network. 20 address public immutable BRIDGE; 21 22 /// @notice Decimals of the token 23 uint8 private immutable DECIMALS; 24 25 /// @notice Emitted whenever tokens are minted for an account. 26 /// @param account Address of the account tokens are being minted for. 27 /// @param amount Amount of tokens minted. 28 event Mint(address indexed account, uint256 amount); 29 30 /// @notice Emitted whenever tokens are burned from an account. 31 /// @param account Address of the account tokens are being burned from. 32 /// @param amount Amount of tokens burned. 33 event Burn(address indexed account, uint256 amount); 34 35 /// @notice A modifier that only allows the bridge to call 36 modifier onlyBridge() { 37 require(msg.sender == BRIDGE, "OptimismMintableERC20: only bridge can mint and burn"); 38 _; 39 } 40 41 /// @notice Semantic version. 42 /// @custom:semver 1.3.0 43 string public constant version = "1.3.0"; 44 45 /// @param _bridge Address of the L2 standard bridge. 46 /// @param _remoteToken Address of the corresponding L1 token. 47 /// @param _name ERC20 name. 48 /// @param _symbol ERC20 symbol. 49 constructor( 50 address _bridge, 51 address _remoteToken, 52 string memory _name, 53 string memory _symbol, 54 uint8 _decimals 55 ) 56 ERC20(_name, _symbol) 57 { 58 REMOTE_TOKEN = _remoteToken; 59 BRIDGE = _bridge; 60 DECIMALS = _decimals; 61 } 62 63 /// @notice Allows the StandardBridge on this network to mint tokens. 64 /// @param _to Address to mint tokens to. 65 /// @param _amount Amount of tokens to mint. 66 function mint( 67 address _to, 68 uint256 _amount 69 ) 70 external 71 virtual 72 override(IOptimismMintableERC20, ILegacyMintableERC20) 73 onlyBridge 74 { 75 _mint(_to, _amount); 76 emit Mint(_to, _amount); 77 } 78 79 /// @notice Allows the StandardBridge on this network to burn tokens. 80 /// @param _from Address to burn tokens from. 81 /// @param _amount Amount of tokens to burn. 82 function burn( 83 address _from, 84 uint256 _amount 85 ) 86 external 87 virtual 88 override(IOptimismMintableERC20, ILegacyMintableERC20) 89 onlyBridge 90 { 91 _burn(_from, _amount); 92 emit Burn(_from, _amount); 93 } 94 95 /// @notice ERC165 interface check function. 96 /// @param _interfaceId Interface ID to check. 97 /// @return Whether or not the interface is supported by this contract. 98 function supportsInterface(bytes4 _interfaceId) external pure virtual returns (bool) { 99 bytes4 iface1 = type(IERC165).interfaceId; 100 // Interface corresponding to the legacy L2StandardERC20. 101 bytes4 iface2 = type(ILegacyMintableERC20).interfaceId; 102 // Interface corresponding to the updated OptimismMintableERC20 (this contract). 103 bytes4 iface3 = type(IOptimismMintableERC20).interfaceId; 104 return _interfaceId == iface1 || _interfaceId == iface2 || _interfaceId == iface3; 105 } 106 107 /// @custom:legacy 108 /// @notice Legacy getter for the remote token. Use REMOTE_TOKEN going forward. 109 function l1Token() public view returns (address) { 110 return REMOTE_TOKEN; 111 } 112 113 /// @custom:legacy 114 /// @notice Legacy getter for the bridge. Use BRIDGE going forward. 115 function l2Bridge() public view returns (address) { 116 return BRIDGE; 117 } 118 119 /// @custom:legacy 120 /// @notice Legacy getter for REMOTE_TOKEN. 121 function remoteToken() public view returns (address) { 122 return REMOTE_TOKEN; 123 } 124 125 /// @custom:legacy 126 /// @notice Legacy getter for BRIDGE. 127 function bridge() public view returns (address) { 128 return BRIDGE; 129 } 130 131 /// @dev Returns the number of decimals used to get its user representation. 132 /// For example, if `decimals` equals `2`, a balance of `505` tokens should 133 /// be displayed to a user as `5.05` (`505 / 10 ** 2`). 134 /// NOTE: This information is only used for _display_ purposes: it in 135 /// no way affects any of the arithmetic of the contract, including 136 /// {IERC20-balanceOf} and {IERC20-transfer}. 137 function decimals() public view override returns (uint8) { 138 return DECIMALS; 139 } 140 }