Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
d8d8775
feat: add appendix for L1 Withdrawer and SuperchainRevSharesCalculator
0xiamflux Sep 2, 2025
d714660
chore: lint on jovian files
0xiamflux Sep 2, 2025
20ba712
refactor: remove outdated references to metadata
0xiamflux Sep 3, 2025
45c29e7
refactor: remove outdated rounding behavior
0xiamflux Sep 3, 2025
dce3654
refactor: rewording on summary
0xiamflux Sep 3, 2025
745a254
feat: add FundReceived event
0xiamflux Sep 3, 2025
60a1add
chore: remove outdated references
0xiamflux Sep 3, 2025
aec17dc
refactor: remove outdated references, make clear backward compatibility
0xiamflux Sep 3, 2025
571c724
refactor: move superchainrevsharecalc and l1withdrawer to their own doc
0xiamflux Sep 3, 2025
8a67f37
feat: add ShareInfo struct to specs
0xiamflux Sep 3, 2025
cd6f2f6
refactor: l1withdrawer events
0xiamflux Sep 3, 2025
32a28ea
Update specs/protocol/jovian/l1-withdrawer.md
0xiamflux Sep 3, 2025
333e3c1
chore: fix from reviews
0xiamflux Sep 3, 2025
1f7f7c8
feat: update mermaid
0xiamflux Sep 3, 2025
f69e097
refactor: update outdated predeploys
0xiamflux Sep 3, 2025
bbc9401
refactor: replace value for amount for ShareInfo
0xiamflux Sep 3, 2025
32fbccd
chore: linting
0xiamflux Sep 3, 2025
25df03d
chore: elaborate opt-in nature of feesplitter
0xiamflux Sep 3, 2025
d3de6b8
Update specs/protocol/jovian/superchain-revshares-calc.md
0xiamflux Sep 3, 2025
01ca566
Update specs/protocol/jovian/fee-vault-initializer.md
0xiamflux Sep 3, 2025
3cc87d6
Update specs/protocol/jovian/fee-vault-initializer.md
0xiamflux Sep 3, 2025
b2fa8a1
refactor: comply fee vault init to specs format
0xiamflux Sep 4, 2025
b6cc84d
chore: lint
0xiamflux Sep 4, 2025
4495849
fix: replacing incorrect arrays for single ShareInfo array
0xiamflux Sep 4, 2025
f13d136
chore: update references of getRecipientsAndValues for getRecipientsA…
0xiamflux Sep 4, 2025
939335f
chore: remove fee-splitter.md
0xiamflux Sep 4, 2025
14a19aa
chore: punctuation and clarification clause
0xiamflux Sep 4, 2025
1837941
chore: rename RevenueShareRecipient -> Recipient
0xiamflux Sep 4, 2025
b6c999d
refactor: add brief explainer on the initializer behavior
0xiamflux Sep 4, 2025
d27d87f
chore: add invariant for fee vault setters
0xiamflux Sep 4, 2025
1fa8df4
chore: clarify share calculator
0xiamflux Sep 4, 2025
5af3468
feat: add withdraw invariant
0xiamflux Sep 4, 2025
d2508d8
chore: remove invariants on predeploys.md
0xiamflux Sep 4, 2025
8f2a0f8
chore: elaborate conditions under l1withdrawer performs L1 withdrawal
0xiamflux Sep 4, 2025
ceeae2e
refactor: removes ShareInfo struct definition, elaborates invariant o…
0xiamflux Sep 4, 2025
a8c5e55
refactor: update FeeSplitter predeploy address
0xiamflux Sep 4, 2025
1f6f787
chore: proof reading
0xiamflux Sep 4, 2025
33949a0
Update specs/protocol/jovian/predeploys.md
0xiamflux Sep 4, 2025
d65aafb
feat: add reference to ISharesCalculator
0xiamflux Sep 5, 2025
e656a0a
refactor: remove withdrawal data references
0xiamflux Sep 15, 2025
0b5ee83
chore: remove upgrade path from fee vault init spec
0xiamflux Sep 16, 2025
972b5a7
feat: add `FeesDepositor` spec (#61)
0xiamflux Sep 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 0 additions & 140 deletions specs/protocol/jovian/fee-splitter.md

This file was deleted.

129 changes: 36 additions & 93 deletions specs/protocol/jovian/fee-vault-initializer.md
Original file line number Diff line number Diff line change
@@ -1,114 +1,57 @@
# FeeVaultInitializer

<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->

- [FeeVaultInitializer](#feevaultinitializer)
- [Constructor](#constructor)
- [Events](#events)
- [Upgrade Path](#upgrade-path)
- [Alternatives Considered](#alternatives-considered)
- [Pros & Cons Of Both Approaches](#pros--cons-of-both-approaches)
- [Getter-driven Approach (Current)](#getter-driven-approach-current)
- [Initializer-driven Approach](#initializer-driven-approach)
- [Considerations](#considerations)
- [Summary](#summary)
- [Functions](#functions)
- [`constructor`](#constructor)
- [Events](#events)
- [`FeeVaultDeployed`](#feevaultdeployed)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->

# FeeVaultInitializer

This contract serves as a runbook for deploying new vault implementations while preserving the current vault configuration. It is intended to be used in a NUT series context to upgrade the vaults to the new implementation once they are deployed.
## Summary

### Constructor
A contract responsible for deploying new vault implementations while preserving the current vault configuration.
It is intended to be used in a Network Upgrade Transaction (NUT) series context to upgrade each vault to the
new implementation once deployed.

On deployment, the constructor will:
## Functions

- Read and grab the current values for `recipient()`, `withdrawalNetwork()`, and `minWithdrawalAmount()` from each live vault (`SequencerFeeVault`, `L1FeeVault`, `BaseFeeVault`, `OperatorFeeVault`). Use a `try/catch` block to handle the case where the call fails because the vault is a legacy one, and query for the `RECIPIENT()` and `MIN_WITHDRAWAL_AMOUNT()` immutable values instead.
- Deploy a new implementation for each vault, passing the grabbed values per vault as constructor immutables, and also passing `L2` as the `WITHDRAWAL_NETWORK` constructor immutable.
- Emit a single event containing the four deployed implementation addresses
### `constructor`

Invariants:
When the initializer is deployed, it will:

- It MUST deploy implementations whose constructor immutables match the current configuration values.
- It MUST emit an event with the deployed implementation addresses.

### Events

Single event with all deployed implementation addresses:
- Read and retrieve the current values for `recipient()`, `withdrawalNetwork()`, and `minWithdrawalAmount()`
from each live vault (`SequencerFeeVault`, `L1FeeVault`, `BaseFeeVault`, `OperatorFeeVault`).
- Handle legacy vaults that may not have the `WITHDRAWAL_NETWORK` function by using a low-level staticcall and
assigning the default value of `WithdrawalNetwork.L2` when the configuration cannot be read.
- Deploy a new implementation for each vault, passing the retrieved values per vault as constructor
immutables, and passing `L2` as the `WITHDRAWAL_NETWORK` constructor immutable in case a legacy vault is
being upgraded.
- Emit the `FeeVaultDeployed` event for each newly deployed vault.

```solidity
event FeeVaultImplementationsDeployed(
address sequencerFeeVaultImplementation,
address l1FeeVaultImplementation,
address baseFeeVaultImplementation,
address operatorFeeVaultImplementation
);
constructor()
```

## Upgrade Path

These are the steps to deploy and activate new implementations through NUTs:
- MUST deploy implementations whose constructor immutables match the current configuration values.
- For legacy vaults, MUST assign a default `WithdrawalNetwork.L2` value to the network configuration on the new implementation.
- For each vault, MUST emit the `FeeVaultDeployed` event.

0. Precalculate:
a. `FeeVaultInitializer` address to be deployed
b. each vault implementation address to be deployed by the `FeeVaultInitializer` address
1. Deploy the `FeeVaultInitializer`. Its constructor deploys the new implementations, keeping the current configuration values.
2. For each vault proxy, call `upgradeTo` (or `upgradeToAndCall` if local policy requires) from the admin or via the `address(0)` NUT flow to point the proxy at the emitted implementation addresses (4 different NUTs).
## Events

Execute in order so that deployments exist before proxies are upgraded.
### `FeeVaultDeployed`

## Alternatives Considered

**Initializer-driven storage init after upgrade**: Stores current configs as immutables on a `FeeVaultInitializer` and grant it permission to call `initialize()` on each vault after proxies are upgraded to the new implementation.

- Flow:
1. Deploy `FeeVaultInitializer`. Its constructor reads the current config from the live vaults and stores those values as immutables.
2. Deploy a new implementation for each vault, passing the initializer’s address as the allowed initializer target (pre-calculated).
3. From address(0) (NUT) or via admin, call `upgradeTo` for each vault proxy to point to the new implementation.
4. Call `FeeVaultInitializer.initializeVaults()` so it pushes the stored config into each vault via `initialize()`.
Emitted when a new fee vault implementation has been deployed.

```solidity
address public immutable FEE_VAULT_INITIALIZER;
Config public config;

constructor(address _feeVaultInitializer) {
FEE_VAULT_INITIALIZER = _feeVaultInitializer;
}

function initialize(Config _config) external {
if (msg.sender != FEE_VAULT_INITIALIZER) revert NotAllowed();
config = _config;
}
event FeeVaultDeployed(
string indexed vaultType,
address indexed newImplementation,
address recipient,
WithdrawalNetwork network,
uint256 minWithdrawalAmount
)
```

## Pros & Cons Of Both Approaches

### Getter-driven Approach (Current)

**Pros**

- Simple and straightforward approach to deploy the new vault implementations while keeping the current configuration values.
- Fewer NUTs are needed on the series, making this process simpler.
- No need to give any permission to the `FeeVaultInitializer` contract to call `initialize()` on the vaults.
- Less code to maintain

**Cons**

- It requires a change to `FeeVaults` getter functions, which is not very clean, and also incurs a minor added gas cost while reading the values.

### Initializer-driven Approach

**Pros**

- No need to change `FeeVaults` getter functions.
- No added gas cost while reading the values.

**Cons**

- More NUTs are needed on the series, making this process more complex.
- Requires permission to the `FeeVaultInitializer` contract to call `initialize()` on the vaults.
- More code to maintain: Vaults need to implement the `initialize()` function.

With these pros and cons in mind, we opted for the getter-driven approach since we find it simpler, and no permissions nor `initialize()` function are needed to be implemented on the vaults.

### Considerations

For chains opting into `FeeSplitter`, ensure `WITHDRAWAL_NETWORK = L2` and `RECIPIENT = FeeSplitter` after upgrade (via admin setters).
Loading