-
Notifications
You must be signed in to change notification settings - Fork 26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
design-doc: SuperchainERC20 Factory for L1 native tokens #50
Changes from 1 commit
1f40f44
d9c30a2
6f397c3
831fb3f
7db5a5d
afed89b
58f554f
33c0f9a
530c606
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,21 +4,21 @@ This document presents the requirements for a factory that deploys `SuperchainER | |
|
||
## Overview | ||
|
||
The `SuperchainERC20Factory` will be a proxied predeploy. It will deploy proxied `SuperchainERC20` tokens using the Beacon pattern. This structure allows upgrading all `SuperchainERC20` implementations at once if needed. | ||
The `SuperchainERC20Factory` will be a proxied predeploy. It will deploy proxied `SuperchainERC20` tokens using the Beacon pattern. This structure allows upgrading all implementations at once if needed. | ||
|
||
Even though this document is specific for L1 native tokens, it should serve as a basis for other cases. | ||
|
||
## Problem Statement + Context | ||
|
||
The `SuperchainERC20` [standard](https://github.com/ethereum-optimism/specs/blob/aee0b2b2b45447daedef4b09bedc1fe7794d645d/specs/interop/token-bridging.md) will make ERC20s interoperable across the Superchain. However, the standard does not solve one of the main challenges in the future of Superchain: dealing with synchronized deployments and upgrades. | ||
|
||
Moreover, the `SuperchainERC20` corresponding to a legacy token will require a liquidity migration conversion method, as presented in the corresponding [spec document](https://github.com/ethereum-optimism/specs/pull/294). The system requires a registry to track the allowed representations for the conversion to be safe. | ||
Moreover, the `SuperchainERC20` corresponding to a legacy token (`OptimismSuperchainERC20`) will require a liquidity migration conversion method, as presented in the corresponding [spec document](https://github.com/ethereum-optimism/specs/pull/294). The system requires a registry to track the allowed representations for the conversion to be safe. | ||
|
||
Both these problems can be solved by introducing factories that comply with the following requirements: | ||
|
||
- **Same address deployment:** the `SuperchainERC20` standard requires the same address across chains. | ||
- Notice this is not strictly necessary: allowing different addresses of `SuperchainERC20`s to communicate using a registry is possible. However, maintaining a registry would be a demanding task. | ||
- **Implementation upgradability:** it should be easy to upgrade `SuperchainERC20` implementations across chains. | ||
- **Implementation upgradability:** it should be easy to upgrade `OptimismSuperchainERC20` implementations across chains. | ||
- **Factory upgradability:** The factory should be upgradable to follow OP Factories structure. | ||
- **Deployment history:** The factory should keep a history of deployed tokens, acting as a registry. | ||
|
||
|
@@ -33,21 +33,21 @@ In what follows, we will list each requirement and detail how the factory should | |
|
||
**Predeploys** | ||
|
||
Factories will live in each L2 as a predeploy on the same address, which is crucial to achieving the same address for `SuperchainERC20`s across chains. | ||
Factories will live in each L2 as a predeploy on the same address, which is crucial to achieving the same address for `OptimismSuperchainERC20`s across chains. | ||
|
||
If the same address for the `SuperchainERC20` on L1 is also needed, then the address at which the predeploy is initialized should match the factory's L1 address. | ||
If the same address for the `OptimismSuperchainERC20` on L1 is also needed, then the address at which the predeploy is initialized should match the factory's L1 address. | ||
tynes marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
**Creation method** | ||
|
||
The `SuperchainERC20` addresses should be independent of the implementations. `CREATE` was discarded due to nonce dependability, and `CREATE2` was discarded because of its dependence on the creation code. For these reasons, the factory should use `CREATE3`. | ||
The `OptimismSuperchainERC20` addresses should be independent of the implementations. `CREATE` was discarded due to nonce dependability, and `CREATE2` was discarded because of its dependence on the creation code. For these reasons, the factory should use `CREATE3`. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should consider calling out to Disclaimer: I helped write CreateX There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like the idea of having a CreateX preinstall. We where discussing having the CREATE3 one. Let's discuss this in the review meeting |
||
|
||
The salt will be composed of the L1 address and the token metadata. This implies that the same L1 token can have multiple SuperchainERC20 representation, as long as the metadata also changes. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the rationale here? Why not just use the L1 address as the salt? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Doing so would imply having a single |
||
|
||
### Implementation Upgradability: Beacon Proxies | ||
|
||
**BeaconProxies** | ||
|
||
The factory will deploy `SuperchainERC20`s as BeaconProxies, as this is the easiest way to upgrade multiple proxies simultaneously. Each BeaconProxy will delegate-call to the implementation address provided by the Beacon Contract. | ||
The factory will deploy `OptimismSuperchainERC20`s as BeaconProxies, as this is the easiest way to upgrade multiple proxies simultaneously. Each BeaconProxy will delegate-call to the implementation address provided by the Beacon Contract. | ||
|
||
**Beacon Contract** | ||
|
||
|
@@ -68,10 +68,10 @@ The factory will be a simple Proxy contract pointing to the current implementati | |
The factory will store a `deployments` mapping that the `L2StandardBridge` will check for access control when converting between the SuperchainERC20 and their corresponding legacy representations (see the [liquidity migration specs](https://github.com/ethereum-optimism/specs/pull/294) for more details). | ||
|
||
```solidity | ||
mapping(address => address) public deployments; | ||
mapping(address superc20 => address remoteToken) public deployments; | ||
``` | ||
|
||
that maps each deployed SuperchainERC20 address to the corresponding L1 address (remote address). | ||
that maps each deployed `OptimismSuperchainERC20` address to the corresponding L1 address (remote address). | ||
|
||
## Implementation | ||
|
||
|
@@ -82,32 +82,32 @@ Will follow the [`Proxy.sol` implementation](https://github.com/ethereum-optimis | |
**Factory Implementation** | ||
|
||
```solidity | ||
contract SuperchainERC20Factory is Semver { | ||
mapping(address => address) public deployments; | ||
contract OptimismSuperchainERC20Factory is Semver { | ||
tynes marked this conversation as resolved.
Show resolved
Hide resolved
|
||
mapping(address superc20 => address remoteToken) public deployments; | ||
|
||
event SuperchainERC20Deployed(address indexed superchainERC20, address indexed remoteToken, string name, string symbol, uint8 decimals); | ||
event OptimismSuperchainERC20Deployed(address indexed superchainERC20, address indexed remoteToken, string name, string symbol, uint8 decimals); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We’re looking for ways to establish common standards regarding deployments. For The same reasoning can be applied to parameters stored for each representation, based on having a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should focus specifically on L1 native tokens for this factory as they are a majority of the liquidity and then return to the problem of making a more generic factory in the future There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
||
constructor() Semver(1, 0, 0) {} | ||
|
||
function deploy(address _remoteToken, string memory _name, string memory _symbol, uint8 _decimals) external returns (address _superchainERC20) { | ||
bytes memory _creationCode = abi.encodePacked( | ||
type(BeaconProxy).creationCode, | ||
abi.encode(Predeploy.SuperchainERC20Beacon, abi.encodeCall(SUPERCHAIN_IMPL.initialize.selector, (_remoteToken, _name, _symbol, _decimals))) | ||
abi.encode(Predeploy.OptimismSuperchainERC20Beacon, abi.encodeCall(SUPERCHAIN_IMPL.initialize.selector, (_remoteToken, _name, _symbol, _decimals))) | ||
); | ||
|
||
bytes32 salt = keccak256(abi.encode(_remoteToken, _name, _symbol, _decimals)); | ||
_superchainERC20 = CREATE3.deploy(salt, _creationCode); | ||
|
||
deployments[_superchainERC20] = _remoteToken; | ||
|
||
emit SuperchainERC20Deployed(_superchainERC20, _remoteToken _name, _symbol, _decimals); | ||
emit OptimismSuperchainERC20Deployed(_superchainERC20, _remoteToken _name, _symbol, _decimals); | ||
} | ||
} | ||
``` | ||
|
||
The name `_remoteToken` was chosen over `_l1Token` to contemplate future L2 native cases. | ||
tynes marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
**BeaconProxy (SuperchainERC20)** | ||
**BeaconProxy (OptimismSuperchainERC20)** | ||
|
||
The Token should follow a simple BeaconProxy implementation, like Openzeppelin: | ||
|
||
|
@@ -116,7 +116,7 @@ https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/pro | |
**Beacon Contract** | ||
|
||
```solidity | ||
contract SuperchainERC20Beacon is IBeacon { | ||
contract OptimismSuperchainERC20Beacon is IBeacon { | ||
/// TODO: Replace with real implementation address | ||
address internal constant IMPLEMENTATION_ADDRESS = 0x0000000000000000000000000000000000000000; | ||
|
||
|
@@ -134,9 +134,9 @@ The implementation should include | |
|
||
## User Stories | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It sounds like we also need a section here explaining the interactions with the L2StandardBridge |
||
|
||
### `SuperchainERC20` deployment | ||
### `OptimismSuperchainERC20` deployment | ||
|
||
1. Anyone can deploy a SuperchainERC20 by calling the `deploy` function in the `SuperchainERC20Factory` contract with `_remoteToken`, `_name`, `_symbol` and `decimals` as inputs. | ||
1. Anyone can deploy a `OptimismSuperchainERC20` by calling the `deploy` function in the `OptimismSuperchainERC20Factory` contract with `_remoteToken`, `_name`, `_symbol` and `decimals` as inputs. | ||
2. The factory stores the `_remoteToken` address for each deployed SuperchainERC20 address. | ||
|
||
```mermaid | ||
|
@@ -145,17 +145,17 @@ sequenceDiagram | |
participant FactoryProxy | ||
participant FactoryImpl | ||
participant CREATE3Proxy | ||
participant Token BeaconProxy | ||
participant BeaconProxy as OptimismSuperchainERC20 BeaconProxy | ||
participant Beacon Contract | ||
participant Implementation | ||
|
||
Alice->>FactoryProxy: deploy(remoteToken, name, symbol, decimals) | ||
FactoryProxy->>FactoryImpl: delegatecall() | ||
FactoryProxy-->FactoryProxy: deployments[superchainERC20]=remoteToken | ||
FactoryProxy->>CREATE3Proxy: create2() | ||
CREATE3Proxy->>Token BeaconProxy: create() | ||
Token BeaconProxy-->Beacon Contract: reads implementation() | ||
Token BeaconProxy->>Implementation: delegatecall() | ||
CREATE3Proxy->>BeaconProxy: create() | ||
BeaconProxy-->Beacon Contract: reads implementation() | ||
BeaconProxy->>Implementation: delegatecall() | ||
``` | ||
|
||
### `SuperchainERC20` implementation upgrade | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit, can we rename the file to something like
SuperchainERC20-factory.md
? The filename sounds like the factory lives on L1, which is not the case since it's a predeployThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My only concern is that this factory is specific for tokens that are native to L1. We can still name it like that and change notation for the others (l2 native, etc)