Skip to content

Conversation

tynes
Copy link
Contributor

@tynes tynes commented Jul 28, 2025

Description

Puts together an initial design doc for revenue sharing by enshrining
the fee split predeploy in the OP Stack.

Puts together an initial design doc for revenue sharing by enshrining
the fee split predeploy in the OP Stack.
Copy link
Contributor

@Joxess Joxess left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a great proposal, right now I'm curious on the value of having the math calculations to be generalizable or not in this phase


#### `FeeSplitter`

All of the `FeeVault` implementations need to have their `RECIPIENT` set to the `FeeSplitter`. This means that all fees that are accumulated in the system will be sent through the `FeeSplitter`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the math also be enshrined in the contract, or something that whoever is the owner might customize?

For example, when operatorFee is enabled, how does that impact the current calculation?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now we should enshrine the math in the contract. If we need to change the math in the future, we could look into abstracting it. I think the interface would be a list of address/uint256/withdrawal-network and we would just pay out to each of them.


- Add Operator Fee Vault support
- Make `OPTIMISM_WALLET` and `L1_WALLET` modifiable by L2 `ProxyAdmin.owner()`
- Replace `L1_WALLET` with sending to an L2 account similar to the Unichain architecture so that the design is more flexible. The L2 account that Unichain sends to is called `L1Splitter` ([link](https://github.com/Uniswap/unichain-contracts/blob/main/src/FeeSplitter/L1Splitter.sol)) and withdraws to L1. This architecture will make it more flexible for custom gas token chains or architectures where fees want to be collected on the L2 directly.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 on enabling CGT support

@alcueca
Copy link
Contributor

alcueca commented Aug 14, 2025

After a couple of reads, I think I get it. We want to:

  • Implement a new FeeVaultV2 contract so that the RECIPIENT can be set by ProxyAdminOwner.
  • Deploy and configure a new FeeVaultV2 copying data from each existing FeeVault (are they not upgradable?).
  • Change something so that the fees accrue to the new FeeVaultV2 maybe?
  • Have a standard FeeSplitter predeploy similar to the one from Base. No one would be using this FeeSplitter as of day 0, but it would be there for whenever anyone wants to change the RECIPIENT in a FeeVaultV2.

@alcueca
Copy link
Contributor

alcueca commented Aug 14, 2025

if we are going to migrate all FeeVault, maybe we should also put them behind a proxy so that next time they can be upgraded.

@tynes tynes marked this pull request as ready for review August 14, 2025 21:45
@tynes
Copy link
Contributor Author

tynes commented Aug 14, 2025

After a couple of reads, I think I get it. We want to:

  • Implement a new FeeVaultV2 contract so that the RECIPIENT can be set by ProxyAdminOwner.
  • Deploy and configure a new FeeVaultV2 copying data from each existing FeeVault (are they not upgradable?).
  • Change something so that the fees accrue to the new FeeVaultV2 maybe?
  • Have a standard FeeSplitter predeploy similar to the one from Base. No one would be using this FeeSplitter as of day 0, but it would be there for whenever anyone wants to change the RECIPIENT in a FeeVaultV2.

Thanks for rereading and summarizing your understanding. The FeeVault contracts are upgradable, but each chain may have a different value for its RECIPIENT. The predeploys are upgraded with network upgrade transactions - these are deposit transactions that are deterministically placed into the hardfork block. This means that if we wanted to maintain the exact same config that each fee vault has, we need to either 1) add those values to the rollup config so that they are sourced from there (but have a race condition if the onchain value is changed after the rollup config is committed to) or 2) dynamically fetch the values as part of the network upgrade transactions. I opt for 2 as part of this.

The FeeVault2 is really just a semantic version bump of the existing FeeVault, we would be adding new code directly to the FeeVault and then replacing the 1967 proxy implementation slot with the address of the newly deployed FeeVault. The network upgrade transactions can do all of this. The fee vault proxy addresses stay the same

