Skip to content

Commit

Permalink
feat: add superchain erc20 factory implementation (#23)
Browse files Browse the repository at this point in the history
* feat: add superchain erc20 factory implementation

* fix: remove createX comments
  • Loading branch information
agusduha authored Aug 19, 2024
1 parent 8b74736 commit 05a54f3
Show file tree
Hide file tree
Showing 8 changed files with 235 additions and 2 deletions.
8 changes: 8 additions & 0 deletions packages/contracts-bedrock/semver-lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,14 @@
"initCodeHash": "0xd49214518ea1a30a43fac09f28b2cee9be570894a500cef342762c9820a070b0",
"sourceCodeHash": "0x6943d40010dcbd1d51dc3668d0a154fbb1568ea49ebcf3aa039d65ef6eab321b"
},
"src/L2/OptimismSuperchainERC20Beacon.sol": {
"initCodeHash": "0xc9893a1ba9b6354ccbdc96918510c9402a0934a59f0cc4a6165955a8e8ee1f7d",
"sourceCodeHash": "0xd069f4bddd08c1435d286819e1bb765648a5ad861fa327547f52de65a372769e"
},
"src/L2/OptimismSuperchainERC20Factory.sol": {
"initCodeHash": "0x98011045722178751e4a1112892f7d9a11bc1f5e42ac18205b6d30a1f1476d24",
"sourceCodeHash": "0x3206f4640662183bfbcd9c183b0d1c5d67c3ea670143daa731f23f62c0ae0855"
},
"src/L2/SequencerFeeVault.sol": {
"initCodeHash": "0xb94145f571e92ee615c6fe903b6568e8aac5fe760b6b65148ffc45d2fb0f5433",
"sourceCodeHash": "0x8f2a54104e5e7105ba03ba37e3ef9b6684a447245f0e0b787ba4cca12957b97c"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
[
{
"inputs": [],
"name": "implementation",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "pure",
"type": "function"
},
{
"inputs": [],
"name": "version",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
[
{
"inputs": [
{
"internalType": "address",
"name": "_remoteToken",
"type": "address"
},
{
"internalType": "string",
"name": "_name",
"type": "string"
},
{
"internalType": "string",
"name": "_symbol",
"type": "string"
},
{
"internalType": "uint8",
"name": "_decimals",
"type": "uint8"
}
],
"name": "deploy",
"outputs": [
{
"internalType": "address",
"name": "_superchainERC20",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "superchainToken",
"type": "address"
}
],
"name": "deployments",
"outputs": [
{
"internalType": "address",
"name": "remoteToken",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "version",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "superchainToken",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "remoteToken",
"type": "address"
},
{
"indexed": false,
"internalType": "address",
"name": "deployer",
"type": "address"
}
],
"name": "OptimismSuperchainERC20Created",
"type": "event"
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[
{
"bytes": "32",
"label": "deployments",
"offset": 0,
"slot": "0",
"type": "mapping(address => address)"
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

import { IBeacon } from "@openzeppelin/contracts-v5/proxy/beacon/IBeacon.sol";
import { ISemver } from "src/universal/ISemver.sol";

/// @custom:proxied
/// @custom:predeployed 0x4200000000000000000000000000000000000027
/// @title OptimismSuperchainERC20Beacon
/// @notice OptimismSuperchainERC20Beacon is the beacon proxy for the OptimismSuperchainERC20 implementation.
contract OptimismSuperchainERC20Beacon is IBeacon, ISemver {
/// TODO: Replace with real implementation address
/// @notice Address of the OptimismSuperchainERC20 implementation.
address internal constant IMPLEMENTATION_ADDRESS = 0x0000000000000000000000000000000000000000;

/// @notice Semantic version.
/// @custom:semver 1.0.0-beta.1
string public constant version = "1.0.0-beta.1";

/// @inheritdoc IBeacon
function implementation() external pure override returns (address) {
return IMPLEMENTATION_ADDRESS;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

import { IOptimismERC20Factory } from "src/L2/IOptimismERC20Factory.sol";
import { ISemver } from "src/universal/ISemver.sol";
import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol";
import { Predeploys } from "src/libraries/Predeploys.sol";
import { BeaconProxy } from "@openzeppelin/contracts-v5/proxy/beacon/BeaconProxy.sol";
import { CREATE3 } from "@rari-capital/solmate/src/utils/CREATE3.sol";

/// @custom:proxied
/// @custom:predeployed 0x4200000000000000000000000000000000000026
/// @title OptimismSuperchainERC20Factory
/// @notice OptimismSuperchainERC20Factory is a factory contract that deploys OptimismSuperchainERC20 Beacon Proxies
/// using CREATE3.
contract OptimismSuperchainERC20Factory is IOptimismERC20Factory, ISemver {
/// @notice Mapping of the deployed OptimismSuperchainERC20 to the remote token address.
/// This is used to keep track of the token deployments.
mapping(address superchainToken => address remoteToken) public deployments;

/// @notice Emitted when a OptimismSuperchainERC20 is deployed.
/// @param superchainToken Address of the SuperchainERC20 deployment.
/// @param remoteToken Address of the corresponding token on the remote chain.
/// @param deployer Address of the account that deployed the token.
event OptimismSuperchainERC20Created(
address indexed superchainToken, address indexed remoteToken, address deployer
);

/// @notice Semantic version.
/// @custom:semver 1.0.0-beta.1
string public constant version = "1.0.0-beta.1";

/// @notice Deploys a OptimismSuperchainERC20 Beacon Proxy using CREATE3.
/// @param _remoteToken Address of the remote token.
/// @param _name Name of the OptimismSuperchainERC20.
/// @param _symbol Symbol of the OptimismSuperchainERC20.
/// @param _decimals Decimals of the OptimismSuperchainERC20.
/// @return _superchainERC20 Address of the OptimismSuperchainERC20 deployment.
function deploy(
address _remoteToken,
string memory _name,
string memory _symbol,
uint8 _decimals
)
external
returns (address _superchainERC20)
{
// Encode the `initialize` call data for the OptimismSuperchainERC20.
bytes memory initCallData =
abi.encodeCall(OptimismSuperchainERC20.initialize, (_remoteToken, _name, _symbol, _decimals));

// Encode the BeaconProxy creation code with the beacon contract address and the `initialize` call data.
bytes memory creationCode = bytes.concat(
type(BeaconProxy).creationCode, abi.encode(Predeploys.OPTIMISM_SUPERCHAIN_ERC20_BEACON, initCallData)
);

// Use CREATE3 for deterministic deployment.
bytes32 salt = keccak256(abi.encode(_remoteToken, _name, _symbol, _decimals));
_superchainERC20 = CREATE3.deploy({ salt: salt, creationCode: creationCode, value: 0 });

// Store OptimismSuperchainERC20 and remote token addresses
deployments[_superchainERC20] = _remoteToken;

emit OptimismSuperchainERC20Created(_superchainERC20, _remoteToken, msg.sender);
}
}
8 changes: 6 additions & 2 deletions packages/contracts-bedrock/src/libraries/Predeploys.sol
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,12 @@ library Predeploys {
/// @notice Address of the ETHLiquidity predeploy.
address internal constant ETH_LIQUIDITY = 0x4200000000000000000000000000000000000025;

/// TODO: Add correct predeploy address for OptimismSuperchainERC20Factory
/// @notice Address of the OptimismSuperchainERC20Factory predeploy.
address internal constant OPTIMISM_SUPERCHAIN_ERC20_FACTORY = 0x4200000000000000000000000000000000000026;

/// @notice Address of the OptimismSuperchainERC20Beacon predeploy.
address internal constant OPTIMISM_SUPERCHAIN_ERC20_BEACON = 0x4200000000000000000000000000000000000027;

/// @notice Returns the name of the predeploy at the given address.
function getName(address _addr) internal pure returns (string memory out_) {
require(isPredeployNamespace(_addr), "Predeploys: address must be a predeploy");
Expand Down Expand Up @@ -128,6 +130,7 @@ library Predeploys {
if (_addr == SUPERCHAIN_WETH) return "SuperchainWETH";
if (_addr == ETH_LIQUIDITY) return "ETHLiquidity";
if (_addr == OPTIMISM_SUPERCHAIN_ERC20_FACTORY) return "OptimismSuperchainERC20Factory";
if (_addr == OPTIMISM_SUPERCHAIN_ERC20_BEACON) return "OptimismSuperchainERC20Beacon";
revert("Predeploys: unnamed predeploy");
}

Expand All @@ -146,7 +149,8 @@ library Predeploys {
|| _addr == L1_FEE_VAULT || _addr == SCHEMA_REGISTRY || _addr == EAS || _addr == GOVERNANCE_TOKEN
|| (_useInterop && _addr == CROSS_L2_INBOX) || (_useInterop && _addr == L2_TO_L2_CROSS_DOMAIN_MESSENGER)
|| (_useInterop && _addr == SUPERCHAIN_WETH) || (_useInterop && _addr == ETH_LIQUIDITY)
|| (_useInterop && _addr == OPTIMISM_SUPERCHAIN_ERC20_FACTORY);
|| (_useInterop && _addr == OPTIMISM_SUPERCHAIN_ERC20_FACTORY)
|| (_useInterop && _addr == OPTIMISM_SUPERCHAIN_ERC20_BEACON);
}

function isPredeployNamespace(address _addr) internal pure returns (bool) {
Expand Down

0 comments on commit 05a54f3

Please sign in to comment.