-
Notifications
You must be signed in to change notification settings - Fork 0
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: add wind down contracts #1
Conversation
Signed-off-by: 0xRaccoon <[email protected]>
Signed-off-by: 0xRaccoon <[email protected]>
…ridge Signed-off-by: 0xRaccoon <[email protected]>
Signed-off-by: 0xRaccoon <[email protected]>
Signed-off-by: 0xRaccoon <[email protected]>
Signed-off-by: 0xRaccoon <[email protected]>
Signed-off-by: 0xRaccoon <[email protected]>
Signed-off-by: 0xRaccoon <[email protected]>
Signed-off-by: 0xRaccoon <[email protected]>
Signed-off-by: 0xRaccoon <[email protected]>
Signed-off-by: 0xRaccoon <[email protected]>
Signed-off-by: 0xRaccoon <[email protected]>
Signed-off-by: 0xRaccoon <[email protected]>
Signed-off-by: 0xRaccoon <[email protected]>
Signed-off-by: 0xRaccoon <[email protected]>
Signed-off-by: 0xRaccoon <[email protected]>
Signed-off-by: 0xRaccoon <[email protected]>
Signed-off-by: 0xRaccoon <[email protected]>
(bool success,) = _user.call{ value: _ethBalance }(""); | ||
if (!success) { | ||
revert IEthBalanceWithdrawer.EthTransferFailed(); | ||
} |
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.
They have a SafeSend
lib that they use for this
address indexed user, uint256 ethBalance, IBalanceWithdrawer.Erc20BalanceClaim[] erc20TokenBalances | ||
); | ||
|
||
string public constant version = "1.0.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.
Add natspec here:
/// @notice Semantic version.
/// @custom:semver 1.0.0-beta.1
function initialize( | ||
IL2OutputOracle _l2Oracle, | ||
ISystemConfig _systemConfig, | ||
ISuperchainConfig _superchainConfig | ||
ISuperchainConfig _superchainConfig, | ||
address _balanceClaimer |
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 about using IBalanceClaimer
directly?
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.
+1
@@ -24,6 +24,8 @@ import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol"; | |||
import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol"; | |||
import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; | |||
import { IL1Block } from "src/L2/interfaces/IL1Block.sol"; | |||
import { IEthBalanceWithdrawer } from "src/L1/interfaces/winddown/IEthBalanceWithdrawer.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.
This interface can be inherited here, the only thing to take into account is that it also has to be added to its interface also.
@@ -24,6 +28,8 @@ import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol"; | |||
/// of some token types that may not be properly supported by this contract include, but are | |||
/// not limited to: tokens with transfer fees, rebasing tokens, and tokens with blocklists. | |||
contract L1StandardBridge is StandardBridge, ISemver { |
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.
IBalanceWithdrawer
should be inherit here and in IL1StandardBridge
|
||
/// @title BalanceClaimer | ||
/// @notice Contract that allows users to claim and withdraw their balances | ||
contract BalanceClaimer is Initializable, ISemver { |
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.
Is it going to be proxied like the others contracts? Missing the natspec
/// @custom:proxied true
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.
Looking good so far sir! Well done
I put the focus mainly on the contracts logic, left suggestions mostly related to styling and some NITs.
The tests need to follow their tests naming standard, you can find it here https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/STYLE_GUIDE.md#tests :)
uint256 _ethBalance, | ||
IBalanceWithdrawer.Erc20BalanceClaim[] calldata _erc20TokenBalances | ||
) | ||
internal |
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.
Why not just doing it public and removing the external one?
internal | |
public |
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.
second this
@@ -0,0 +1,118 @@ | |||
// SPDX-License-Identifier: MIT | |||
pragma solidity 0.8.15; |
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.
New contracts are being created under 0.8.25
, is there any specific requirement for it to be 0.8.15
?
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 are going to update this from a very old commit, I preferred to use the same version than the L1StandardBridge
and OptmismPortal
contracts for consistency.
IErc20BalanceWithdrawer public erc20BalanceWithdrawer; | ||
|
||
/// @notice The mapping of users who have claimed their balances | ||
mapping(address => bool) public claimed; |
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.
If updating the compiler version, the mapping could have named args
mapping(address => bool) public claimed; | |
mapping(address _user => bool _claimed) public claimed; |
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.
since we prefer to deploy using solidity 0.8.15 this naming is not supported in this version
if (!_canClaim(_proof, _user, _ethBalance, _erc20TokenBalances)) { | ||
revert IBalanceClaimer.NoBalanceToClaim(); |
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 NIT, but I'm very much in favor of inlined if's, wdyt?
contract BalanceClaimer is Initializable, ISemver { | ||
/// @notice Emitted when a user claims their balance | ||
event BalanceClaimed( | ||
address indexed user, uint256 ethBalance, IBalanceWithdrawer.Erc20BalanceClaim[] erc20TokenBalances |
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.
Missng args natspec
} | ||
|
||
/// @dev Test that the claim function reverts when the user is invalid | ||
function test_claim_invalid_user_reverts() 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.
function test_claim_invalid_user_reverts() external { | |
function test_claim_reverts_invalidUser() external { |
} | ||
|
||
/// @dev Test that the claim function reverts when the proof is invalid | ||
function test_claim_invalid_proof_reverts() 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.
function test_claim_invalid_proof_reverts() external { | |
function test_claim_reverts_invalidProof() external { |
} | ||
|
||
/// @dev Test that the claim function reverts when the eth balance is invalid | ||
function test_claim_invalid_eth_balance_reverts() 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.
function test_claim_invalid_eth_balance_reverts() external { | |
function test_claim_reverts_invalidEthBalance() external { |
} | ||
|
||
/// @dev Test that the claim function reverts when the erc20 balance is invalid | ||
function test_claim_invalid_erc20_balance_reverts() 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.
function test_claim_invalid_erc20_balance_reverts() external { | |
function test_claim_reverts_erc20BalanceReverts() external { |
|
||
/// @notice Address of the SuperchainConfig contract. | ||
ISuperchainConfig public superchainConfig; | ||
|
||
/// @notice Address of the SystemConfig contract. | ||
ISystemConfig public systemConfig; | ||
|
||
address public balanceClaimer; |
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.
Missing natspec
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.
also storing it casted to IBalanceWithdrawer
for neatness :)
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.
+1 to IBalanceWithdrawer
bytes32[] calldata _proof, | ||
address _user, | ||
uint256 _ethBalance, | ||
IBalanceWithdrawer.Erc20BalanceClaim[] calldata _erc20TokenBalances |
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.
as mentioned by @0xDiscotech on L1StandardBridge
, i'd rename this argument to _erc20TokenClaim
if (claimed[_user]) return false; | ||
bytes32 _leaf = keccak256(bytes.concat(keccak256(abi.encode(_user, _ethBalance, _erc20TokenBalances)))); | ||
_canClaimTokens = MerkleProof.verify(_proof, root, _leaf); | ||
} |
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.
is there a chance someone may need two claims to fully withdraw their balances? if so, the claimed
check wouldn't allow a second claim.
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.
no, the claim should be just one per account, the merkle tree should include all the tokens and eth information for the user to claim
|
||
function balanceClaimer() external view returns (address); |
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.
missing natspec
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.
will add the natspec in the contract since it seems to be the practice used in this repo
@@ -33,6 +33,7 @@ import { IL1CrossDomainMessenger } from "src/L1/interfaces/IL1CrossDomainMesseng | |||
import { IL1ERC721Bridge } from "src/L1/interfaces/IL1ERC721Bridge.sol"; | |||
import { IL1StandardBridge } from "src/L1/interfaces/IL1StandardBridge.sol"; | |||
import { IOptimismMintableERC20Factory } from "src/universal/interfaces/IOptimismMintableERC20Factory.sol"; | |||
import { IBalanceClaimer } from "src/L1/interfaces/winddown/IBalanceClaimer.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.
the BalanceClaimer
and BalanceWithdrawer
interfaces are really confusing
address public balanceClaimer; | ||
|
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.
- missing natspec
- i'd store the address casted to an interface like the rest of contracts for neatness
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.
+1
returns (bool _canClaimTokens) | ||
{ | ||
if (claimed[_user]) return false; | ||
bytes32 _leaf = keccak256(bytes.concat(keccak256(abi.encode(_user, _ethBalance, _erc20TokenBalances)))); |
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.
do we have an example merkle tree / data created via the offchain script to test?
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 we tested with an example, the plan is to test all the leaves with a script
PR moved to: #3 |
The purpose is to allow users to claim their balances of
eth
andERC20
tokens with a prior snapshot of their balances.Currently, the assets to be claimed by the users are located in 2 contracts in
mainnet
:A snapshot of the users'
eth
balance ofOptimismPortal
and snapshot of the users'ERC20
balances ofL1StandardBridge
will be taken and the Merkle tree, root, and proofs for users will be generated off-chain.The approach consists of a contract
BalanceClaimer
that contains thebytes32
merkle root value, all the Merkle verification logic, and claims methods. To achieve this approach, it is be necessary to updateL1StandardBridge
and theOptimisimPotal
contracts and add the following methods:withdrawErc20Balance
only called byBalanceClaimer
contract after claim verification to send the user token balances.withdrawEthBalance
only called byBalanceClaimer
contract after claim verification to send the usereth
balance.The
claim
method is permissionless and can be called by any address.