Commit 865c5167 authored by dapperscene6's avatar dapperscene6

contracts-bedrock: add withdrawal network and make withdrawal minimum configurable

parent 75c00a50
...@@ -13,7 +13,7 @@ OP Stack configuration is an active work in progress and will likely evolve sign ...@@ -13,7 +13,7 @@ OP Stack configuration is an active work in progress and will likely evolve sign
## New Blockchain Configuration ## New Blockchain Configuration
New OP Stack blockchains are currently configured with a JSON file inside the Optimism repository. The file is `<optimism repository>/packages/contracts-bedrock/deploy-config/<chain name>.json`. For example, [this is the configuration file for the tutorial blockchain](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/deploy-config/getting-started.json). New OP Stack blockchains are currently configured with a JSON file inside the Optimism repository. The file is `<optimism repository>/packages/contracts-bedrock/deploy-config/<chain name>.json`. For example, [this is the configuration file for the tutorial blockchain](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/deploy-config/getting-started.json).
### Admin accounts ### Admin accounts
...@@ -29,10 +29,25 @@ New OP Stack blockchains are currently configured with a JSON file inside the Op ...@@ -29,10 +29,25 @@ New OP Stack blockchains are currently configured with a JSON file inside the Op
| Key | Type | Description | Default value | | Key | Type | Description | Default value |
| --- | --- | --- | --- | | --- | --- | --- | --- |
| `baseFeeVaultRecipient` | L1 Address | L1 address that the base fees from all transactions on the L2 can be withdrawn to. | It is recommended to have a single admin account to retain a common security model. | | `baseFeeVaultRecipient` | L1 or L2 Address | Address that the base fees from all transactions on the L2 can be withdrawn to. | It is recommended to have a single admin account to retain a common security model. |
| `l1FeeVaultRecipient` | L1 Address | L1 address that the L1 data fees from all transactions on the L2 can be withdrawn to. | It is recommended to have a single admin account to retain a common security model. | | `l1FeeVaultRecipient` | L1 or L2 Address | Address that the L1 data fees from all transactions on the L2 can be withdrawn to. | It is recommended to have a single admin account to retain a common security model. |
| `sequencerFeeVaultRecipient` | L1 Address | L1 address that the tip fees from all transactions on the L2 can be withdrawn to. | It is recommended to have a single admin account to retain a common security model. | | `sequencerFeeVaultRecipient` | L1 or L2 Address | Address that the tip fees from all transactions on the L2 can be withdrawn to. | It is recommended to have a single admin account to retain a common security model. |
### Minimum Fee Withdrawal Amounts
| Key | Type | Description | Default value |
| --- | --- | --- | --- |
| `baseFeeVaultMinimumWithdrawalAmount` | Number in wei | The minimum amount of funds the `BaseFeeVault` contract must have for a fee withdrawal. | 10 ether |
| `l1FeeVaultMinimumWithdrawalAmount` | Number in wei | The minimum amount of funds the `L1FeeVault` contract must have for a fee withdrawal. | 10 ether |
| `sequencerFeeVaultWithdrawalAmount` | Number in wei | The minimum amount of funds the `SequencerFeeVault` contract must have for a fee withdrawal. | 10 ether |
### Withdrawal Network
| Key | Type | Description | Default value |
| --- | --- | --- | --- |
| `baseFeeVaultWithdrawalNetwork` | Number representing network enum | A value of `0` will withdraw funds to the recient address on L1 and a value of `1` will withdraw funds to the recient address on L2. |
| `l1FeeVaultWithdrawalNetwork` | Number representing network enum | A value of `0` will withdraw funds to the recient address on L1 and a value of `1` will withdraw funds to the recient address on L2. |
| `sequencerFeeVaultWithdrawalNetwork` | Number representing network enum | A value of `0` will withdraw funds to the recient address on L1 and a value of `1` will withdraw funds to the recient address on L2. |
### Misc. ### Misc.
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -13,7 +13,7 @@ const SequencerFeeVaultStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"cont ...@@ -13,7 +13,7 @@ const SequencerFeeVaultStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"cont
var SequencerFeeVaultStorageLayout = new(solc.StorageLayout) var SequencerFeeVaultStorageLayout = new(solc.StorageLayout)
var SequencerFeeVaultDeployedBin = "0x6080604052600436106100695760003560e01c806384411d651161004357806384411d651461010c578063d3e5792b14610130578063d4ff92181461016457600080fd5b80630d9019e1146100755780633ccfd60b146100d357806354fd4d50146100ea57600080fd5b3661007057005b600080fd5b34801561008157600080fd5b506100a97f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156100df57600080fd5b506100e8610197565b005b3480156100f657600080fd5b506100ff6103b8565b6040516100ca9190610612565b34801561011857600080fd5b5061012260005481565b6040519081526020016100ca565b34801561013c57600080fd5b506101227f000000000000000000000000000000000000000000000000000000000000000081565b34801561017057600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006100a9565b7f0000000000000000000000000000000000000000000000000000000000000000471015610271576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f4665655661756c743a207769746864726177616c20616d6f756e74206d75737460448201527f2062652067726561746572207468616e206d696e696d756d207769746864726160648201527f77616c20616d6f756e7400000000000000000000000000000000000000000000608482015260a40160405180910390fd5b600047905080600080828254610287919061065b565b9091555050604080518281527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166020820152338183015290517fc8a211cc64b6ed1b50595a9fcb1932b6d1e5a6e8ef15b60e5b1f988ea9086bba9181900360600190a1604080516020810182526000815290517fe11013dd0000000000000000000000000000000000000000000000000000000081527342000000000000000000000000000000000000109163e11013dd918491610383917f0000000000000000000000000000000000000000000000000000000000000000916188b891600401610673565b6000604051808303818588803b15801561039c57600080fd5b505af11580156103b0573d6000803e3d6000fd5b505050505050565b60606103e37f000000000000000000000000000000000000000000000000000000000000000061045b565b61040c7f000000000000000000000000000000000000000000000000000000000000000061045b565b6104357f000000000000000000000000000000000000000000000000000000000000000061045b565b604051602001610447939291906106b7565b604051602081830303815290604052905090565b60608160000361049e57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156104c857806104b28161072d565b91506104c19050600a83610794565b91506104a2565b60008167ffffffffffffffff8111156104e3576104e36107a8565b6040519080825280601f01601f19166020018201604052801561050d576020820181803683370190505b5090505b8415610590576105226001836107d7565b915061052f600a866107ee565b61053a90603061065b565b60f81b81838151811061054f5761054f610802565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610589600a86610794565b9450610511565b949350505050565b60005b838110156105b357818101518382015260200161059b565b838111156105c2576000848401525b50505050565b600081518084526105e0816020860160208601610598565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061062560208301846105c8565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561066e5761066e61062c565b500190565b73ffffffffffffffffffffffffffffffffffffffff8416815263ffffffff831660208201526060604082015260006106ae60608301846105c8565b95945050505050565b600084516106c9818460208901610598565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551610705816001850160208a01610598565b60019201918201528351610720816002840160208801610598565b0160020195945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361075e5761075e61062c565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826107a3576107a3610765565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000828210156107e9576107e961062c565b500390565b6000826107fd576107fd610765565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000a" var SequencerFeeVaultDeployedBin = "0x6080604052600436106100745760003560e01c806384411d651161004e57806384411d6514610117578063d0e12f901461013b578063d3e5792b1461017c578063d4ff9218146101b057600080fd5b80630d9019e1146100805780633ccfd60b146100de57806354fd4d50146100f557600080fd5b3661007b57005b600080fd5b34801561008c57600080fd5b506100b47f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156100ea57600080fd5b506100f36101e3565b005b34801561010157600080fd5b5061010a610486565b6040516100d591906106fa565b34801561012357600080fd5b5061012d60005481565b6040519081526020016100d5565b34801561014757600080fd5b5061016f7f000000000000000000000000000000000000000000000000000000000000000081565b6040516100d5919061077e565b34801561018857600080fd5b5061012d7f000000000000000000000000000000000000000000000000000000000000000081565b3480156101bc57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006100b4565b7f00000000000000000000000000000000000000000000000000000000000000004710156102bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f4665655661756c743a207769746864726177616c20616d6f756e74206d75737460448201527f2062652067726561746572207468616e206d696e696d756d207769746864726160648201527f77616c20616d6f756e7400000000000000000000000000000000000000000000608482015260a40160405180910390fd5b6000479050806000808282546102d391906107c1565b90915550506040517f38e04cbeb8c10f8f568618aa75be0f10b6729b8b4237743b4de20cbcde2839ee9061034e9083907f00000000000000000000000000000000000000000000000000000000000000009033907f0000000000000000000000000000000000000000000000000000000000000000906107d9565b60405180910390a160017f0000000000000000000000000000000000000000000000000000000000000000600181111561038a5761038a610714565b036103ce576103ca7f00000000000000000000000000000000000000000000000000000000000000005a8360405180602001604052806000815250610529565b5050565b604080516020810182526000815290517fe11013dd0000000000000000000000000000000000000000000000000000000081527342000000000000000000000000000000000000109163e11013dd918491610451917f0000000000000000000000000000000000000000000000000000000000000000916188b89160040161081a565b6000604051808303818588803b15801561046a57600080fd5b505af115801561047e573d6000803e3d6000fd5b505050505050565b60606104b17f0000000000000000000000000000000000000000000000000000000000000000610543565b6104da7f0000000000000000000000000000000000000000000000000000000000000000610543565b6105037f0000000000000000000000000000000000000000000000000000000000000000610543565b60405160200161051593929190610855565b604051602081830303815290604052905090565b600080600080845160208601878a8af19695505050505050565b60608160000361058657505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156105b0578061059a816108cb565b91506105a99050600a83610932565b915061058a565b60008167ffffffffffffffff8111156105cb576105cb610946565b6040519080825280601f01601f1916602001820160405280156105f5576020820181803683370190505b5090505b84156106785761060a600183610975565b9150610617600a8661098c565b6106229060306107c1565b60f81b818381518110610637576106376109a0565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610671600a86610932565b94506105f9565b949350505050565b60005b8381101561069b578181015183820152602001610683565b838111156106aa576000848401525b50505050565b600081518084526106c8816020860160208601610680565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061070d60208301846106b0565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6002811061077a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b6020810161078c8284610743565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156107d4576107d4610792565b500190565b84815273ffffffffffffffffffffffffffffffffffffffff848116602083015283166040820152608081016108116060830184610743565b95945050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815263ffffffff8316602082015260606040820152600061081160608301846106b0565b60008451610867818460208901610680565b80830190507f2e0000000000000000000000000000000000000000000000000000000000000080825285516108a3816001850160208a01610680565b600192019182015283516108be816002840160208801610680565b0160020195945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036108fc576108fc610792565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261094157610941610903565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60008282101561098757610987610792565b500390565b60008261099b5761099b610903565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000a"
func init() { func init() {
if err := json.Unmarshal([]byte(SequencerFeeVaultStorageLayoutJSON), SequencerFeeVaultStorageLayout); err != nil { if err := json.Unmarshal([]byte(SequencerFeeVaultStorageLayoutJSON), SequencerFeeVaultStorageLayout); err != nil {
......
...@@ -84,6 +84,18 @@ type DeployConfig struct { ...@@ -84,6 +84,18 @@ type DeployConfig struct {
L1FeeVaultRecipient common.Address `json:"l1FeeVaultRecipient"` L1FeeVaultRecipient common.Address `json:"l1FeeVaultRecipient"`
// L1 recipient of fees accumulated in the SequencerFeeVault // L1 recipient of fees accumulated in the SequencerFeeVault
SequencerFeeVaultRecipient common.Address `json:"sequencerFeeVaultRecipient"` SequencerFeeVaultRecipient common.Address `json:"sequencerFeeVaultRecipient"`
// Minimum withdrawal amount for the BaseFeeVault
BaseFeeVaultMinimumWithdrawalAmount *hexutil.Big `json:"baseFeeVaultMinimumWithdrawalAmount"`
// Minimum withdrawal amount for the L1FeeVault
L1FeeVaultMinimumWithdrawalAmount *hexutil.Big `json:"l1FeeVaultMinimumWithdrawalAmount"`
// Minimum withdrawal amount for the SequencerFeeVault
SequencerFeeVaultMinimumWithdrawalAmount *hexutil.Big `json:"sequencerFeeVaultMinimumWithdrawalAmount"`
// Withdrawal network for the BaseFeeVault
BaseFeeVaultWithdrawalNetwork uint8 `json:"baseFeeVaultWithdrawalNetwork"`
// Withdrawal network for the L1FeeVault
L1FeeVaultWithdrawalNetwork uint8 `json:"l1FeeVaultWithdrawalNetwork"`
// Withdrawal network for the SequencerFeeVault
SequencerFeeVaultWithdrawalNetwork uint8 `json:"sequencerFeeVaultWithdrawalNetwork"`
// L1StandardBridge proxy address on L1 // L1StandardBridge proxy address on L1
L1StandardBridgeProxy common.Address `json:"l1StandardBridgeProxy"` L1StandardBridgeProxy common.Address `json:"l1StandardBridgeProxy"`
// L1CrossDomainMessenger proxy address on L1 // L1CrossDomainMessenger proxy address on L1
...@@ -178,6 +190,15 @@ func (d *DeployConfig) Check() error { ...@@ -178,6 +190,15 @@ func (d *DeployConfig) Check() error {
if d.SequencerFeeVaultRecipient == (common.Address{}) { if d.SequencerFeeVaultRecipient == (common.Address{}) {
return fmt.Errorf("%w: SequencerFeeVaultRecipient cannot be address(0)", ErrInvalidDeployConfig) return fmt.Errorf("%w: SequencerFeeVaultRecipient cannot be address(0)", ErrInvalidDeployConfig)
} }
if d.BaseFeeVaultWithdrawalNetwork >= 2 {
return fmt.Errorf("%w: BaseFeeVaultWithdrawalNetwork can only be 0 (L1) or 1 (L2)", ErrInvalidDeployConfig)
}
if d.L1FeeVaultWithdrawalNetwork >= 2 {
return fmt.Errorf("%w: L1FeeVaultWithdrawalNetwork can only be 0 (L1) or 1 (L2)", ErrInvalidDeployConfig)
}
if d.SequencerFeeVaultWithdrawalNetwork >= 2 {
return fmt.Errorf("%w: SequencerFeeVaultWithdrawalNetwork can only be 0 (L1) or 1 (L2)", ErrInvalidDeployConfig)
}
if d.GasPriceOracleOverhead == 0 { if d.GasPriceOracleOverhead == 0 {
log.Warn("GasPriceOracleOverhead is 0") log.Warn("GasPriceOracleOverhead is 0")
} }
...@@ -410,13 +431,19 @@ func NewL2ImmutableConfig(config *DeployConfig, block *types.Block) (immutables. ...@@ -410,13 +431,19 @@ func NewL2ImmutableConfig(config *DeployConfig, block *types.Block) (immutables.
"remoteChainId": new(big.Int).SetUint64(config.L1ChainID), "remoteChainId": new(big.Int).SetUint64(config.L1ChainID),
} }
immutable["SequencerFeeVault"] = immutables.ImmutableValues{ immutable["SequencerFeeVault"] = immutables.ImmutableValues{
"recipient": config.SequencerFeeVaultRecipient, "recipient": config.SequencerFeeVaultRecipient,
"minimumWithdrawalAmount": config.SequencerFeeVaultMinimumWithdrawalAmount,
"withdrawalNetwork": config.SequencerFeeVaultWithdrawalNetwork,
} }
immutable["L1FeeVault"] = immutables.ImmutableValues{ immutable["L1FeeVault"] = immutables.ImmutableValues{
"recipient": config.L1FeeVaultRecipient, "recipient": config.L1FeeVaultRecipient,
"minimumWithdrawalAmount": config.L1FeeVaultMinimumWithdrawalAmount,
"withdrawalNetwork": config.L1FeeVaultWithdrawalNetwork,
} }
immutable["BaseFeeVault"] = immutables.ImmutableValues{ immutable["BaseFeeVault"] = immutables.ImmutableValues{
"recipient": config.BaseFeeVaultRecipient, "recipient": config.BaseFeeVaultRecipient,
"minimumWithdrawalAmount": config.BaseFeeVaultMinimumWithdrawalAmount,
"withdrawalNetwork": config.BaseFeeVaultWithdrawalNetwork,
} }
return immutable, nil return immutable, nil
......
...@@ -22,6 +22,14 @@ ...@@ -22,6 +22,14 @@
"baseFeeVaultRecipient": "0xBcd4042DE499D14e55001CcbB24a551F3b954096", "baseFeeVaultRecipient": "0xBcd4042DE499D14e55001CcbB24a551F3b954096",
"l1FeeVaultRecipient": "0x71bE63f3384f5fb98995898A86B02Fb2426c5788", "l1FeeVaultRecipient": "0x71bE63f3384f5fb98995898A86B02Fb2426c5788",
"sequencerFeeVaultRecipient": "0x71bE63f3384f5fb98995898A86B02Fb2426c5788", "sequencerFeeVaultRecipient": "0x71bE63f3384f5fb98995898A86B02Fb2426c5788",
"baseFeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000",
"l1FeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000",
"sequencerFeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000",
"baseFeeVaultWithdrawalNetwork": 0,
"l1FeeVaultWithdrawalNetwork": 0,
"sequencerFeeVaultWithdrawalNetwork": 0,
"l1ERC721BridgeProxy": "0xff000000000000000000000000000000000000ff", "l1ERC721BridgeProxy": "0xff000000000000000000000000000000000000ff",
"l1StandardBridgeProxy": "0xff000000000000000000000000000000000000fd", "l1StandardBridgeProxy": "0xff000000000000000000000000000000000000fd",
"l1CrossDomainMessengerProxy": "0xff000000000000000000000000000000000000dd", "l1CrossDomainMessengerProxy": "0xff000000000000000000000000000000000000dd",
......
...@@ -39,6 +39,12 @@ ...@@ -39,6 +39,12 @@
"baseFeeVaultRecipient": "0x42000000000000000000000000000000000000f5", "baseFeeVaultRecipient": "0x42000000000000000000000000000000000000f5",
"l1FeeVaultRecipient": "0x42000000000000000000000000000000000000f6", "l1FeeVaultRecipient": "0x42000000000000000000000000000000000000f6",
"sequencerFeeVaultRecipient": "0x42000000000000000000000000000000000000f7", "sequencerFeeVaultRecipient": "0x42000000000000000000000000000000000000f7",
"baseFeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000",
"l1FeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000",
"sequencerFeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000",
"baseFeeVaultWithdrawalNetwork": 0,
"l1FeeVaultWithdrawalNetwork": 0,
"sequencerFeeVaultWithdrawalNetwork": 0,
"l1StandardBridgeProxy": "0x42000000000000000000000000000000000000f8", "l1StandardBridgeProxy": "0x42000000000000000000000000000000000000f8",
"l1CrossDomainMessengerProxy": "0x42000000000000000000000000000000000000f9", "l1CrossDomainMessengerProxy": "0x42000000000000000000000000000000000000f9",
"l1ERC721BridgeProxy": "0x4200000000000000000000000000000000000060", "l1ERC721BridgeProxy": "0x4200000000000000000000000000000000000060",
......
...@@ -95,18 +95,24 @@ func BuildOptimism(immutable ImmutableConfig) (DeploymentResults, error) { ...@@ -95,18 +95,24 @@ func BuildOptimism(immutable ImmutableConfig) (DeploymentResults, error) {
Name: "SequencerFeeVault", Name: "SequencerFeeVault",
Args: []interface{}{ Args: []interface{}{
immutable["SequencerFeeVault"]["recipient"], immutable["SequencerFeeVault"]["recipient"],
immutable["SequencerFeeVault"]["minimumWithdrawalAmount"],
immutable["SequencerFeeVault"]["withdrawalNetwork"],
}, },
}, },
{ {
Name: "BaseFeeVault", Name: "BaseFeeVault",
Args: []interface{}{ Args: []interface{}{
immutable["BaseFeeVault"]["recipient"], immutable["BaseFeeVault"]["recipient"],
immutable["BaseFeeVault"]["minimumWithdrawalAmount"],
immutable["BaseFeeVault"]["withdrawalNetwork"],
}, },
}, },
{ {
Name: "L1FeeVault", Name: "L1FeeVault",
Args: []interface{}{ Args: []interface{}{
immutable["L1FeeVault"]["recipient"], immutable["L1FeeVault"]["recipient"],
immutable["L1FeeVault"]["minimumWithdrawalAmount"],
immutable["L1FeeVault"]["withdrawalNetwork"],
}, },
}, },
{ {
...@@ -159,6 +165,9 @@ func BuildL2(constructors []deployer.Constructor) (DeploymentResults, error) { ...@@ -159,6 +165,9 @@ func BuildL2(constructors []deployer.Constructor) (DeploymentResults, error) {
func l2Deployer(backend *backends.SimulatedBackend, opts *bind.TransactOpts, deployment deployer.Constructor) (*types.Transaction, error) { func l2Deployer(backend *backends.SimulatedBackend, opts *bind.TransactOpts, deployment deployer.Constructor) (*types.Transaction, error) {
var tx *types.Transaction var tx *types.Transaction
var recipient common.Address
var minimumWithdrawalAmount *big.Int
var withdrawalNetwork uint8
var err error var err error
switch deployment.Name { switch deployment.Name {
case "GasPriceOracle": case "GasPriceOracle":
...@@ -182,23 +191,23 @@ func l2Deployer(backend *backends.SimulatedBackend, opts *bind.TransactOpts, dep ...@@ -182,23 +191,23 @@ func l2Deployer(backend *backends.SimulatedBackend, opts *bind.TransactOpts, dep
// No arguments required for L2ToL1MessagePasser // No arguments required for L2ToL1MessagePasser
_, tx, _, err = bindings.DeployL2ToL1MessagePasser(opts, backend) _, tx, _, err = bindings.DeployL2ToL1MessagePasser(opts, backend)
case "SequencerFeeVault": case "SequencerFeeVault":
recipient, ok := deployment.Args[0].(common.Address) recipient, minimumWithdrawalAmount, withdrawalNetwork, err = prepareFeeVaultArguments(deployment)
if !ok { if err != nil {
return nil, fmt.Errorf("invalid type for recipient") return nil, err
} }
_, tx, _, err = bindings.DeploySequencerFeeVault(opts, backend, recipient) _, tx, _, err = bindings.DeploySequencerFeeVault(opts, backend, recipient, minimumWithdrawalAmount, withdrawalNetwork)
case "BaseFeeVault": case "BaseFeeVault":
recipient, ok := deployment.Args[0].(common.Address) recipient, minimumWithdrawalAmount, withdrawalNetwork, err = prepareFeeVaultArguments(deployment)
if !ok { if err != nil {
return nil, fmt.Errorf("invalid type for recipient") return nil, err
} }
_, tx, _, err = bindings.DeployBaseFeeVault(opts, backend, recipient) _, tx, _, err = bindings.DeployBaseFeeVault(opts, backend, recipient, minimumWithdrawalAmount, withdrawalNetwork)
case "L1FeeVault": case "L1FeeVault":
recipient, ok := deployment.Args[0].(common.Address) recipient, minimumWithdrawalAmount, withdrawalNetwork, err = prepareFeeVaultArguments(deployment)
if !ok { if err != nil {
return nil, fmt.Errorf("invalid type for recipient") return nil, err
} }
_, tx, _, err = bindings.DeployL1FeeVault(opts, backend, recipient) _, tx, _, err = bindings.DeployL1FeeVault(opts, backend, recipient, minimumWithdrawalAmount, withdrawalNetwork)
case "OptimismMintableERC20Factory": case "OptimismMintableERC20Factory":
_, tx, _, err = bindings.DeployOptimismMintableERC20Factory(opts, backend, predeploys.L2StandardBridgeAddr) _, tx, _, err = bindings.DeployOptimismMintableERC20Factory(opts, backend, predeploys.L2StandardBridgeAddr)
case "DeployerWhitelist": case "DeployerWhitelist":
...@@ -236,3 +245,19 @@ func l2Deployer(backend *backends.SimulatedBackend, opts *bind.TransactOpts, dep ...@@ -236,3 +245,19 @@ func l2Deployer(backend *backends.SimulatedBackend, opts *bind.TransactOpts, dep
return tx, err return tx, err
} }
func prepareFeeVaultArguments(deployment deployer.Constructor) (common.Address, *big.Int, uint8, error) {
recipient, ok := deployment.Args[0].(common.Address)
if !ok {
return common.Address{}, nil, 0, fmt.Errorf("invalid type for recipient")
}
minimumWithdrawalAmountHex, ok := deployment.Args[1].(*hexutil.Big)
if !ok {
return common.Address{}, nil, 0, fmt.Errorf("invalid type for minimumWithdrawalAmount")
}
withdrawalNetwork, ok := deployment.Args[2].(uint8)
if !ok {
return common.Address{}, nil, 0, fmt.Errorf("invalid type for withdrawalNetwork")
}
return recipient, minimumWithdrawalAmountHex.ToInt(), withdrawalNetwork, nil
}
...@@ -6,10 +6,13 @@ import ( ...@@ -6,10 +6,13 @@ import (
"github.com/ethereum-optimism/optimism/op-chain-ops/immutables" "github.com/ethereum-optimism/optimism/op-chain-ops/immutables"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func TestBuildOptimism(t *testing.T) { func TestBuildOptimism(t *testing.T) {
minimumWithdrawalAmountBig, _ := big.NewInt(0).SetString("8ac7230489e80000", 16)
minimumWithdrawalAmount := (*hexutil.Big)(minimumWithdrawalAmountBig)
results, err := immutables.BuildOptimism(immutables.ImmutableConfig{ results, err := immutables.BuildOptimism(immutables.ImmutableConfig{
"L2StandardBridge": { "L2StandardBridge": {
"otherBridge": common.HexToAddress("0x1234567890123456789012345678901234567890"), "otherBridge": common.HexToAddress("0x1234567890123456789012345678901234567890"),
...@@ -26,13 +29,19 @@ func TestBuildOptimism(t *testing.T) { ...@@ -26,13 +29,19 @@ func TestBuildOptimism(t *testing.T) {
"bridge": common.HexToAddress("0x1234567890123456789012345678901234567890"), "bridge": common.HexToAddress("0x1234567890123456789012345678901234567890"),
}, },
"SequencerFeeVault": { "SequencerFeeVault": {
"recipient": common.HexToAddress("0x1234567890123456789012345678901234567890"), "recipient": common.HexToAddress("0x1234567890123456789012345678901234567890"),
"minimumWithdrawalAmount": minimumWithdrawalAmount,
"withdrawalNetwork": uint8(0),
}, },
"L1FeeVault": { "L1FeeVault": {
"recipient": common.HexToAddress("0x1234567890123456789012345678901234567890"), "recipient": common.HexToAddress("0x1234567890123456789012345678901234567890"),
"minimumWithdrawalAmount": minimumWithdrawalAmount,
"withdrawalNetwork": uint8(0),
}, },
"BaseFeeVault": { "BaseFeeVault": {
"recipient": common.HexToAddress("0x1234567890123456789012345678901234567890"), "recipient": common.HexToAddress("0x1234567890123456789012345678901234567890"),
"minimumWithdrawalAmount": minimumWithdrawalAmount,
"withdrawalNetwork": uint8(0),
}, },
}) })
require.Nil(t, err) require.Nil(t, err)
......
...@@ -102,9 +102,15 @@ func MakeDeployParams(t require.TestingT, tp *TestParams) *DeployParams { ...@@ -102,9 +102,15 @@ func MakeDeployParams(t require.TestingT, tp *TestParams) *DeployParams {
GasPriceOracleScalar: 1000_000, GasPriceOracleScalar: 1000_000,
DeploymentWaitConfirmations: 1, DeploymentWaitConfirmations: 1,
SequencerFeeVaultRecipient: common.Address{19: 1}, SequencerFeeVaultRecipient: common.Address{19: 1},
BaseFeeVaultRecipient: common.Address{19: 2}, BaseFeeVaultRecipient: common.Address{19: 2},
L1FeeVaultRecipient: common.Address{19: 3}, L1FeeVaultRecipient: common.Address{19: 3},
BaseFeeVaultMinimumWithdrawalAmount: uint64ToBig(1000_000_000), // 1 gwei
L1FeeVaultMinimumWithdrawalAmount: uint64ToBig(1000_000_000), // 1 gwei
SequencerFeeVaultMinimumWithdrawalAmount: uint64ToBig(1000_000_000), // 1 gwei
BaseFeeVaultWithdrawalNetwork: uint8(1), // L2 withdrawal network
L1FeeVaultWithdrawalNetwork: uint8(1), // L2 withdrawal network
SequencerFeeVaultWithdrawalNetwork: uint8(1), // L2 withdrawal network
EIP1559Elasticity: 10, EIP1559Elasticity: 10,
EIP1559Denominator: 50, EIP1559Denominator: 50,
......
...@@ -125,9 +125,15 @@ func DefaultSystemConfig(t *testing.T) SystemConfig { ...@@ -125,9 +125,15 @@ func DefaultSystemConfig(t *testing.T) SystemConfig {
GasPriceOracleOverhead: 2100, GasPriceOracleOverhead: 2100,
GasPriceOracleScalar: 1_000_000, GasPriceOracleScalar: 1_000_000,
SequencerFeeVaultRecipient: common.Address{19: 1}, SequencerFeeVaultRecipient: common.Address{19: 1},
BaseFeeVaultRecipient: common.Address{19: 2}, BaseFeeVaultRecipient: common.Address{19: 2},
L1FeeVaultRecipient: common.Address{19: 3}, L1FeeVaultRecipient: common.Address{19: 3},
BaseFeeVaultMinimumWithdrawalAmount: uint642big(1000_000_000), // 1 gwei
L1FeeVaultMinimumWithdrawalAmount: uint642big(1000_000_000), // 1 gwei
SequencerFeeVaultMinimumWithdrawalAmount: uint642big(1000_000_000), // 1 gwei
BaseFeeVaultWithdrawalNetwork: uint8(1), // L2 withdrawal network
L1FeeVaultWithdrawalNetwork: uint8(1), // L2 withdrawal network
SequencerFeeVaultWithdrawalNetwork: uint8(1), // L2 withdrawal network
DeploymentWaitConfirmations: 1, DeploymentWaitConfirmations: 1,
......
...@@ -12,9 +12,15 @@ import { FeeVault } from "../universal/FeeVault.sol"; ...@@ -12,9 +12,15 @@ import { FeeVault } from "../universal/FeeVault.sol";
*/ */
contract BaseFeeVault is FeeVault, Semver { contract BaseFeeVault is FeeVault, Semver {
/** /**
* @custom:semver 1.1.0 * @custom:semver 1.2.0
* *
* @param _recipient Address that will receive the accumulated fees. * @param _recipient Wallet that will receive the fees.
* @param _minWithdrawalAmount Minimum balance for withdrawals.
* @param _withdrawalNetwork Network which the recipient will receive fees on.
*/ */
constructor(address _recipient) FeeVault(_recipient, 10 ether) Semver(1, 1, 0) {} constructor(
address _recipient,
uint256 _minWithdrawalAmount,
WithdrawalNetwork _withdrawalNetwork
) FeeVault(_recipient, _minWithdrawalAmount, _withdrawalNetwork) Semver(1, 2, 0) {}
} }
...@@ -12,9 +12,15 @@ import { FeeVault } from "../universal/FeeVault.sol"; ...@@ -12,9 +12,15 @@ import { FeeVault } from "../universal/FeeVault.sol";
*/ */
contract L1FeeVault is FeeVault, Semver { contract L1FeeVault is FeeVault, Semver {
/** /**
* @custom:semver 1.1.0 * @custom:semver 1.2.0
* *
* @param _recipient Address that will receive the accumulated fees. * @param _recipient Wallet that will receive the fees.
* @param _minWithdrawalAmount Minimum balance for withdrawals.
* @param _withdrawalNetwork Network which the recipient will receive fees on.
*/ */
constructor(address _recipient) FeeVault(_recipient, 10 ether) Semver(1, 1, 0) {} constructor(
address _recipient,
uint256 _minWithdrawalAmount,
WithdrawalNetwork _withdrawalNetwork
) FeeVault(_recipient, _minWithdrawalAmount, _withdrawalNetwork) Semver(1, 2, 0) {}
} }
...@@ -13,11 +13,17 @@ import { FeeVault } from "../universal/FeeVault.sol"; ...@@ -13,11 +13,17 @@ import { FeeVault } from "../universal/FeeVault.sol";
*/ */
contract SequencerFeeVault is FeeVault, Semver { contract SequencerFeeVault is FeeVault, Semver {
/** /**
* @custom:semver 1.1.0 * @custom:semver 1.2.0
* *
* @param _recipient Address that will receive the accumulated fees. * @param _recipient Wallet that will receive the fees.
* @param _minWithdrawalAmount Minimum balance for withdrawals.
* @param _withdrawalNetwork Network which the recipient will receive fees on.
*/ */
constructor(address _recipient) FeeVault(_recipient, 10 ether) Semver(1, 1, 0) {} constructor(
address _recipient,
uint256 _minWithdrawalAmount,
WithdrawalNetwork _withdrawalNetwork
) FeeVault(_recipient, _minWithdrawalAmount, _withdrawalNetwork) Semver(1, 2, 0) {}
/** /**
* @custom:legacy * @custom:legacy
......
...@@ -3,6 +3,7 @@ pragma solidity 0.8.15; ...@@ -3,6 +3,7 @@ pragma solidity 0.8.15;
import { Bridge_Initializer } from "./CommonTest.t.sol"; import { Bridge_Initializer } from "./CommonTest.t.sol";
import { FeeVault } from "../universal/FeeVault.sol";
import { L1FeeVault } from "../L2/L1FeeVault.sol"; import { L1FeeVault } from "../L2/L1FeeVault.sol";
import { BaseFeeVault } from "../L2/BaseFeeVault.sol"; import { BaseFeeVault } from "../L2/BaseFeeVault.sol";
import { StandardBridge } from "../universal/StandardBridge.sol"; import { StandardBridge } from "../universal/StandardBridge.sol";
...@@ -13,24 +14,31 @@ contract FeeVault_Test is Bridge_Initializer { ...@@ -13,24 +14,31 @@ contract FeeVault_Test is Bridge_Initializer {
BaseFeeVault baseFeeVault = BaseFeeVault(payable(Predeploys.BASE_FEE_VAULT)); BaseFeeVault baseFeeVault = BaseFeeVault(payable(Predeploys.BASE_FEE_VAULT));
L1FeeVault l1FeeVault = L1FeeVault(payable(Predeploys.L1_FEE_VAULT)); L1FeeVault l1FeeVault = L1FeeVault(payable(Predeploys.L1_FEE_VAULT));
address constant recipient = address(0x10000); uint256 constant otherMinimumWithdrawalAmount = 10 ether;
function setUp() public override { function setUp() public override {
super.setUp(); super.setUp();
vm.etch(Predeploys.BASE_FEE_VAULT, address(new BaseFeeVault(recipient)).code); vm.etch(
vm.etch(Predeploys.L1_FEE_VAULT, address(new L1FeeVault(recipient)).code); Predeploys.BASE_FEE_VAULT,
address(new BaseFeeVault(alice, NON_ZERO_VALUE, FeeVault.WithdrawalNetwork.L1)).code
);
vm.etch(
Predeploys.L1_FEE_VAULT,
address(
new L1FeeVault(bob, otherMinimumWithdrawalAmount, FeeVault.WithdrawalNetwork.L2)
).code
);
vm.label(Predeploys.BASE_FEE_VAULT, "BaseFeeVault"); vm.label(Predeploys.BASE_FEE_VAULT, "BaseFeeVault");
vm.label(Predeploys.L1_FEE_VAULT, "L1FeeVault"); vm.label(Predeploys.L1_FEE_VAULT, "L1FeeVault");
} }
function test_constructor_succeeds() external { function test_constructor_succeeds() external {
assertEq(baseFeeVault.RECIPIENT(), recipient); assertEq(baseFeeVault.RECIPIENT(), alice);
assertEq(l1FeeVault.RECIPIENT(), recipient); assertEq(l1FeeVault.RECIPIENT(), bob);
} assertEq(baseFeeVault.MIN_WITHDRAWAL_AMOUNT(), NON_ZERO_VALUE);
assertEq(l1FeeVault.MIN_WITHDRAWAL_AMOUNT(), otherMinimumWithdrawalAmount);
function test_minWithdrawalAmount_succeeds() external { assertEq(uint8(baseFeeVault.WITHDRAWAL_NETWORK()), uint8(FeeVault.WithdrawalNetwork.L1));
assertEq(baseFeeVault.MIN_WITHDRAWAL_AMOUNT(), 10 ether); assertEq(uint8(l1FeeVault.WITHDRAWAL_NETWORK()), uint8(FeeVault.WithdrawalNetwork.L2));
assertEq(l1FeeVault.MIN_WITHDRAWAL_AMOUNT(), 10 ether);
} }
} }
...@@ -3,6 +3,7 @@ pragma solidity 0.8.15; ...@@ -3,6 +3,7 @@ pragma solidity 0.8.15;
import { Bridge_Initializer } from "./CommonTest.t.sol"; import { Bridge_Initializer } from "./CommonTest.t.sol";
import { FeeVault } from "../universal/FeeVault.sol";
import { SequencerFeeVault } from "../L2/SequencerFeeVault.sol"; import { SequencerFeeVault } from "../L2/SequencerFeeVault.sol";
import { StandardBridge } from "../universal/StandardBridge.sol"; import { StandardBridge } from "../universal/StandardBridge.sol";
import { Predeploys } from "../libraries/Predeploys.sol"; import { Predeploys } from "../libraries/Predeploys.sol";
...@@ -11,16 +12,25 @@ contract SequencerFeeVault_Test is Bridge_Initializer { ...@@ -11,16 +12,25 @@ contract SequencerFeeVault_Test is Bridge_Initializer {
SequencerFeeVault vault = SequencerFeeVault(payable(Predeploys.SEQUENCER_FEE_WALLET)); SequencerFeeVault vault = SequencerFeeVault(payable(Predeploys.SEQUENCER_FEE_WALLET));
address constant recipient = address(256); address constant recipient = address(256);
event Withdrawal(uint256 value, address to, address from); event Withdrawal(
uint256 value,
address to,
address from,
FeeVault.WithdrawalNetwork withdrawalNetwork
);
function setUp() public override { function setUp() public override {
super.setUp(); super.setUp();
vm.etch(Predeploys.SEQUENCER_FEE_WALLET, address(new SequencerFeeVault(recipient)).code); vm.etch(
Predeploys.SEQUENCER_FEE_WALLET,
address(new SequencerFeeVault(recipient, NON_ZERO_VALUE, FeeVault.WithdrawalNetwork.L1))
.code
);
vm.label(Predeploys.SEQUENCER_FEE_WALLET, "SequencerFeeVault"); vm.label(Predeploys.SEQUENCER_FEE_WALLET, "SequencerFeeVault");
} }
function test_minWithdrawalAmount_succeeds() external { function test_minWithdrawalAmount_succeeds() external {
assertEq(vault.MIN_WITHDRAWAL_AMOUNT(), 10 ether); assertEq(vault.MIN_WITHDRAWAL_AMOUNT(), NON_ZERO_VALUE);
} }
function test_constructor_succeeds() external { function test_constructor_succeeds() external {
...@@ -46,7 +56,7 @@ contract SequencerFeeVault_Test is Bridge_Initializer { ...@@ -46,7 +56,7 @@ contract SequencerFeeVault_Test is Bridge_Initializer {
vault.withdraw(); vault.withdraw();
} }
function test_withdraw_succeeds() external { function test_withdraw_toL1_succeeds() external {
uint256 amount = vault.MIN_WITHDRAWAL_AMOUNT() + 1; uint256 amount = vault.MIN_WITHDRAWAL_AMOUNT() + 1;
vm.deal(address(vault), amount); vm.deal(address(vault), amount);
...@@ -54,7 +64,12 @@ contract SequencerFeeVault_Test is Bridge_Initializer { ...@@ -54,7 +64,12 @@ contract SequencerFeeVault_Test is Bridge_Initializer {
assertEq(vault.totalProcessed(), 0); assertEq(vault.totalProcessed(), 0);
vm.expectEmit(true, true, true, true, address(Predeploys.SEQUENCER_FEE_WALLET)); vm.expectEmit(true, true, true, true, address(Predeploys.SEQUENCER_FEE_WALLET));
emit Withdrawal(address(vault).balance, vault.RECIPIENT(), address(this)); emit Withdrawal(
address(vault).balance,
vault.RECIPIENT(),
address(this),
FeeVault.WithdrawalNetwork.L1
);
// The entire vault's balance is withdrawn // The entire vault's balance is withdrawn
vm.expectCall( vm.expectCall(
...@@ -73,4 +88,33 @@ contract SequencerFeeVault_Test is Bridge_Initializer { ...@@ -73,4 +88,33 @@ contract SequencerFeeVault_Test is Bridge_Initializer {
// The withdrawal was successful // The withdrawal was successful
assertEq(vault.totalProcessed(), amount); assertEq(vault.totalProcessed(), amount);
} }
function test_withdraw_toL2_succeeds() external {
vm.etch(
Predeploys.SEQUENCER_FEE_WALLET,
address(new SequencerFeeVault(recipient, NON_ZERO_VALUE, FeeVault.WithdrawalNetwork.L2))
.code
);
uint256 amount = vault.MIN_WITHDRAWAL_AMOUNT() + 1;
vm.deal(address(vault), amount);
// No ether has been withdrawn yet
assertEq(vault.totalProcessed(), 0);
vm.expectEmit(true, true, true, true, address(Predeploys.SEQUENCER_FEE_WALLET));
emit Withdrawal(
address(vault).balance,
vault.RECIPIENT(),
address(this),
FeeVault.WithdrawalNetwork.L2
);
// The entire vault's balance is withdrawn
vm.expectCall(recipient, address(vault).balance, bytes(""));
vault.withdraw();
// The withdrawal was successful
assertEq(vault.totalProcessed(), amount);
}
} }
...@@ -3,6 +3,7 @@ pragma solidity 0.8.15; ...@@ -3,6 +3,7 @@ pragma solidity 0.8.15;
import { L2StandardBridge } from "../L2/L2StandardBridge.sol"; import { L2StandardBridge } from "../L2/L2StandardBridge.sol";
import { Predeploys } from "../libraries/Predeploys.sol"; import { Predeploys } from "../libraries/Predeploys.sol";
import { SafeCall } from "../libraries/SafeCall.sol";
/** /**
* @title FeeVault * @title FeeVault
...@@ -11,13 +12,14 @@ import { Predeploys } from "../libraries/Predeploys.sol"; ...@@ -11,13 +12,14 @@ import { Predeploys } from "../libraries/Predeploys.sol";
*/ */
abstract contract FeeVault { abstract contract FeeVault {
/** /**
* @notice Emits each time that a withdrawal occurs. * @notice Enum representing where the FeeVault withdraws funds to.
* * @custom:value L1 FeeVault withdraws funds to L1.
* @param value Amount that was withdrawn (in wei). * @custom:value L2 FeeVault withdraws funds to L2.
* @param to Address that the funds were sent to.
* @param from Address that triggered the withdrawal.
*/ */
event Withdrawal(uint256 value, address to, address from); enum WithdrawalNetwork {
L1,
L2
}
/** /**
* @notice Minimum balance before a withdrawal can be triggered. * @notice Minimum balance before a withdrawal can be triggered.
...@@ -25,10 +27,15 @@ abstract contract FeeVault { ...@@ -25,10 +27,15 @@ abstract contract FeeVault {
uint256 public immutable MIN_WITHDRAWAL_AMOUNT; uint256 public immutable MIN_WITHDRAWAL_AMOUNT;
/** /**
* @notice Wallet that will receive the fees on L1. * @notice Wallet that will receive the fees.
*/ */
address public immutable RECIPIENT; address public immutable RECIPIENT;
/**
* @notice Network which the RECIPIENT will receive fees on.
*/
WithdrawalNetwork public immutable WITHDRAWAL_NETWORK;
/** /**
* @notice The minimum gas limit for the FeeVault withdrawal transaction. * @notice The minimum gas limit for the FeeVault withdrawal transaction.
*/ */
...@@ -40,12 +47,28 @@ abstract contract FeeVault { ...@@ -40,12 +47,28 @@ abstract contract FeeVault {
uint256 public totalProcessed; uint256 public totalProcessed;
/** /**
* @param _recipient Wallet that will receive the fees on L1. * @notice Emitted each time a withdrawal occurs.
* @param _minWithdrawalAmount Minimum balance before a withdrawal can be triggered. *
* @param value Amount that was withdrawn (in wei).
* @param to Address that the funds were sent to.
* @param from Address that triggered the withdrawal.
* @param withdrawalNetwork Network which the to address will receive funds on.
*/
event Withdrawal(uint256 value, address to, address from, WithdrawalNetwork withdrawalNetwork);
/**
* @param _recipient Wallet that will receive the fees.
* @param _minWithdrawalAmount Minimum balance for withdrawals.
* @param _withdrawalNetwork Network which the recipient will receive fees on.
*/ */
constructor(address _recipient, uint256 _minWithdrawalAmount) { constructor(
MIN_WITHDRAWAL_AMOUNT = _minWithdrawalAmount; address _recipient,
uint256 _minWithdrawalAmount,
WithdrawalNetwork _withdrawalNetwork
) {
RECIPIENT = _recipient; RECIPIENT = _recipient;
MIN_WITHDRAWAL_AMOUNT = _minWithdrawalAmount;
WITHDRAWAL_NETWORK = _withdrawalNetwork;
} }
/** /**
...@@ -54,7 +77,7 @@ abstract contract FeeVault { ...@@ -54,7 +77,7 @@ abstract contract FeeVault {
receive() external payable {} receive() external payable {}
/** /**
* @notice Triggers a withdrawal of funds to the L1 fee wallet. * @notice Triggers a withdrawal of funds to the fee wallet on L1 or L2.
*/ */
function withdraw() external { function withdraw() external {
require( require(
...@@ -65,12 +88,16 @@ abstract contract FeeVault { ...@@ -65,12 +88,16 @@ abstract contract FeeVault {
uint256 value = address(this).balance; uint256 value = address(this).balance;
totalProcessed += value; totalProcessed += value;
emit Withdrawal(value, RECIPIENT, msg.sender); emit Withdrawal(value, RECIPIENT, msg.sender, WITHDRAWAL_NETWORK);
L2StandardBridge(payable(Predeploys.L2_STANDARD_BRIDGE)).bridgeETHTo{ value: value }( if (WITHDRAWAL_NETWORK == WithdrawalNetwork.L2) {
RECIPIENT, SafeCall.call(RECIPIENT, gasleft(), value, bytes(""));
WITHDRAWAL_MIN_GAS, } else {
bytes("") L2StandardBridge(payable(Predeploys.L2_STANDARD_BRIDGE)).bridgeETHTo{ value: value }(
); RECIPIENT,
WITHDRAWAL_MIN_GAS,
bytes("")
);
}
} }
} }
...@@ -18,6 +18,12 @@ ...@@ -18,6 +18,12 @@
"baseFeeVaultRecipient": "0xBcd4042DE499D14e55001CcbB24a551F3b954096", "baseFeeVaultRecipient": "0xBcd4042DE499D14e55001CcbB24a551F3b954096",
"l1FeeVaultRecipient": "0x71bE63f3384f5fb98995898A86B02Fb2426c5788", "l1FeeVaultRecipient": "0x71bE63f3384f5fb98995898A86B02Fb2426c5788",
"sequencerFeeVaultRecipient": "0xfabb0ac9d68b0b445fb7357272ff202c5651694a", "sequencerFeeVaultRecipient": "0xfabb0ac9d68b0b445fb7357272ff202c5651694a",
"baseFeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000",
"l1FeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000",
"sequencerFeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000",
"baseFeeVaultWithdrawalNetwork": 0,
"l1FeeVaultWithdrawalNetwork": 0,
"sequencerFeeVaultWithdrawalNetwork": 0,
"proxyAdminOwner": "0xBcd4042DE499D14e55001CcbB24a551F3b954096", "proxyAdminOwner": "0xBcd4042DE499D14e55001CcbB24a551F3b954096",
"finalSystemOwner": "0xBcd4042DE499D14e55001CcbB24a551F3b954096", "finalSystemOwner": "0xBcd4042DE499D14e55001CcbB24a551F3b954096",
"portalGuardian": "0xBcd4042DE499D14e55001CcbB24a551F3b954096", "portalGuardian": "0xBcd4042DE499D14e55001CcbB24a551F3b954096",
......
...@@ -29,9 +29,16 @@ ...@@ -29,9 +29,16 @@
"finalizationPeriodSeconds": 12, "finalizationPeriodSeconds": 12,
"proxyAdminOwner": "ADMIN", "proxyAdminOwner": "ADMIN",
"baseFeeVaultRecipient": "ADMIN", "baseFeeVaultRecipient": "ADMIN",
"l1FeeVaultRecipient": "ADMIN", "l1FeeVaultRecipient": "ADMIN",
"sequencerFeeVaultRecipient": "ADMIN", "sequencerFeeVaultRecipient": "ADMIN",
"baseFeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000",
"l1FeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000",
"sequencerFeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000",
"baseFeeVaultWithdrawalNetwork": 0,
"l1FeeVaultWithdrawalNetwork": 0,
"sequencerFeeVaultWithdrawalNetwork": 0,
"gasPriceOracleOverhead": 2100, "gasPriceOracleOverhead": 2100,
"gasPriceOracleScalar": 1000000, "gasPriceOracleScalar": 1000000,
......
...@@ -32,6 +32,12 @@ ...@@ -32,6 +32,12 @@
"baseFeeVaultRecipient": "0xBc1233d0C3e6B5d53Ab455cF65A6623F6dCd7e4f", "baseFeeVaultRecipient": "0xBc1233d0C3e6B5d53Ab455cF65A6623F6dCd7e4f",
"l1FeeVaultRecipient": "0xBc1233d0C3e6B5d53Ab455cF65A6623F6dCd7e4f", "l1FeeVaultRecipient": "0xBc1233d0C3e6B5d53Ab455cF65A6623F6dCd7e4f",
"sequencerFeeVaultRecipient": "0xBc1233d0C3e6B5d53Ab455cF65A6623F6dCd7e4f", "sequencerFeeVaultRecipient": "0xBc1233d0C3e6B5d53Ab455cF65A6623F6dCd7e4f",
"baseFeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000",
"l1FeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000",
"sequencerFeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000",
"baseFeeVaultWithdrawalNetwork": 0,
"l1FeeVaultWithdrawalNetwork": 0,
"sequencerFeeVaultWithdrawalNetwork": 0,
"gasPriceOracleOverhead": 2100, "gasPriceOracleOverhead": 2100,
"gasPriceOracleScalar": 1000000, "gasPriceOracleScalar": 1000000,
......
...@@ -23,9 +23,15 @@ ...@@ -23,9 +23,15 @@
"baseFeeVaultRecipient": "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc", "baseFeeVaultRecipient": "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc",
"l1FeeVaultRecipient": "0x71bE63f3384f5fb98995898A86B02Fb2426c5788", "l1FeeVaultRecipient": "0x71bE63f3384f5fb98995898A86B02Fb2426c5788",
"sequencerFeeVaultRecipient": "0xfabb0ac9d68b0b445fb7357272ff202c5651694a", "sequencerFeeVaultRecipient": "0xfabb0ac9d68b0b445fb7357272ff202c5651694a",
"baseFeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000",
"l1FeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000",
"sequencerFeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000",
"baseFeeVaultWithdrawalNetwork": 0,
"l1FeeVaultWithdrawalNetwork": 0,
"sequencerFeeVaultWithdrawalNetwork": 0,
"governanceTokenName": "Optimism", "governanceTokenName": "Optimism",
"governanceTokenSymbol": "OP", "governanceTokenSymbol": "OP",
"governanceTokenOwner": "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc", "governanceTokenOwner": "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc",
"finalizationPeriodSeconds": 2, "finalizationPeriodSeconds": 2,
"numDeployConfirmations": 1 "numDeployConfirmations": 1
} }
\ No newline at end of file
...@@ -29,6 +29,12 @@ const config: DeployConfig = { ...@@ -29,6 +29,12 @@ const config: DeployConfig = {
baseFeeVaultRecipient: '0x90F79bf6EB2c4f870365E785982E1f101E93b906', baseFeeVaultRecipient: '0x90F79bf6EB2c4f870365E785982E1f101E93b906',
l1FeeVaultRecipient: '0x90F79bf6EB2c4f870365E785982E1f101E93b906', l1FeeVaultRecipient: '0x90F79bf6EB2c4f870365E785982E1f101E93b906',
sequencerFeeVaultRecipient: '0x90F79bf6EB2c4f870365E785982E1f101E93b906', sequencerFeeVaultRecipient: '0x90F79bf6EB2c4f870365E785982E1f101E93b906',
baseFeeVaultMinimumWithdrawalAmount: '0x8ac7230489e80000',
l1FeeVaultMinimumWithdrawalAmount: '0x8ac7230489e80000',
sequencerFeeVaultMinimumWithdrawalAmount: '0x8ac7230489e80000',
baseFeeVaultWithdrawalNetwork: 0,
l1FeeVaultWithdrawalNetwork: 0,
sequencerFeeVaultWithdrawalNetwork: 0,
governanceTokenName: 'Optimism', governanceTokenName: 'Optimism',
governanceTokenSymbol: 'OP', governanceTokenSymbol: 'OP',
......
...@@ -22,6 +22,12 @@ ...@@ -22,6 +22,12 @@
"baseFeeVaultRecipient": "0xa3d596EAfaB6B13Ab18D40FaE1A962700C84ADEa", "baseFeeVaultRecipient": "0xa3d596EAfaB6B13Ab18D40FaE1A962700C84ADEa",
"l1FeeVaultRecipient": "0xa3d596EAfaB6B13Ab18D40FaE1A962700C84ADEa", "l1FeeVaultRecipient": "0xa3d596EAfaB6B13Ab18D40FaE1A962700C84ADEa",
"sequencerFeeVaultRecipient": "0xa3d596EAfaB6B13Ab18D40FaE1A962700C84ADEa", "sequencerFeeVaultRecipient": "0xa3d596EAfaB6B13Ab18D40FaE1A962700C84ADEa",
"baseFeeVaultMinimumWithdrawalAmount": '0x8ac7230489e80000',
"l1FeeVaultMinimumWithdrawalAmount": '0x8ac7230489e80000',
"sequencerFeeVaultMinimumWithdrawalAmount": '0x8ac7230489e80000',
"baseFeeVaultWithdrawalNetwork": 0,
"l1FeeVaultWithdrawalNetwork": 0,
"sequencerFeeVaultWithdrawalNetwork": 0,
"governanceTokenName": "Optimism", "governanceTokenName": "Optimism",
"governanceTokenSymbol": "OP", "governanceTokenSymbol": "OP",
"governanceTokenOwner": "0x5C4e7Ba1E219E47948e6e3F55019A647bA501005", "governanceTokenOwner": "0x5C4e7Ba1E219E47948e6e3F55019A647bA501005",
......
...@@ -13,17 +13,38 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -13,17 +13,38 @@ const deployFn: DeployFunction = async (hre) => {
if (sequencerFeeVaultRecipient === ethers.constants.AddressZero) { if (sequencerFeeVaultRecipient === ethers.constants.AddressZero) {
throw new Error(`SequencerFeeVault RECIPIENT undefined`) throw new Error(`SequencerFeeVault RECIPIENT undefined`)
} }
const sequencerFeeVaultMinimumWithdrawalAmount =
deployConfig.sequencerFeeVaultMinimumWithdrawalAmount
const sequencerFeeVaultWithdrawalNetwork =
deployConfig.sequencerFeeVaultWithdrawalNetwork
if (sequencerFeeVaultWithdrawalNetwork >= 2) {
throw new Error('SequencerFeeVault WITHDRAWAL_NETWORK must be 0 or 1')
}
await deploy({ await deploy({
hre, hre,
name: 'SequencerFeeVault', name: 'SequencerFeeVault',
args: [sequencerFeeVaultRecipient], args: [
sequencerFeeVaultRecipient,
sequencerFeeVaultMinimumWithdrawalAmount,
sequencerFeeVaultWithdrawalNetwork,
],
postDeployAction: async (contract) => { postDeployAction: async (contract) => {
await assertContractVariable( await assertContractVariable(
contract, contract,
'RECIPIENT', 'RECIPIENT',
ethers.utils.getAddress(sequencerFeeVaultRecipient) ethers.utils.getAddress(sequencerFeeVaultRecipient)
) )
await assertContractVariable(
contract,
'MIN_WITHDRAWAL_AMOUNT',
sequencerFeeVaultMinimumWithdrawalAmount
)
await assertContractVariable(
contract,
'WITHDRAWAL_NETWORK',
sequencerFeeVaultWithdrawalNetwork
)
}, },
}) })
} }
......
...@@ -13,17 +13,38 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -13,17 +13,38 @@ const deployFn: DeployFunction = async (hre) => {
if (baseFeeVaultRecipient === ethers.constants.AddressZero) { if (baseFeeVaultRecipient === ethers.constants.AddressZero) {
throw new Error('BaseFeeVault RECIPIENT undefined') throw new Error('BaseFeeVault RECIPIENT undefined')
} }
const baseFeeVaultMinimumWithdrawalAmount =
deployConfig.baseFeeVaultMinimumWithdrawalAmount
const baseFeeVaultWithdrawalNetwork =
deployConfig.baseFeeVaultWithdrawalNetwork
if (baseFeeVaultWithdrawalNetwork >= 2) {
throw new Error('BaseFeeVault WITHDRAWAL_NETWORK must be 0 or 1')
}
await deploy({ await deploy({
hre, hre,
name: 'BaseFeeVault', name: 'BaseFeeVault',
args: [baseFeeVaultRecipient], args: [
baseFeeVaultRecipient,
baseFeeVaultMinimumWithdrawalAmount,
baseFeeVaultWithdrawalNetwork,
],
postDeployAction: async (contract) => { postDeployAction: async (contract) => {
await assertContractVariable( await assertContractVariable(
contract, contract,
'RECIPIENT', 'RECIPIENT',
ethers.utils.getAddress(baseFeeVaultRecipient) ethers.utils.getAddress(baseFeeVaultRecipient)
) )
await assertContractVariable(
contract,
'MIN_WITHDRAWAL_AMOUNT',
baseFeeVaultMinimumWithdrawalAmount
)
await assertContractVariable(
contract,
'WITHDRAWAL_NETWORK',
baseFeeVaultWithdrawalNetwork
)
}, },
}) })
} }
......
...@@ -13,17 +13,37 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -13,17 +13,37 @@ const deployFn: DeployFunction = async (hre) => {
if (l1FeeVaultRecipient === ethers.constants.AddressZero) { if (l1FeeVaultRecipient === ethers.constants.AddressZero) {
throw new Error('L1FeeVault RECIPIENT undefined') throw new Error('L1FeeVault RECIPIENT undefined')
} }
const l1FeeVaultMinimumWithdrawalAmount =
deployConfig.l1FeeVaultMinimumWithdrawalAmount
const l1FeeVaultWithdrawalNetwork = deployConfig.l1FeeVaultWithdrawalNetwork
if (l1FeeVaultWithdrawalNetwork >= 2) {
throw new Error('L1FeeVault WITHDRAWAL_NETWORK must be 0 or 1')
}
await deploy({ await deploy({
hre, hre,
name: 'L1FeeVault', name: 'L1FeeVault',
args: [l1FeeVaultRecipient], args: [
l1FeeVaultRecipient,
l1FeeVaultMinimumWithdrawalAmount,
l1FeeVaultWithdrawalNetwork,
],
postDeployAction: async (contract) => { postDeployAction: async (contract) => {
await assertContractVariable( await assertContractVariable(
contract, contract,
'RECIPIENT', 'RECIPIENT',
ethers.utils.getAddress(l1FeeVaultRecipient) ethers.utils.getAddress(l1FeeVaultRecipient)
) )
await assertContractVariable(
contract,
'MIN_WITHDRAWAL_AMOUNT',
l1FeeVaultMinimumWithdrawalAmount
)
await assertContractVariable(
contract,
'WITHDRAWAL_NETWORK',
l1FeeVaultWithdrawalNetwork
)
}, },
}) })
} }
......
...@@ -136,19 +136,49 @@ interface RequiredDeployConfig { ...@@ -136,19 +136,49 @@ interface RequiredDeployConfig {
proxyAdminOwner: string proxyAdminOwner: string
/** /**
* L1 address which receives the base fee for the L2 network. * L1 or L2 address which receives the base fee for the L2 network.
*/ */
baseFeeVaultRecipient: string baseFeeVaultRecipient: string
/** /**
* L1 address which receives data fees for the L2 network. * L1 or L2 address which receives data fees for the L2 network.
*/ */
l1FeeVaultRecipient: string l1FeeVaultRecipient: string
/** /**
* L1 address which receives tip fees for the L2 network. * L1 or L2 address which receives tip fees for the L2 network.
*/ */
sequencerFeeVaultRecipient: string sequencerFeeVaultRecipient: string
/**
* Minimum withdrawal amount for the BaseFeeVault contract.
*/
baseFeeVaultMinimumWithdrawalAmount: string
/**
* Minimum withdrawal amount for the L1FeeVault contract.
*/
l1FeeVaultMinimumWithdrawalAmount: string
/**
* Minimum withdrawal amount for the SequencerFeeVault contract.
*/
sequencerFeeVaultMinimumWithdrawalAmount: string
/**
* The network that BaseFeeVault contract withdrawals are sent to.
*/
baseFeeVaultWithdrawalNetwork: number
/**
* The network that L1FeeVault contract withdrawals are sent to.
*/
l1FeeVaultWithdrawalNetwork: number
/**
* The network that SequencerFeeVault contract withdrawals are sent to.
*/
sequencerFeeVaultWithdrawalNetwork: number
} }
/** /**
...@@ -279,6 +309,27 @@ export const deployConfigSpec: { ...@@ -279,6 +309,27 @@ export const deployConfigSpec: {
sequencerFeeVaultRecipient: { sequencerFeeVaultRecipient: {
type: 'address', type: 'address',
}, },
baseFeeVaultMinimumWithdrawalAmount: {
type: 'string',
default: '0x8ac7230489e80000', // 10 ether
},
l1FeeVaultMinimumWithdrawalAmount: {
type: 'string',
default: '0x8ac7230489e80000', // 10 ether
},
sequencerFeeVaultMinimumWithdrawalAmount: {
type: 'string',
default: '0x8ac7230489e80000', // 10 ether
},
baseFeeVaultWithdrawalNetwork: {
type: 'number',
},
l1FeeVaultWithdrawalNetwork: {
type: 'number',
},
sequencerFeeVaultWithdrawalNetwork: {
type: 'number',
},
cliqueSignerAddress: { cliqueSignerAddress: {
type: 'address', type: 'address',
default: ethers.constants.AddressZero, default: ethers.constants.AddressZero,
......
...@@ -392,7 +392,7 @@ const check = { ...@@ -392,7 +392,7 @@ const check = {
signer signer
) )
await assertSemver(SequencerFeeVault, 'SequencerFeeVault', '1.1.0') await assertSemver(SequencerFeeVault, 'SequencerFeeVault', '1.2.0')
const RECIPIENT = await SequencerFeeVault.RECIPIENT() const RECIPIENT = await SequencerFeeVault.RECIPIENT()
assert(RECIPIENT !== hre.ethers.constants.AddressZero) assert(RECIPIENT !== hre.ethers.constants.AddressZero)
...@@ -406,6 +406,10 @@ const check = { ...@@ -406,6 +406,10 @@ const check = {
await SequencerFeeVault.MIN_WITHDRAWAL_AMOUNT() await SequencerFeeVault.MIN_WITHDRAWAL_AMOUNT()
console.log(` - MIN_WITHDRAWAL_AMOUNT: ${MIN_WITHDRAWAL_AMOUNT}`) console.log(` - MIN_WITHDRAWAL_AMOUNT: ${MIN_WITHDRAWAL_AMOUNT}`)
const WITHDRAWAL_NETWORK = await SequencerFeeVault.WITHDRAWAL_NETWORK()
assert(WITHDRAWAL_NETWORK < 2)
console.log(` - WITHDRAWAL_NETWORK: ${WITHDRAWAL_NETWORK}`)
await checkProxy(hre, 'SequencerFeeVault', signer.provider) await checkProxy(hre, 'SequencerFeeVault', signer.provider)
await assertProxy(hre, 'SequencerFeeVault', signer.provider) await assertProxy(hre, 'SequencerFeeVault', signer.provider)
}, },
...@@ -635,7 +639,7 @@ const check = { ...@@ -635,7 +639,7 @@ const check = {
signer signer
) )
await assertSemver(BaseFeeVault, 'BaseFeeVault', '1.1.0') await assertSemver(BaseFeeVault, 'BaseFeeVault', '1.2.0')
const MIN_WITHDRAWAL_AMOUNT = await BaseFeeVault.MIN_WITHDRAWAL_AMOUNT() const MIN_WITHDRAWAL_AMOUNT = await BaseFeeVault.MIN_WITHDRAWAL_AMOUNT()
console.log(` - MIN_WITHDRAWAL_AMOUNT: ${MIN_WITHDRAWAL_AMOUNT}`) console.log(` - MIN_WITHDRAWAL_AMOUNT: ${MIN_WITHDRAWAL_AMOUNT}`)
...@@ -644,6 +648,10 @@ const check = { ...@@ -644,6 +648,10 @@ const check = {
assert(RECIPIENT !== hre.ethers.constants.AddressZero) assert(RECIPIENT !== hre.ethers.constants.AddressZero)
yell(` - RECIPIENT: ${RECIPIENT}`) yell(` - RECIPIENT: ${RECIPIENT}`)
const WITHDRAWAL_NETWORK = await BaseFeeVault.WITHDRAWAL_NETWORK()
assert(WITHDRAWAL_NETWORK < 2)
console.log(` - WITHDRAWAL_NETWORK: ${WITHDRAWAL_NETWORK}`)
await checkProxy(hre, 'BaseFeeVault', signer.provider) await checkProxy(hre, 'BaseFeeVault', signer.provider)
await assertProxy(hre, 'BaseFeeVault', signer.provider) await assertProxy(hre, 'BaseFeeVault', signer.provider)
}, },
...@@ -658,7 +666,7 @@ const check = { ...@@ -658,7 +666,7 @@ const check = {
signer signer
) )
await assertSemver(L1FeeVault, 'L1FeeVault', '1.1.0') await assertSemver(L1FeeVault, 'L1FeeVault', '1.2.0')
const MIN_WITHDRAWAL_AMOUNT = await L1FeeVault.MIN_WITHDRAWAL_AMOUNT() const MIN_WITHDRAWAL_AMOUNT = await L1FeeVault.MIN_WITHDRAWAL_AMOUNT()
console.log(` - MIN_WITHDRAWAL_AMOUNT: ${MIN_WITHDRAWAL_AMOUNT}`) console.log(` - MIN_WITHDRAWAL_AMOUNT: ${MIN_WITHDRAWAL_AMOUNT}`)
...@@ -667,6 +675,10 @@ const check = { ...@@ -667,6 +675,10 @@ const check = {
assert(RECIPIENT !== hre.ethers.constants.AddressZero) assert(RECIPIENT !== hre.ethers.constants.AddressZero)
yell(` - RECIPIENT: ${RECIPIENT}`) yell(` - RECIPIENT: ${RECIPIENT}`)
const WITHDRAWAL_NETWORK = await L1FeeVault.WITHDRAWAL_NETWORK()
assert(WITHDRAWAL_NETWORK < 2)
console.log(` - WITHDRAWAL_NETWORK: ${WITHDRAWAL_NETWORK}`)
await checkProxy(hre, 'L1FeeVault', signer.provider) await checkProxy(hre, 'L1FeeVault', signer.provider)
await assertProxy(hre, 'L1FeeVault', signer.provider) await assertProxy(hre, 'L1FeeVault', signer.provider)
}, },
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment