-
Notifications
You must be signed in to change notification settings - Fork 3.2k
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
feat: introduce SuperchainERC20 redesign + ICrosschainERC20 #12321
base: develop
Are you sure you want to change the base?
feat: introduce SuperchainERC20 redesign + ICrosschainERC20 #12321
Conversation
* feat: add superchain erc20 bridge * fix: interfaces and versions
* refactor: use oz upgradeable erc20 as dependency * chore: update interfaces * fix: tests based on changes * refactor: remove op as dependency * feat: add check for supererc20 bridge on modifier * chore: update tests and interfaces * chore: update stack vars name on test * chore: remove empty gitmodules file * chore: update superchain weth errors
* test: add superchain erc20 bridge tests * test: add optimism superchain erc20 beacon tests * test: remove unnecessary test * test: tests fixes * test: tests fixes
* chore: update missing bridge on natspec * fix: natspecs --------- Co-authored-by: agusduha <[email protected]>
--------- Co-authored-by: agusduha <[email protected]>
* refactor: rename mint and burn functions on superchain erc20 * chore: rename optimism superchain erc20 to superchain erc20 * feat: create optimism superchain erc20 contract * chore: update natspec and errors * fix: superchain erc20 tests * refactor: make superchain erc20 abstract * refactor: move storage and erc20 metadata functions to implementation * chore: update interfaces * chore: update superchain erc20 events * fix: tests * fix: natspecs * fix: add semmver lock and snapshots * fix: remove unused imports * fix: natspecs --------- Co-authored-by: 0xDiscotech <[email protected]>
fix: update redesign with dev
* fix: semver natspec check failure * fix: ignore mock contracts in semver natspec script * fix: error message
* feat: add crosschain erc20 interface * fix: refactor interfaces
Co-authored-by: 0xng <[email protected]> Co-authored-by: 0xParticle <[email protected]> Co-authored-by: gotzenx <[email protected]>
* fix: stop inheriting superchain interfaces * fix: move events and erros into the implementation * fix: make superchainERC20 inherits from crosschainERC20
What is the |
@@ -129,9 +129,14 @@ func run() error { | |||
return | |||
} | |||
|
|||
// Skip mock contracts | |||
if strings.Contains(contractName, "_MockContract") { |
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.
Not a strong opinion but could just be open to making it mock
, case insensitive. Tradeoff in explicit vs implicit
"type": "error" | ||
}, | ||
{ | ||
"inputs": [], | ||
"name": "OnlyBridge", | ||
"name": "OnlySuperchainERC20Bridge", |
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.
We want to move away from the superchain specific naming so that this can be an ethereum wide standard in theory
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.
This error is being used in the SuperchainERC20
that is the OP implementation of ICrosschainERC20
, the neutral namings are set on that interface so that it can be used in other ethereum chains
/// @notice The SuperchainERC20Bridge allows for the bridging of ERC20 tokens to make them fungible across the | ||
/// Superchain. It builds on top of the L2ToL2CrossDomainMessenger for both replay protection and domain | ||
/// binding. | ||
contract SuperchainERC20Bridge { |
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.
Sorry for the naming nits, I know that I proposed this one, curious if you have any thoughts on the following issue: ethereum-optimism/specs#399
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.
We agree on changing the name, we notice that asset
is often used
so to be more consistent, do u prefer SuperchainTokenBridge
or SuperchainAssetBridge
?
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.
I have a slight preference for SuperchainTokenBridge
unless you think that there are non token assets?
function relayERC20(address _token, address _from, address _to, uint256 _amount) external { | ||
if (msg.sender != MESSENGER) revert CallerNotL2ToL2CrossDomainMessenger(); | ||
|
||
if (IL2ToL2CrossDomainMessenger(MESSENGER).crossDomainMessageSender() != address(this)) { |
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.
Would you find any value in adding a L2ToL2CrossDomainMessenger.context()
function that returns both the source + sender + other contextual information? I notice we do this double call thing everywhere, it could be a simplification
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.
It is a useful change, but we will be doing it in another PR to reduce the changes scope
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
import { IOptimismERC20Factory } from "./IOptimismERC20Factory.sol"; |
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 on import style, even tho eventually we should go back to relative paths so external projects can import this project without it breaking their remappings
…licts fix: crosschain merge conflicts
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## develop #12321 +/- ##
===========================================
- Coverage 64.23% 64.04% -0.19%
===========================================
Files 52 52
Lines 4353 4353
===========================================
- Hits 2796 2788 -8
- Misses 1381 1390 +9
+ Partials 176 175 -1
Flags with carried forward coverage won't be shown. Click here to find out more. |
I would like to make a security disclosure. ERC-20 standard contains a security flaw which resulted in $80,000,000 worth of tokens being lost due to lack of error handling implementation within the logic of Here is the full description: #12322 (comment) As you are about to build your technology stack on top of the ERC-20 standard your users will be affected and are guaranteed to lose funds similar to how it happened on Ethereum due to the above described issue, unless you fix it. |
Hi @Dexaran ! I'll echo what I replied on the other issue: #12322 (comment) |
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.
Just a skim of the diff with a few small comments
// Skip mock contracts | ||
if strings.Contains(contractName, "_mock") { | ||
return | ||
} |
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.
Looks like we already have MockL2ToL2CrossDomainMessenger
and this PR adds SuperchainERC20Implementation_mock
. Can we stick with the existing Mock*
precedent?
/// @notice Allows the L2StandardBridge to mint tokens. | ||
/// @param _to Address to mint tokens to. | ||
/// @param _amount Amount of tokens to mint. | ||
interface IOptimismSuperchainERC20 is ISuperchainERC20 { |
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.
What is the SuperchainERC20 interface compared to the CrosschainERC20 interface?
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.
It has specific errors of the abstract implementation SuperchainERC20
that extends ICrosschainERC20
. We extend it here so that the OptimismSuperchainERC20
has the correct ABI.
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.
Hmm I thought I heard that SuperchainERC20 was being renamed to CrosschainERC20, and therefore I'd only expect to see CrosschainERC20
throughout this PR. I may be out of the loop there though, so just want to better understand the relationship between the two
/// @notice Mint tokens through a crosschain transfer. | ||
/// @param _to Address to mint tokens to. | ||
/// @param _amount Amount of tokens to mint. | ||
function __crosschainMint(address _to, uint256 _amount) external; |
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.
What does the double underscore convention mean? The only other place I see this in the codebase (aside from the __constructor__
dummy sigs) is internal initializer methods such as __ERC721Bridge_init
, but these are not initializers
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.
It is to make it clear that are not supposed to be called by anyone else
It was proposed in this thread https://discord.com/channels/1244729134312198194/1285980446857101423/1289362724135899209
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.
Asked a follow up question to learn more in discord here
/// binding. | ||
contract SuperchainTokenBridge { | ||
/// @notice Thrown when attempting to perform an operation and the account is the zero address. | ||
error ZeroAddress(); |
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.
Consider an Errors.sol
to avoid redeclaring errors like this in each file
/// @notice Thrown when attempting to relay a message and the function caller (msg.sender) is not | ||
/// L2ToL2CrossDomainMessenger. | ||
error CallerNotL2ToL2CrossDomainMessenger(); |
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.
This looks analagous to the Unauthorized
eror we use elsewhere in the codebase. Consider using that to minimize the amount of new errors for a simpler ABI. Either the Unauthorized()
or the Unauthorized(expected, actual)
signatures that we use are ok with me
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.
We discussed this with @skeletor-spaceman, @0xng, and @gotzenx, and we believe that having explicit error messages offers more advantages than disadvantages. However, we're open to changing them if it's absolutely necessary for the PR.
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.
I don't feel strongly, I just want to be careful about exploding the amount of custom errors vs. grouping related ones and using params to get specific. For example you could even do Unauthorized(string)
to revert with Unauthorized("Caller is not L2ToL2CrossDomainMessenger")
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.
Returning a string defeats the purpose of using a custom error no? At least with regards to the bytecode size
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.
I definitely am a minimalist and prefer a minimal API but if you are very opinionated about very specific custom errors, its ok to ship
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.
Returning a string defeats the purpose of using a custom error no? At least with regards to the bytecode size
Ultimately depends on what we want to optimize for. The tradeoff is roughly:
- Bespoke errors for each case: Biggest ABI, but full rationale is part of the ABI for consumers
Unauthorized(address actual, address expected)
types of errors: Small ABI, but ABI alone doesn't tell consumer what each address semantically represents from the ABI (i.e.CallerNotL2ToL2CrossDomainMessenger
tells me I expected the L2ToL2CrossDomainMessenger, but I have to know that theexpected: 0x...
address is the L2ToL2CrossDomainMessenger addressUnauthorized(string)
: Same ABI size, more flexibility in communicating to users what went wrong, larger bytecode and gas due to string usageUnauthorized(bytes32)
: Like the prior bullet, but limited string size, so smaller/cheaper
Personally I also like smaller interfaces (for functions, errors, and events) as it means smaller surface areas (less attack surface when talking about functions), and for me that makes it easier to fit full context in my head when reasoning + less room for mistakes when choosing which to use.
Ultimately whatever we decide should be upstreamed to the Style Guide to avoid this bikeshed in the future 😅
/// @custom:semver 1.0.0-beta.7 | ||
string public constant version = "1.0.0-beta.7"; |
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.
Looks like we skipped beta.6
and went straight to 7
/// @custom:semver 1.0.0-beta.7 | |
string public constant version = "1.0.0-beta.7"; | |
/// @custom:semver 1.0.0-beta.6 | |
string public constant version = "1.0.0-beta.6"; |
* fix: refactor common errors * fix: remove unused version
…ory-merge-conflicts fix: superchain erc20 factory merge conflicts
Description
The main idea is migrating the
sendERC20
andrelayERC20
functions from theSuperchainERC20
standard to a newSuperchainERC20Bridge
. Also introducingICrosschainERC20
interface for mint/burn functions to be cross-chain neutral and extensible to other L2s.Specs:
ethereum-optimism/specs#384
ethereum-optimism/specs#413
Tests
SuperchainERC20Bridge
testsAdditional context
The
SuperchainERC20Bridge
is a new predeploy.Metadata
Closes #12322