From dcae6b0e799b5aad3a5b678942d056fb1f10fc52 Mon Sep 17 00:00:00 2001 From: agusduha Date: Thu, 8 Aug 2024 11:28:52 -0300 Subject: [PATCH] feat: modify OptimismMintableERC20Factory for convert --- .../src/L2/IOptimismERC20Factory.sol | 4 +- .../OptimismMintableERC20Factory.sol | 30 +++--- .../OptimismMintableERC20FactoryInterop.sol | 97 +++++++++++++++++++ 3 files changed, 113 insertions(+), 18 deletions(-) create mode 100644 packages/contracts-bedrock/src/universal/OptimismMintableERC20FactoryInterop.sol diff --git a/packages/contracts-bedrock/src/L2/IOptimismERC20Factory.sol b/packages/contracts-bedrock/src/L2/IOptimismERC20Factory.sol index 0286a8f7b34e..5e0040aa83cf 100644 --- a/packages/contracts-bedrock/src/L2/IOptimismERC20Factory.sol +++ b/packages/contracts-bedrock/src/L2/IOptimismERC20Factory.sol @@ -6,7 +6,7 @@ pragma solidity ^0.8.0; /// determine if a ERC20 contract is deployed by a factory. interface IOptimismERC20Factory { /// @notice Checks if a ERC20 token is deployed by the factory. - /// @param _token The address of the ERC20 token to check the deployment. + /// @param _localToken The address of the ERC20 token to check the deployment. /// @return _remoteToken The address of the remote token if it is deployed or `address(0)` if not. - function deployments(address _token) external view returns (address _remoteToken); + function deployments(address _localToken) external view returns (address _remoteToken); } diff --git a/packages/contracts-bedrock/src/universal/OptimismMintableERC20Factory.sol b/packages/contracts-bedrock/src/universal/OptimismMintableERC20Factory.sol index 6e7baf31f1fb..d0ec64eb56a6 100644 --- a/packages/contracts-bedrock/src/universal/OptimismMintableERC20Factory.sol +++ b/packages/contracts-bedrock/src/universal/OptimismMintableERC20Factory.sol @@ -43,8 +43,8 @@ contract OptimismMintableERC20Factory is ISemver, Initializable { /// the OptimismMintableERC20 token contract since this contract /// is responsible for deploying OptimismMintableERC20 contracts. /// @notice Semantic version. - /// @custom:semver 1.9.0 - string public constant version = "1.9.0"; + /// @custom:semver 1.10.0 + string public constant version = "1.10.0"; /// @notice Constructs the OptimismMintableERC20Factory contract. constructor() { @@ -114,19 +114,17 @@ contract OptimismMintableERC20Factory is ISemver, Initializable { public returns (address) { - require(_remoteToken != address(0), "OptimismMintableERC20Factory: must provide remote token address"); - - bytes32 salt = keccak256(abi.encode(_remoteToken, _name, _symbol, _decimals)); - address localToken = - address(new OptimismMintableERC20{ salt: salt }(bridge, _remoteToken, _name, _symbol, _decimals)); - - // Emit the old event too for legacy support. - emit StandardL2TokenCreated(_remoteToken, localToken); - - // Emit the updated event. The arguments here differ from the legacy event, but - // are consistent with the ordering used in StandardBridge events. - emit OptimismMintableERC20Created(localToken, _remoteToken, msg.sender); - - return localToken; + return _createWithCreate3(_remoteToken, _name, _symbol, _decimals); } + + function _createWithCreate3( + address _remoteToken, + string memory _name, + string memory _symbol, + uint8 _decimals + ) + internal + virtual + returns (address) + { } } diff --git a/packages/contracts-bedrock/src/universal/OptimismMintableERC20FactoryInterop.sol b/packages/contracts-bedrock/src/universal/OptimismMintableERC20FactoryInterop.sol new file mode 100644 index 000000000000..04a8cefcda94 --- /dev/null +++ b/packages/contracts-bedrock/src/universal/OptimismMintableERC20FactoryInterop.sol @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import { OptimismMintableERC20Factory, OptimismMintableERC20 } from "src/universal/OptimismMintableERC20Factory.sol"; +import { IOptimismERC20Factory } from "src/L2/IOptimismERC20Factory.sol"; +import { CREATE3 } from "@rari-capital/solmate/src/utils/CREATE3.sol"; + +/// @custom:proxied +/// @custom:predeployed 0x4200000000000000000000000000000000000012 +/// @title OptimismMintableERC20FactoryInterop +/// @notice OptimismMintableERC20FactoryInterop is a factory contract that generates OptimismMintableERC20 +/// contracts on the network it's deployed to, using CREATE3. Simplifies the deployment process for users +/// who may be less familiar with deploying smart contracts. Designed to be backwards +/// compatible with the older OptimismMintableERC20Factory contract. +contract OptimismMintableERC20FactoryInterop is OptimismMintableERC20Factory, IOptimismERC20Factory { + /// @notice Storage slot that the OptimismMintableERC20FactoryInteropStorage struct is stored at. + /// keccak256(abi.encode(uint256(keccak256("optimismMintableERC20FactoryInterop.storage")) - 1)) & + /// ~bytes32(uint256(0xff)); + bytes32 internal constant OPTIMISM_MINTABLE_ERC20_FACTORY_INTEROP_SLOT = + 0xb6fdf24dfda35722597f70f86628ef4ce6db853b20879bdd2d61f0f5d169b100; + + /// @notice Storage struct for the OptimismMintableERC20FactoryInterop storage. + /// @custom:storage-location erc7201:optimismMintableERC20FactoryInterop.storage + struct OptimismMintableERC20FactoryInteropStorage { + /// @notice Mapping of local token address to remote token address. + mapping(address => address) deployments; + } + + /// @notice Returns the storage for the OptimismMintableERC20FactoryInteropStorage. + function _getStorage() private pure returns (OptimismMintableERC20FactoryInteropStorage storage _storage) { + assembly { + _storage.slot := OPTIMISM_MINTABLE_ERC20_FACTORY_INTEROP_SLOT + } + } + + /// @notice Creates an instance of the OptimismMintableERC20 contract, with specified decimals using CREATE3. + /// @param _remoteToken Address of the token on the remote chain. + /// @param _name ERC20 name. + /// @param _symbol ERC20 symbol. + /// @param _decimals ERC20 decimals. + /// @return Address of the newly created token. + function createWithCreate3( + address _remoteToken, + string memory _name, + string memory _symbol, + uint8 _decimals + ) + external + returns (address) + { + return _createWithCreate3(_remoteToken, _name, _symbol, _decimals); + } + + /// @notice Creates an instance of the OptimismMintableERC20 contract, with specified decimals using CREATE3. + /// @param _remoteToken Address of the token on the remote chain. + /// @param _name ERC20 name. + /// @param _symbol ERC20 symbol. + /// @param _decimals ERC20 decimals. + /// @return _localToken Address of the newly created token. + function _createWithCreate3( + address _remoteToken, + string memory _name, + string memory _symbol, + uint8 _decimals + ) + internal + override + returns (address _localToken) + { + require(_remoteToken != address(0), "OptimismMintableERC20Factory: must provide remote token address"); + + bytes memory creationCode = abi.encodePacked( + type(OptimismMintableERC20).creationCode, abi.encode(bridge, _remoteToken, _name, _symbol, _decimals) + ); + + bytes32 salt = keccak256(abi.encode(_remoteToken, _name, _symbol, _decimals)); + + _localToken = CREATE3.deploy({ salt: salt, creationCode: creationCode, value: 0 }); + + _getStorage().deployments[_localToken] = _remoteToken; + + // Emit the old event too for legacy support. + emit StandardL2TokenCreated(_remoteToken, _localToken); + + // Emit the updated event. The arguments here differ from the legacy event, but + // are consistent with the ordering used in StandardBridge events. + emit OptimismMintableERC20Created(_localToken, _remoteToken, msg.sender); + } + + /// @notice Returns the address of the token on the remote chain if the deployment exists, + /// else returns `address(0)`. + /// @param _localToken Address of the token on the local chain. + /// @return _remoteToken Address of the token on the remote chain. + function deployments(address _localToken) external view override returns (address _remoteToken) { + return _getStorage().deployments[_localToken]; + } +}