You are right that at the end of this upgrade, it would not be auto configuring anybody into using the FeeSplitter. We would follow up with a multisig transaction to configure it.

@alcueca
Copy link
Contributor

alcueca commented Aug 16, 2025

I see the nuance, the FeeVault contracts are upgradable, but moving RECIPIENT from immutable to state variable requires collecting the value from the existing implementation and then setting it in the new implementation. It's not an storage to storage upgrade nor a bytecode to bytecode upgrade. Maybe this can be explained more clearly in the design docs.

I don't see how the onchain value would change since it is immutable, but regardless I don't see a problem with using a migrator contract instead of manually setting the address in the rollup config. Both options seem to have a similar complexity, which is low in any case.

In general, I agree with the design - I think it can be explained to partners easily.

I also agree with the approach - opt-in mitigates the risk of a wholesale migration of all fee flows. We do not standardize the fee flows yet, but make it easier to do so piecemeal.

@tynes tynes requested a review from Copilot August 18, 2025 15:24
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces an initial design document for standardizing revenue sharing across the OP Stack through fee split predeploys. The design aims to create a unified, configurable solution for splitting fees between Superchain operators and chain operators while maintaining backward compatibility with existing implementations.

Key changes include:

  • Introduction of a standardized FeeSplitter predeploy based on existing Base and Uniswap implementations
  • Enhanced FeeVault contracts with configurable recipient settings
  • Opt-in migration strategy to avoid breaking existing production systems

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

This design doc is specific to the fee splitting logic and does not cover any logic around where those fees go after they are split.

It is also opt-in for chains, the network upgrade transactions do not modify any existing `FeeVault` configuration. The new `FeeVault` contracts are deployed and initialized at each `FeeVault` predeploy. The `FeeSplitter` is deployed without being hooked into any of the `FeeVault` contracts.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adversarial modeling during threat modeling around advantageous fee splitting

- `RECIPIENT`
- `WITHDRAWAL_NETWORK`

#### `FeeVaultInitializer`
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lay out the pros and cons for modifying the FeeVault in favor of allowing the chain operators being able to more easily change their config

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Propose we use defi-wonderland/optimism#482 (comment) as the upgrade path

- 100% opt-in
- Simple runbook for opting in
- Support all 4 fee vaults
- Does not break Base or Uniswap fee splitter contracts
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non goal - arbitrary config fee split algo, we enshrine the 15%/2.5%


### Production Today

The `FeeSplitter` predeploy (including both Base and Uniswap implementations) depends on the `RECIPIENT` of each of these contracts to be set to the fee split contract with the `WithdrawalNetwork` of L2.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should do a design review on the FeeSplitter itself

@tynes
Copy link
Contributor Author

tynes commented Aug 19, 2025

Reduce the number of interactions as much as possible

  • Poke the fee splitter to pull fees from the fee vaults
  • Can the same poke trigger a withdrawal?
  • The poke should not require a multisig
  • Make sure it works with CGT and L3s
  • For CGT
    • There is a bunch of nuance, sometimes there isn't an L1 representation of the token
    • Will likely be a case by case basis
  • A withdrawal service would be really helpful

@pharger
Copy link

pharger commented Aug 19, 2025

Few notes in similar vein:

  • Add diagram flow of funds to the design spec so operators know how the funds will move and where manual intervention will be needed @tynes
  • Figure out how we might automate the withdraw flows so that operators dont need manual process every 7 days to prove withdraws etc
  • Fee splitter should not require a multisig
  • Lets deep dive once we have a live prototype on testnets that we can validate - somewhat weary that we will run into issues with the profit calcs when looking in detail at the math
  • CGTs --> Lets collaborate with them on the best solve when we bring v2 live
  • L3s --> P3 right now but understand how to serve in the future

@tynes
Copy link
Contributor Author

tynes commented Aug 19, 2025

Specs - defi-wonderland/specs#47
Implementation - defi-wonderland/optimism#469

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants