-
Notifications
You must be signed in to change notification settings - Fork 8
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
Support ETH withdrawal and deposit with custom gas fee token #198
Support ETH withdrawal and deposit with custom gas fee token #198
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
❗ Your organization needs to install the Codecov GitHub app to enable full functionality. Additional details and impacted files@@ Coverage Diff @@
## block-custom-token-from-l1standardbridge #198 +/- ##
============================================================================
- Coverage 42.72% 40.13% -2.60%
============================================================================
Files 38 75 +37
Lines 4002 5183 +1181
Branches 621 826 +205
============================================================================
+ Hits 1710 2080 +370
- Misses 2185 2996 +811
Partials 107 107
Flags with carried forward coverage won't be shown. Click here to find out more.
|
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.
Overall LGTM, I like that the diff is much smaller vs the first attempt. Still a few comments if you could reply.
/// @param _from Address of the sender. | ||
/// @param _target Address of the receiver. | ||
/// @param _amount Amount of the token sent. | ||
function _initiateBridgeETHERC20( |
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 am not a solidity developer, but it feels a bit wrong to me that this function should only ever be invoked with the L1 Eth's corresponding L2 ERC20 token address as local token, and the zero address as remote token.
Maybe it's more idiomatic to leave it as written, but if we know the required call parameters, why even include them as parameters to this function?
Minimally, could we note in the doc what the required values for these parameters are, or perhaps check them explicitly?
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 can hardcode the _remoteToken
. For the _localToken
address, it can be any ERC20 token addresses on L2.
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.
Maybe this is my misunderstanding. When is this function intended to be called? I thought it was only invoked when the L2 gas token is not the L1 native gas token, and the token being transferred was the wrapped version of the L1 native ETH? Is that not the case?
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.
Yes, the wrapped version of the L1 native ETH can be any addresses on L2, so we don't know the _localToken
address. We can read this address from the L1Block
contract.
@@ -332,7 +333,7 @@ contract SystemDictator is OwnableUpgradeable { | |||
(bool success,) = address(config.implementationAddressConfig.addressDeprecatorImpl).delegatecall( | |||
abi.encodeWithSelector(bytes4(keccak256("deprecateAddresses()"))) | |||
); | |||
require(success, "Reverted: Error deprecating addresses"); |
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 haven't looked at the blame, but it's unclear to me why these messages are changing? There are a few other similar instances as well.
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 simplified the error message to reduce the contract 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.
Are you concerned about this generating merge conflicts? Was the contract size becoming problematic?
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.
Yes, this can be the problem. Once we finish the migration, this contract can be removed.
if (token != Constants.ETHER && msg.value != 0 && l2ETHToken == address(0)) revert NoValue(); | ||
if (token != Constants.ETHER && msg.value != 0 && l2ETHToken != address(0)) { | ||
require( |
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 can combine the initial check for token != Constants.ETHER
and msg.value != 0
into a single condition.
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 sure how to make changes. Could you please clarify 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.
LGTM!
packages/contracts-bedrock/src/universal/CrossDomainMessenger.sol
Outdated
Show resolved
Hide resolved
@@ -385,7 +394,7 @@ contract OptimismPortal is Initializable, ResourceMetering, ISemver { | |||
|
|||
// Only transfer value when a non zero value is specified. This saves gas in the case of | |||
// using the standard bridge or arbitrary message passing. | |||
if (_tx.value != 0) { | |||
if (_tx.value != 0 && l2Sender != Predeploys.L2_STANDARD_BRIDGE) { |
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.
so ETHERC20 and other ERC20 withdrawals have l2Sender set as L2_STANDARD_BRIDGE
and Boba withdrawals have l2Sender != L2_STANDARD_BRIDGE (directly triggered on L2toL1MessagePasser and thats the only way)?
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.
Yes. There are three cases:
- Withdrawal BOBA
Users can only trigger this action in L2ToL1Messenger. The l2Sender is the msg.sender (user wallet address) - Withdrawal L1 native token
Users can only trigger this action in L2StandardBridge. The L2StandardBridge calls L2ToL1Messenger and the l2Sender is L2StandardBridge - Withdrawal other ERC20 tokens
Users can only trigger this action in L2StandardBridge. The L2StandardBridge calls L2CrossDomainMessenger and L2CrossDomainMessenger calls L2ToL1Messenger. Te l2Sender is L2CrossDomainMessenger.
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.
thats great! If we could record these somewhere or on internal specs, would be great for us and future audit.
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.
Yes, I will write up a documentation.
@@ -1016,7 +1016,8 @@ contract Deploy is Deployer { | |||
disputeGameFactory: mustGetAddress("DisputeGameFactoryProxy"), | |||
optimismPortal: mustGetAddress("OptimismPortalProxy"), | |||
optimismMintableERC20Factory: mustGetAddress("OptimismMintableERC20FactoryProxy"), | |||
gasPayingToken: customGasTokenAddress | |||
gasPayingToken: customGasTokenAddress, | |||
l2ETHToken: address(0) |
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 see we are going with l2ETHToken = addr(0) for the tests. So the two possible values of l2ETHToken are either addr(0) for Boba-ETH and L2BNB for Boba-BNB right?
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.
Another unit tests are added. For the local deployment we assume that this l2ETHToken is disabled.
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 modified the deployment script, so devs can configure it.
c09aef0
into
block-custom-token-from-l1standardbridge
📋 Add associated issues, tickets, docs URL here.
Overview
Describe what your Pull Request is about in a few sentences.
Enable ETH deposit and withdrawal when the custom gas fee token is enabled
Changes
Describe your changes and implementation choices. More details make PRs easier to review.
I added a function called
l2ETHToken
in the Op stack just like thegasPayingToken
function. Thisl2ETHToken
function is to record the l2 ETH ERC20 contract address. Both L1 and L2 can call smart contracts to retrieve this address.Users call
OptimismPortal.depositTransaction()
or send ETH toOptimismPortal
. The OptimismPortal calls theL1CrossChainMessenger
to build the cross chain message and emit it in the event. The L2 will apply the message toL2StandardBridge
.Users call
L2StandardBridge
to withdraw it.L2StandardBridge
directly callsL2ToL1Messenger
to build the cross chain message and emit it in the event. On L1, we send the ETH if the_tx.sender
isL2StandardBridge
.Testing
Describe how to test your new feature/bug fix and if possible, a step by step guide on how to demo this.
The integration tests are added