Skip to content

Commit 0f21af9

Browse files
0xDiscotechfunkornaut0010xiamflux0xChinsimon-something
authored
feat: introduce fee splitter for revenue share (#17536)
* feat: fee splitter system (#469) ---- Co-authored-by: Disco <[email protected]> Co-authored-by: Flux <[email protected]> Co-authored-by: Chiin <[email protected]> * fix: failing tests (#553) * refactor: revenue sharing config (#538) * fix: pre pr and semgrep (#565) * fix: warnings (#571) * fix: tests failing on fork environment (#575) * fix: use encode call on constructors (#578) * feat: add integration splitter test (#581) * fix: integration test nits (#583) * test: more coverage on splitter tests (#594) --------- Co-authored-by: Chiin <[email protected]> * fix: add missing operator fee vault field (#616) * feat: invariants and tests (#595) * fix: ir informationals (#609) * fix: pre pr (#622) * refactor: use cdm (#624) * fix: update withdrawal gas limit value on check (#627) * fix: remove rev share field from deploy op chain input struct (#628) * refactor: remove initializer and vaults getter changes (#631) * fix: remove immutable check over vaults (#634) Co-authored-by: 0xng <[email protected]> Co-authored-by: Funkornaut <[email protected]> Co-authored-by: Joxess <[email protected]> * fix: audit findings (#658) * fix: pre pr * feat: add user guide docs for rev sharing on op deployer (#666) * docs: add create2 comment (#667) --------- Co-authored-by: Funkornaut <[email protected]> Co-authored-by: Flux <[email protected]> Co-authored-by: Chiin <[email protected]> Co-authored-by: Simon Something /DrGoNoGo <[email protected]> Co-authored-by: 0xng <[email protected]> Co-authored-by: Joxess <[email protected]>
1 parent 2534a40 commit 0f21af9

File tree

108 files changed

+9306
-621
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

108 files changed

+9306
-621
lines changed

.circleci/config.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -562,7 +562,7 @@ jobs:
562562
contracts-bedrock-build:
563563
docker:
564564
- image: <<pipeline.parameters.default_docker_image>>
565-
resource_class: xlarge
565+
resource_class: 2xlarge
566566
parameters:
567567
build_args:
568568
description: Forge build arguments
@@ -862,7 +862,7 @@ jobs:
862862
circleci_ip_ranges: true
863863
docker:
864864
- image: <<pipeline.parameters.default_docker_image>>
865-
resource_class: xlarge
865+
resource_class: 2xlarge
866866
parameters:
867867
test_list:
868868
description: List of test files to run

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,4 @@ __pycache__
5050
crytic-export
5151

5252
# ignore local asdf config
53-
.tool-versions
53+
.tool-versions

.semgrep/rules/sol-rules.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ rules:
194194
paths:
195195
exclude:
196196
- packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol
197+
- packages/contracts-bedrock/test/invariants/FeeSplit.t.sol
197198

198199
- id: sol-style-enforce-require-msg
199200
languages: [solidity]

devnet-sdk/contracts/constants/constants.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,15 @@ var (
2222
ProxyAdmin types.Address = common.HexToAddress("0x4200000000000000000000000000000000000018")
2323
BaseFeeVault types.Address = common.HexToAddress("0x4200000000000000000000000000000000000019")
2424
L1FeeVault types.Address = common.HexToAddress("0x420000000000000000000000000000000000001a")
25+
OperatorFeeVault types.Address = common.HexToAddress("0x420000000000000000000000000000000000001B")
2526
SchemaRegistry types.Address = common.HexToAddress("0x4200000000000000000000000000000000000020")
2627
EAS types.Address = common.HexToAddress("0x4200000000000000000000000000000000000021")
2728
CrossL2Inbox types.Address = common.HexToAddress("0x4200000000000000000000000000000000000022")
2829
L2ToL2CrossDomainMessenger types.Address = common.HexToAddress("0x4200000000000000000000000000000000000023")
2930
SuperchainETHBridge types.Address = common.HexToAddress("0x4200000000000000000000000000000000000024")
3031
ETHLiquidity types.Address = common.HexToAddress("0x4200000000000000000000000000000000000025")
3132
SuperchainTokenBridge types.Address = common.HexToAddress("0x4200000000000000000000000000000000000028")
33+
FeeSplitter types.Address = common.HexToAddress("0x420000000000000000000000000000000000002B")
3234
GovernanceToken types.Address = common.HexToAddress("0x4200000000000000000000000000000000000042")
3335
Create2Deployer types.Address = common.HexToAddress("0x13b0D85CcB8bf860b6b79AF3029fCA081AE9beF2")
3436
MultiCall3 types.Address = common.HexToAddress("0xcA11bde05977b3631167028862bE2a173976CA11")

op-chain-ops/devkeys/devkeys.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,10 @@ const (
158158
SequencerFeeVaultRecipientRole ChainOperatorRole = 9
159159
// SystemConfigOwner is the key that can make SystemConfig changes.
160160
SystemConfigOwner ChainOperatorRole = 10
161+
// OperatorFeeVaultRecipientRole is the key that receives from the OperatorFeeVault predeploy
162+
OperatorFeeVaultRecipientRole ChainOperatorRole = 11
163+
// ChainFeesRecipientRole is the key that receives the chain's share from the FeeSplitter
164+
ChainFeesRecipientRole ChainOperatorRole = 12
161165
)
162166

163167
func (role ChainOperatorRole) String() string {
@@ -182,8 +186,12 @@ func (role ChainOperatorRole) String() string {
182186
return "l1-fee-vault-recipient"
183187
case SequencerFeeVaultRecipientRole:
184188
return "sequencer-fee-vault-recipient"
189+
case OperatorFeeVaultRecipientRole:
190+
return "operator-fee-vault-recipient"
185191
case SystemConfigOwner:
186192
return "system-config-owner"
193+
case ChainFeesRecipientRole:
194+
return "chain-fees-recipient"
187195
default:
188196
return fmt.Sprintf("unknown-operator-%d", uint64(role))
189197
}

op-chain-ops/genesis/config.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,22 @@ type DevDeployConfig struct {
8686
FundDevAccounts bool `json:"fundDevAccounts"`
8787
}
8888

89+
type RevenueShareDeployConfig struct {
90+
UseRevenueShare bool `json:"useRevenueShare"`
91+
ChainFeesRecipient common.Address `json:"chainFeesRecipient"`
92+
}
93+
94+
var _ ConfigChecker = (*RevenueShareDeployConfig)(nil)
95+
96+
func (d *RevenueShareDeployConfig) Check(log log.Logger) error {
97+
if d.UseRevenueShare {
98+
if d.ChainFeesRecipient == (common.Address{}) {
99+
return fmt.Errorf("%w: ChainFeesRecipient cannot be address(0)", ErrInvalidDeployConfig)
100+
}
101+
}
102+
return nil
103+
}
104+
89105
type L2GenesisBlockDeployConfig struct {
90106
L2GenesisBlockNonce hexutil.Uint64 `json:"l2GenesisBlockNonce"`
91107
L2GenesisBlockGasLimit hexutil.Uint64 `json:"l2GenesisBlockGasLimit"`
@@ -150,18 +166,24 @@ type L2VaultsDeployConfig struct {
150166
// SequencerFeeVaultRecipient represents the recipient of fees accumulated in the SequencerFeeVault.
151167
// Can be an account on L1 or L2, depending on the SequencerFeeVaultWithdrawalNetwork value.
152168
SequencerFeeVaultRecipient common.Address `json:"sequencerFeeVaultRecipient"`
169+
// OperatorFeeVaultRecipient represents the recipient of fees accumulated in the OperatorFeeVault.
170+
OperatorFeeVaultRecipient common.Address `json:"operatorFeeVaultRecipient"`
153171
// BaseFeeVaultMinimumWithdrawalAmount represents the minimum withdrawal amount for the BaseFeeVault.
154172
BaseFeeVaultMinimumWithdrawalAmount *hexutil.Big `json:"baseFeeVaultMinimumWithdrawalAmount"`
155173
// L1FeeVaultMinimumWithdrawalAmount represents the minimum withdrawal amount for the L1FeeVault.
156174
L1FeeVaultMinimumWithdrawalAmount *hexutil.Big `json:"l1FeeVaultMinimumWithdrawalAmount"`
157175
// SequencerFeeVaultMinimumWithdrawalAmount represents the minimum withdrawal amount for the SequencerFeeVault.
158176
SequencerFeeVaultMinimumWithdrawalAmount *hexutil.Big `json:"sequencerFeeVaultMinimumWithdrawalAmount"`
177+
// OperatorFeeVaultMinimumWithdrawalAmount represents the minimum withdrawal amount for the OperatorFeeVault.
178+
OperatorFeeVaultMinimumWithdrawalAmount *hexutil.Big `json:"operatorFeeVaultMinimumWithdrawalAmount"`
159179
// BaseFeeVaultWithdrawalNetwork represents the withdrawal network for the BaseFeeVault.
160180
BaseFeeVaultWithdrawalNetwork WithdrawalNetwork `json:"baseFeeVaultWithdrawalNetwork"`
161181
// L1FeeVaultWithdrawalNetwork represents the withdrawal network for the L1FeeVault.
162182
L1FeeVaultWithdrawalNetwork WithdrawalNetwork `json:"l1FeeVaultWithdrawalNetwork"`
163183
// SequencerFeeVaultWithdrawalNetwork represents the withdrawal network for the SequencerFeeVault.
164184
SequencerFeeVaultWithdrawalNetwork WithdrawalNetwork `json:"sequencerFeeVaultWithdrawalNetwork"`
185+
// OperatorFeeVaultWithdrawalNetwork represents the withdrawal network for the OperatorFeeVault.
186+
OperatorFeeVaultWithdrawalNetwork WithdrawalNetwork `json:"operatorFeeVaultWithdrawalNetwork"`
165187
}
166188

167189
var _ ConfigChecker = (*L2VaultsDeployConfig)(nil)
@@ -176,6 +198,9 @@ func (d *L2VaultsDeployConfig) Check(log log.Logger) error {
176198
if d.SequencerFeeVaultRecipient == (common.Address{}) {
177199
return fmt.Errorf("%w: SequencerFeeVaultRecipient cannot be address(0)", ErrInvalidDeployConfig)
178200
}
201+
if d.OperatorFeeVaultRecipient == (common.Address{}) {
202+
return fmt.Errorf("%w: OperatorFeeVaultRecipient cannot be address(0)", ErrInvalidDeployConfig)
203+
}
179204
if !d.BaseFeeVaultWithdrawalNetwork.Valid() {
180205
return fmt.Errorf("%w: BaseFeeVaultWithdrawalNetwork can only be 0 (L1) or 1 (L2)", ErrInvalidDeployConfig)
181206
}
@@ -185,6 +210,9 @@ func (d *L2VaultsDeployConfig) Check(log log.Logger) error {
185210
if !d.SequencerFeeVaultWithdrawalNetwork.Valid() {
186211
return fmt.Errorf("%w: SequencerFeeVaultWithdrawalNetwork can only be 0 (L1) or 1 (L2)", ErrInvalidDeployConfig)
187212
}
213+
if !d.OperatorFeeVaultWithdrawalNetwork.Valid() {
214+
return fmt.Errorf("%w: OperatorFeeVaultWithdrawalNetwork can only be 0 (L1) or 1 (L2)", ErrInvalidDeployConfig)
215+
}
188216
return nil
189217
}
190218

@@ -743,6 +771,7 @@ type L2InitializationConfig struct {
743771
L2CoreDeployConfig
744772
FeeMarketConfig
745773
AltDADeployConfig
774+
RevenueShareDeployConfig
746775
}
747776

748777
func (d *L2InitializationConfig) Check(log log.Logger) error {

op-chain-ops/genesis/testdata/test-deploy-config-full.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,15 @@
4040
"baseFeeVaultRecipient": "0x42000000000000000000000000000000000000f5",
4141
"l1FeeVaultRecipient": "0x42000000000000000000000000000000000000f6",
4242
"sequencerFeeVaultRecipient": "0x42000000000000000000000000000000000000f7",
43+
"operatorFeeVaultRecipient": "0x4200000000000000000000000000000000000063",
4344
"baseFeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000",
4445
"l1FeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000",
4546
"sequencerFeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000",
47+
"operatorFeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000",
4648
"baseFeeVaultWithdrawalNetwork": 0,
4749
"l1FeeVaultWithdrawalNetwork": 1,
4850
"sequencerFeeVaultWithdrawalNetwork": 1,
51+
"operatorFeeVaultWithdrawalNetwork": 1,
4952
"l1StandardBridgeProxy": "0x42000000000000000000000000000000000000f8",
5053
"l1CrossDomainMessengerProxy": "0x42000000000000000000000000000000000000f9",
5154
"l1ERC721BridgeProxy": "0x4200000000000000000000000000000000000060",
@@ -94,5 +97,7 @@
9497
"daChallengeProxy": "0x0000000000000000000000000000000000000000",
9598
"daChallengeWindow": 0,
9699
"daResolveWindow": 0,
97-
"daResolverRefundPercentage": 0
100+
"daResolverRefundPercentage": 0,
101+
"useRevenueShare": true,
102+
"chainFeesRecipient": "0x0000000000000000000000000000000000000444"
98103
}

op-chain-ops/genesis/withdrawal_network_test.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,18 +83,21 @@ func TestWithdrawalNetworkInlineJSON(t *testing.T) {
8383
BaseFeeVaultWithdrawalNetwork WithdrawalNetwork `json:"baseFeeVaultWithdrawalNetwork"`
8484
L1FeeVaultWithdrawalNetwork WithdrawalNetwork `json:"l1FeeVaultWithdrawalNetwork"`
8585
SequencerFeeVaultWithdrawalNetwork WithdrawalNetwork `json:"sequencerFeeVaultWithdrawalNetwork"`
86+
OperatorFeeVaultWithdrawalNetwork WithdrawalNetwork `json:"operatorFeeVaultWithdrawalNetwork"`
8687
}
8788

8889
jsonString := `{
8990
"baseFeeVaultWithdrawalNetwork": "remote",
9091
"l1FeeVaultWithdrawalNetwork": "local",
91-
"sequencerFeeVaultWithdrawalNetwork": "local"
92+
"sequencerFeeVaultWithdrawalNetwork": "local",
93+
"operatorFeeVaultWithdrawalNetwork": "local"
9294
}`
9395

9496
intJsonString := `{
9597
"baseFeeVaultWithdrawalNetwork": 0,
9698
"l1FeeVaultWithdrawalNetwork": 1,
97-
"sequencerFeeVaultWithdrawalNetwork": 1
99+
"sequencerFeeVaultWithdrawalNetwork": 1,
100+
"operatorFeeVaultWithdrawalNetwork": 1
98101
}`
99102

100103
t.Run("StringMarshaling", func(t *testing.T) {
@@ -104,6 +107,7 @@ func TestWithdrawalNetworkInlineJSON(t *testing.T) {
104107
require.Equal(t, WithdrawalNetwork("remote"), decoded.BaseFeeVaultWithdrawalNetwork)
105108
require.Equal(t, WithdrawalNetwork("local"), decoded.L1FeeVaultWithdrawalNetwork)
106109
require.Equal(t, WithdrawalNetwork("local"), decoded.SequencerFeeVaultWithdrawalNetwork)
110+
require.Equal(t, WithdrawalNetwork("local"), decoded.OperatorFeeVaultWithdrawalNetwork)
107111

108112
encoded, err := json.Marshal(decoded)
109113
require.NoError(t, err)
@@ -118,6 +122,7 @@ func TestWithdrawalNetworkInlineJSON(t *testing.T) {
118122
require.Equal(t, WithdrawalNetwork("remote"), decoded.BaseFeeVaultWithdrawalNetwork)
119123
require.Equal(t, WithdrawalNetwork("local"), decoded.L1FeeVaultWithdrawalNetwork)
120124
require.Equal(t, WithdrawalNetwork("local"), decoded.SequencerFeeVaultWithdrawalNetwork)
125+
require.Equal(t, WithdrawalNetwork("local"), decoded.OperatorFeeVaultWithdrawalNetwork)
121126

122127
encoded, err := json.Marshal(decoded)
123128
require.NoError(t, err)

op-chain-ops/interopgen/deploy.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer"
2222
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/manage"
2323
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/opcm"
24+
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/standard"
2425
"github.com/ethereum-optimism/optimism/op-service/eth"
2526
)
2627

@@ -329,11 +330,17 @@ func GenesisL2(l2Host *script.Host, cfg *L2Config, deployment *L2Deployment, mul
329330
L1FeeVaultRecipient: cfg.L1FeeVaultRecipient,
330331
L1FeeVaultMinimumWithdrawalAmount: cfg.L1FeeVaultMinimumWithdrawalAmount.ToInt(),
331332
L1FeeVaultWithdrawalNetwork: big.NewInt(int64(cfg.L1FeeVaultWithdrawalNetwork.ToUint8())),
333+
OperatorFeeVaultRecipient: cfg.OperatorFeeVaultRecipient,
334+
OperatorFeeVaultMinimumWithdrawalAmount: cfg.OperatorFeeVaultMinimumWithdrawalAmount.ToInt(),
335+
OperatorFeeVaultWithdrawalNetwork: big.NewInt(int64(cfg.OperatorFeeVaultWithdrawalNetwork.ToUint8())),
332336
GovernanceTokenOwner: cfg.GovernanceTokenOwner,
333337
Fork: big.NewInt(cfg.SolidityForkNumber(1)),
334338
DeployCrossL2Inbox: multichainDepSet,
335339
EnableGovernance: cfg.EnableGovernance,
336340
FundDevAccounts: cfg.FundDevAccounts,
341+
UseRevenueShare: cfg.UseRevenueShare,
342+
ChainFeesRecipient: cfg.ChainFeesRecipient,
343+
L1FeesDepositor: standard.L1FeesDepositor,
337344
}); err != nil {
338345
return fmt.Errorf("failed L2 genesis: %w", err)
339346
}

op-chain-ops/interopgen/recipe.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,10 @@ func (r *InteropDevL2Recipe) build(l1ChainID uint64, addrs devkeys.Addresses) (*
186186
if err != nil {
187187
return nil, err
188188
}
189+
operatorFeeVaultRecipient, err := addrs.Address(chainOps(devkeys.OperatorFeeVaultRecipientRole))
190+
if err != nil {
191+
return nil, err
192+
}
189193
sequencerP2P, err := addrs.Address(chainOps(devkeys.SequencerP2PRole))
190194
if err != nil {
191195
return nil, err
@@ -228,12 +232,15 @@ func (r *InteropDevL2Recipe) build(l1ChainID uint64, addrs devkeys.Addresses) (*
228232
BaseFeeVaultRecipient: baseFeeVaultRecipient,
229233
L1FeeVaultRecipient: l1FeeVaultRecipient,
230234
SequencerFeeVaultRecipient: sequencerFeeVaultRecipient,
235+
OperatorFeeVaultRecipient: operatorFeeVaultRecipient,
231236
BaseFeeVaultMinimumWithdrawalAmount: (*hexutil.Big)(Ether(10)),
232237
L1FeeVaultMinimumWithdrawalAmount: (*hexutil.Big)(Ether(10)),
233238
SequencerFeeVaultMinimumWithdrawalAmount: (*hexutil.Big)(Ether(10)),
239+
OperatorFeeVaultMinimumWithdrawalAmount: (*hexutil.Big)(Ether(10)),
234240
BaseFeeVaultWithdrawalNetwork: "remote",
235241
L1FeeVaultWithdrawalNetwork: "remote",
236242
SequencerFeeVaultWithdrawalNetwork: "remote",
243+
OperatorFeeVaultWithdrawalNetwork: "remote",
237244
},
238245
GovernanceDeployConfig: genesis.GovernanceDeployConfig{
239246
EnableGovernance: false,
@@ -282,6 +289,10 @@ func (r *InteropDevL2Recipe) build(l1ChainID uint64, addrs devkeys.Addresses) (*
282289
AltDADeployConfig: genesis.AltDADeployConfig{
283290
UseAltDA: false,
284291
},
292+
RevenueShareDeployConfig: genesis.RevenueShareDeployConfig{
293+
UseRevenueShare: false,
294+
ChainFeesRecipient: common.Address{},
295+
},
285296
},
286297
Prefund: make(map[common.Address]*big.Int),
287298
SaltMixer: "",

0 commit comments

Comments
 (0)