From d890e124bce855a5a35943e23f5a0a6a1ce79a6d Mon Sep 17 00:00:00 2001 From: Sander Bosma Date: Wed, 17 Apr 2024 13:34:04 +0200 Subject: [PATCH] chore: copy of OptimismMintableERC20.sol --- .../OptimismMintableUpgradableERC20.sol | 149 ++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 packages/contracts-bedrock/contracts/universal/OptimismMintableUpgradableERC20.sol diff --git a/packages/contracts-bedrock/contracts/universal/OptimismMintableUpgradableERC20.sol b/packages/contracts-bedrock/contracts/universal/OptimismMintableUpgradableERC20.sol new file mode 100644 index 0000000000000..d1d6043bafafb --- /dev/null +++ b/packages/contracts-bedrock/contracts/universal/OptimismMintableUpgradableERC20.sol @@ -0,0 +1,149 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; +import { ILegacyMintableERC20, IOptimismMintableERC20 } from "./IOptimismMintableERC20.sol"; +import { Semver } from "../universal/Semver.sol"; + +/** + * @title OptimismMintableERC20 + * @notice OptimismMintableERC20 is a standard extension of the base ERC20 token contract designed + * to allow the StandardBridge contracts to mint and burn tokens. This makes it possible to + * use an OptimismMintablERC20 as the L2 representation of an L1 token, or vice-versa. + * Designed to be backwards compatible with the older StandardL2ERC20 token which was only + * meant for use on L2. + */ +contract OptimismMintableERC20 is IOptimismMintableERC20, ILegacyMintableERC20, ERC20, Semver { + /** + * @notice Address of the corresponding version of this token on the remote chain. + */ + address public immutable REMOTE_TOKEN; + + /** + * @notice Address of the StandardBridge on this network. + */ + address public immutable BRIDGE; + + /** + * @notice Emitted whenever tokens are minted for an account. + * + * @param account Address of the account tokens are being minted for. + * @param amount Amount of tokens minted. + */ + event Mint(address indexed account, uint256 amount); + + /** + * @notice Emitted whenever tokens are burned from an account. + * + * @param account Address of the account tokens are being burned from. + * @param amount Amount of tokens burned. + */ + event Burn(address indexed account, uint256 amount); + + /** + * @notice A modifier that only allows the bridge to call + */ + modifier onlyBridge() { + require(msg.sender == BRIDGE, "OptimismMintableERC20: only bridge can mint and burn"); + _; + } + + /** + * @custom:semver 1.0.0 + * + * @param _bridge Address of the L2 standard bridge. + * @param _remoteToken Address of the corresponding L1 token. + * @param _name ERC20 name. + * @param _symbol ERC20 symbol. + */ + constructor( + address _bridge, + address _remoteToken, + string memory _name, + string memory _symbol + ) ERC20(_name, _symbol) Semver(1, 0, 0) { + REMOTE_TOKEN = _remoteToken; + BRIDGE = _bridge; + } + + /** + * @notice Allows the StandardBridge on this network to mint tokens. + * + * @param _to Address to mint tokens to. + * @param _amount Amount of tokens to mint. + */ + function mint(address _to, uint256 _amount) + external + virtual + override(IOptimismMintableERC20, ILegacyMintableERC20) + onlyBridge + { + _mint(_to, _amount); + emit Mint(_to, _amount); + } + + /** + * @notice Allows the StandardBridge on this network to burn tokens. + * + * @param _from Address to burn tokens from. + * @param _amount Amount of tokens to burn. + */ + function burn(address _from, uint256 _amount) + external + virtual + override(IOptimismMintableERC20, ILegacyMintableERC20) + onlyBridge + { + _burn(_from, _amount); + emit Burn(_from, _amount); + } + + /** + * @notice ERC165 interface check function. + * + * @param _interfaceId Interface ID to check. + * + * @return Whether or not the interface is supported by this contract. + */ + function supportsInterface(bytes4 _interfaceId) external pure returns (bool) { + bytes4 iface1 = type(IERC165).interfaceId; + // Interface corresponding to the legacy L2StandardERC20. + bytes4 iface2 = type(ILegacyMintableERC20).interfaceId; + // Interface corresponding to the updated OptimismMintableERC20 (this contract). + bytes4 iface3 = type(IOptimismMintableERC20).interfaceId; + return _interfaceId == iface1 || _interfaceId == iface2 || _interfaceId == iface3; + } + + /** + * @custom:legacy + * @notice Legacy getter for the remote token. Use REMOTE_TOKEN going forward. + */ + function l1Token() public view returns (address) { + return REMOTE_TOKEN; + } + + /** + * @custom:legacy + * @notice Legacy getter for the bridge. Use BRIDGE going forward. + */ + function l2Bridge() public view returns (address) { + return BRIDGE; + } + + /** + * @custom:legacy + * @notice Legacy getter for REMOTE_TOKEN. + */ + function remoteToken() public view returns (address) { + return REMOTE_TOKEN; + } + + /** + * @custom:legacy + * @notice Legacy getter for BRIDGE. + */ + function bridge() public view returns (address) { + return BRIDGE; + } +}