forked from ethereum-optimism/superchain-ops
-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add rev share upgrader #53
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
69 commits
Select commit
Hold shift + click to select a range
8957282
feat: add rev share upgrader
0xChin f081a19
feat: add upgrade function
0xChin d0f52d6
chore: remove wrong checks
0xChin 7910b0c
feat: add combined path
0xChin bb918b0
refactor: remove no sense struct
0xChin dcd596d
chore: fix comments
0xChin 6f11b32
feat: add templates with example configs
0xChin 1c7c070
chore: descope
0xChin 29b0cc7
refactor: move interfaces to single files
0xChin 64a4838
docs: natspec
0xChin f628e32
refactor: use custom errors
0xChin 90ffdea
chore: improve comments
0xChin 495ecb1
fix: reorder contracts deployment
0xChin 96acf0b
chore: improve function naming
0xChin 4650303
chore: improve function naming
0xChin 80d93a1
chore: improve comments
0xChin 4fb8591
chore(descope): remove upgradeContracts function
0xChin 8378bb9
chore(descope): hardcode saltSeed
0xChin 2750349
chore(descope): hardcode same salt for all contracts
0xChin 21e825a
feat: allow multiple chain upgrades at once goooood
0xChin 30d8d7d
test: add integration test
0xChin 77965ec
fix: colission due to default salt
0xChin ee1d78b
test: add integration test with delegatecall
0xChin 1524459
perf: remove default variable init
0xChin 528e60b
refactor: remove magic number usage
0xChin e8b4b3b
refactor: use helper functions for portal deposits
0xChin 6662636
refactor: move main case to beginning
0xChin dd34193
refactor: improve var naming
0xChin 5fe8f70
chore: add zero length array check
0xChin 4200f56
refactor: add deploy periphery contract
0xChin 34855bb
refactor: invert calls order
0xChin 111c49a
refactor: reduce interface complexity
0xChin a76d1f0
feat: add revshare template and integration tests
0xChin 88a9d39
refactor: remove fixture file
0xChin 8c3599b
refactor: cleanup
0xChin 93542ad
chore: improve naming
0xChin 03d4cfa
feat: add portal check
0xChin d61043c
chore: remove unused task
0xChin 582d73b
refactor: use interfaces
0xChin acaaf16
chore: improve readability
0xChin d69bf10
chore: fix contract name
0xChin a5f713f
feat: fix contract naming, add regression tests
0xChin 1e674a4
test: add todo regression
0xChin 4c3e55e
test: make integration tests with different configs for both chains
0xChin 3079543
chore: remove regression tests until upgrader is deployed
0xChin 616fb00
chore: remove deprecated tasks and tests
0xChin 0f59f65
chore: remove deprecated test
0xChin 6a015e9
refactor: use common library for all revshare configs/data/creation c…
0xChin 1dad4b4
chore: remove default value initalization
0xChin bd5a0fb
refactor: rename RevShareManager -> RevShareUpgrader
0xChin 585bee0
refactor: single param for calling upgrader contract
0xChin d9a62b8
refactor: remove portals array from template config
0xChin c02d294
refactor: remove unnecessary encoding and decoding
0xChin 2d7e5af
refactor: remove unnecessary for loop
0xChin 4baf448
fix: broken validation
0xChin ef6f900
refactor: improve var naming
0xChin 7c143e0
refactor: improve var naming
0xChin 617a779
feat: improve template validations
0xChin 491dfc7
refactor: remove assembly usage
0xChin 6e57f0c
feat: use same impl for BaseFeeVault and L1FeeVault
0xChin a932638
chore: improve comments
0xChin ec1d538
refactor: use for loop for vaults deployment
0xChin e83ae80
feat: add upgrader unit tests (#55)
0xDiscotech 99a3551
chore: add comment
0xDiscotech b532af6
feat: add check and interface (#56)
0xDiscotech ad2dc9d
chore: fix gas costs
0xChin f2d108b
chore: undo wrong changes
0xChin 1bdc236
chore: update gas limits (#57)
0xChin ce3936c
feat: add chain processed event (#58)
0xDiscotech File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,302 @@ | ||
| // SPDX-License-Identifier: MIT | ||
| pragma solidity 0.8.15; | ||
|
|
||
| import {RevShareLibrary} from "src/libraries/RevShareLibrary.sol"; | ||
| import {Utils} from "src/libraries/Utils.sol"; | ||
|
|
||
| // Interfaces | ||
| import {IOptimismPortal2} from "@eth-optimism-bedrock/interfaces/L1/IOptimismPortal2.sol"; | ||
| import {IProxyAdmin} from "@eth-optimism-bedrock/interfaces/universal/IProxyAdmin.sol"; | ||
| import {ICreate2Deployer} from "src/interfaces/ICreate2Deployer.sol"; | ||
| import {IFeeSplitter} from "src/interfaces/IFeeSplitter.sol"; | ||
| import {IFeeVault} from "src/interfaces/IFeeVault.sol"; | ||
|
|
||
| /// @title RevShareContractsUpgrader | ||
| /// @notice Upgrader contract that manages RevShare deployments and configuration via delegatecall. | ||
| /// @dev Supports two operations: | ||
| /// 1. setupRevShare() - Setup revenue sharing on already-upgraded contracts | ||
| /// 2. upgradeAndSetupRevShare() - Combined upgrade + setup (most efficient) | ||
| /// All operations use the default calculator (L1Withdrawer + SuperchainRevenueShareCalculator). | ||
| contract RevShareContractsUpgrader { | ||
| /// @notice Base salt seed for CREATE2 deployments | ||
| string private constant SALT_SEED = "RevShare"; | ||
|
|
||
| /// @notice Thrown when portal address is zero | ||
| error PortalCannotBeZeroAddress(); | ||
|
|
||
| /// @notice Thrown when L1Withdrawer recipient is zero address | ||
| error L1WithdrawerRecipientCannotBeZeroAddress(); | ||
|
|
||
| /// @notice Thrown when chain fees recipient is zero address | ||
| error ChainFeesRecipientCannotBeZeroAddress(); | ||
|
|
||
| /// @notice Thrown when gas limit is zero | ||
| error GasLimitCannotBeZero(); | ||
|
|
||
| /// @notice Thrown when array is empty | ||
| error EmptyArray(); | ||
|
|
||
| /// @notice Emitted when a chain's RevShare setup deposits are completed | ||
| /// @param portal The portal address for the chain | ||
| /// @param chainIndex The index of the chain in the configs array | ||
| event ChainProcessed(address portal, uint256 chainIndex); | ||
|
|
||
| /// @notice Struct for L1Withdrawer configuration. | ||
| /// @param minWithdrawalAmount Minimum withdrawal amount | ||
| /// @param recipient Recipient address for withdrawals | ||
| /// @param gasLimit Gas limit for L1 withdrawals | ||
| struct L1WithdrawerConfig { | ||
| uint256 minWithdrawalAmount; | ||
| address recipient; | ||
| uint32 gasLimit; | ||
| } | ||
|
|
||
| /// @notice Struct for RevShare setup configuration per chain. | ||
| /// @param portal OptimismPortal2 address for the target L2 | ||
| /// @param l1WithdrawerConfig L1Withdrawer configuration | ||
| /// @param chainFeesRecipient Chain fees recipient address for the calculator | ||
| struct RevShareConfig { | ||
| address portal; | ||
| L1WithdrawerConfig l1WithdrawerConfig; | ||
| address chainFeesRecipient; | ||
| } | ||
|
|
||
| /// @notice Upgrades vault and splitter contracts and sets up revenue sharing in one transaction for multiple chains. | ||
| /// This is the most efficient path as vaults are initialized with RevShare config from the start. | ||
| /// @param _configs Array of RevShare configuration structs, one per chain. | ||
| function upgradeAndSetupRevShare(RevShareConfig[] calldata _configs) external { | ||
| if (_configs.length == 0) revert EmptyArray(); | ||
|
|
||
| for (uint256 i; i < _configs.length; i++) { | ||
| RevShareConfig calldata config = _configs[i]; | ||
| if (config.portal == address(0)) revert PortalCannotBeZeroAddress(); | ||
| if (config.l1WithdrawerConfig.recipient == address(0)) revert L1WithdrawerRecipientCannotBeZeroAddress(); | ||
| if (config.chainFeesRecipient == address(0)) revert ChainFeesRecipientCannotBeZeroAddress(); | ||
| if (config.l1WithdrawerConfig.gasLimit == 0) revert GasLimitCannotBeZero(); | ||
|
|
||
| // Deploy L1Withdrawer and SuperchainRevenueShareCalculator | ||
| address precalculatedCalculator = | ||
| _deployRevSharePeriphery(config.portal, config.l1WithdrawerConfig, config.chainFeesRecipient); | ||
|
|
||
| // Upgrade fee splitter and initialize with calculator FIRST | ||
| // This prevents the edge case where fees could be sent to an uninitialized FeeSplitter | ||
| bytes32 feeSplitterSalt = _getSalt("FeeSplitter"); | ||
| address feeSplitterImpl = Utils.getCreate2Address( | ||
| feeSplitterSalt, RevShareLibrary.feeSplitterCreationCode, RevShareLibrary.CREATE2_DEPLOYER | ||
| ); | ||
| _depositCreate2( | ||
| config.portal, | ||
| RevShareLibrary.FEE_SPLITTER_DEPLOYMENT_GAS_LIMIT, | ||
| feeSplitterSalt, | ||
| RevShareLibrary.feeSplitterCreationCode | ||
| ); | ||
| _depositCall( | ||
| config.portal, | ||
| address(RevShareLibrary.PROXY_ADMIN), | ||
| RevShareLibrary.UPGRADE_GAS_LIMIT, | ||
| abi.encodeCall( | ||
| IProxyAdmin.upgradeAndCall, | ||
| ( | ||
| payable(RevShareLibrary.FEE_SPLITTER), | ||
| feeSplitterImpl, | ||
| abi.encodeCall(IFeeSplitter.initialize, (precalculatedCalculator)) | ||
| ) | ||
| ) | ||
| ); | ||
|
|
||
| // Upgrade all 4 vaults with RevShare configuration (recipient=FeeSplitter, minWithdrawal=0, network=L2) | ||
| _upgradeVaultsWithRevShareConfig(config.portal); | ||
|
|
||
| emit ChainProcessed(config.portal, i); | ||
| } | ||
| } | ||
|
|
||
| /// @notice Enables revenue sharing after vaults have been upgraded and `FeeSplitter` initialized. | ||
| /// Deploys L1Withdrawer and calculator, then configures vaults and splitter for multiple chains. | ||
| /// @param _configs Array of RevShare configuration structs, one per chain. | ||
| function setupRevShare(RevShareConfig[] calldata _configs) external { | ||
| if (_configs.length == 0) revert EmptyArray(); | ||
|
|
||
| for (uint256 i; i < _configs.length; i++) { | ||
| RevShareConfig calldata config = _configs[i]; | ||
| if (config.portal == address(0)) revert PortalCannotBeZeroAddress(); | ||
| if (config.l1WithdrawerConfig.recipient == address(0)) revert L1WithdrawerRecipientCannotBeZeroAddress(); | ||
| if (config.chainFeesRecipient == address(0)) revert ChainFeesRecipientCannotBeZeroAddress(); | ||
| if (config.l1WithdrawerConfig.gasLimit == 0) revert GasLimitCannotBeZero(); | ||
|
|
||
| // Deploy L1Withdrawer and SuperchainRevenueShareCalculator | ||
| address calculator = | ||
| _deployRevSharePeriphery(config.portal, config.l1WithdrawerConfig, config.chainFeesRecipient); | ||
|
|
||
| // Set calculator on fee splitter | ||
| _depositCall( | ||
| config.portal, | ||
| RevShareLibrary.FEE_SPLITTER, | ||
| RevShareLibrary.SETTERS_GAS_LIMIT, | ||
| abi.encodeCall(IFeeSplitter.setSharesCalculator, (calculator)) | ||
| ); | ||
|
|
||
| // Configure all 4 vaults for revenue sharing | ||
| _configureVaultsForRevShare(config.portal); | ||
|
|
||
| emit ChainProcessed(config.portal, i); | ||
| } | ||
| } | ||
|
|
||
| /// @notice Deploys L1Withdrawer and SuperchainRevenueShareCalculator to L2. | ||
| /// @param _portal The OptimismPortal2 address for the target L2 | ||
| /// @param _l1WithdrawerConfig L1Withdrawer configuration | ||
| /// @param _chainFeesRecipient Chain fees recipient address | ||
| /// @return calculator The deployed calculator address | ||
| function _deployRevSharePeriphery( | ||
| address _portal, | ||
| L1WithdrawerConfig calldata _l1WithdrawerConfig, | ||
| address _chainFeesRecipient | ||
| ) private returns (address calculator) { | ||
| // Deploy L1Withdrawer | ||
| bytes memory l1WithdrawerInitCode = bytes.concat( | ||
| RevShareLibrary.l1WithdrawerCreationCode, | ||
| abi.encode( | ||
| _l1WithdrawerConfig.minWithdrawalAmount, _l1WithdrawerConfig.recipient, _l1WithdrawerConfig.gasLimit | ||
| ) | ||
| ); | ||
| bytes32 l1WithdrawerSalt = _getSalt("L1Withdrawer"); | ||
| address precalculatedL1Withdrawer = | ||
| Utils.getCreate2Address(l1WithdrawerSalt, l1WithdrawerInitCode, RevShareLibrary.CREATE2_DEPLOYER); | ||
| _depositCreate2( | ||
| _portal, RevShareLibrary.L1_WITHDRAWER_DEPLOYMENT_GAS_LIMIT, l1WithdrawerSalt, l1WithdrawerInitCode | ||
| ); | ||
|
|
||
| // Deploy SuperchainRevenueShareCalculator | ||
| bytes memory calculatorInitCode = bytes.concat( | ||
| RevShareLibrary.scRevShareCalculatorCreationCode, abi.encode(precalculatedL1Withdrawer, _chainFeesRecipient) | ||
| ); | ||
| bytes32 calculatorSalt = _getSalt("SCRevShareCalculator"); | ||
| calculator = Utils.getCreate2Address(calculatorSalt, calculatorInitCode, RevShareLibrary.CREATE2_DEPLOYER); | ||
| _depositCreate2( | ||
| _portal, RevShareLibrary.SC_REV_SHARE_CALCULATOR_DEPLOYMENT_GAS_LIMIT, calculatorSalt, calculatorInitCode | ||
| ); | ||
| } | ||
|
|
||
| /// @notice Configures all 4 vaults for revenue sharing (recipient=FeeSplitter, minWithdrawal=0, network=L2). | ||
| /// @param _portal The OptimismPortal2 address for the target L2 | ||
| function _configureVaultsForRevShare(address _portal) private { | ||
| address[4] memory vaults = [ | ||
| RevShareLibrary.OPERATOR_FEE_VAULT, | ||
| RevShareLibrary.SEQUENCER_FEE_WALLET, | ||
| RevShareLibrary.BASE_FEE_VAULT, | ||
| RevShareLibrary.L1_FEE_VAULT | ||
| ]; | ||
|
|
||
| for (uint256 i; i < vaults.length; i++) { | ||
| _depositCall( | ||
| _portal, | ||
| vaults[i], | ||
| RevShareLibrary.SETTERS_GAS_LIMIT, | ||
| abi.encodeCall(IFeeVault.setRecipient, (RevShareLibrary.FEE_SPLITTER)) | ||
| ); | ||
| _depositCall( | ||
| _portal, | ||
| vaults[i], | ||
| RevShareLibrary.SETTERS_GAS_LIMIT, | ||
| abi.encodeCall(IFeeVault.setMinWithdrawalAmount, (0)) | ||
| ); | ||
| _depositCall( | ||
| _portal, | ||
| vaults[i], | ||
| RevShareLibrary.SETTERS_GAS_LIMIT, | ||
| abi.encodeCall(IFeeVault.setWithdrawalNetwork, (IFeeVault.WithdrawalNetwork.L2)) | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| /// @notice Upgrades all 4 vaults with RevShare configuration (recipient=FeeSplitter, minWithdrawal=0, network=L2). | ||
| /// Deploys only 3 implementations: OperatorFeeVault, SequencerFeeVault, and the same FeeVault implementation is used for both BaseFeeVault and L1FeeVault (we use the same one for both to avoid making the deployment size bigger). | ||
| /// @param _portal The OptimismPortal2 address for the target L2 | ||
| function _upgradeVaultsWithRevShareConfig(address _portal) private { | ||
| address[4] memory vaultProxies = [ | ||
| RevShareLibrary.OPERATOR_FEE_VAULT, | ||
| RevShareLibrary.SEQUENCER_FEE_WALLET, | ||
| RevShareLibrary.BASE_FEE_VAULT, | ||
| RevShareLibrary.L1_FEE_VAULT | ||
| ]; | ||
| bytes[4] memory creationCodes = [ | ||
| RevShareLibrary.operatorFeeVaultCreationCode, | ||
| RevShareLibrary.sequencerFeeVaultCreationCode, | ||
| RevShareLibrary.defaultFeeVaultCreationCode, | ||
| RevShareLibrary.defaultFeeVaultCreationCode | ||
| ]; | ||
| string[4] memory vaultNames = ["OperatorFeeVault", "SequencerFeeVault", "BaseFeeVault", "L1FeeVault"]; | ||
|
|
||
| address defaultImpl; | ||
| for (uint256 i; i < vaultProxies.length; i++) { | ||
| bytes32 salt = _getSalt(vaultNames[i]); | ||
| address impl; | ||
|
|
||
| // Check if this is the BaseFeeVault or L1FeeVault (both use default implementation) | ||
| bool isBaseFeeVault = keccak256(bytes(vaultNames[i])) == keccak256(bytes("BaseFeeVault")); | ||
| bool isL1FeeVault = keccak256(bytes(vaultNames[i])) == keccak256(bytes("L1FeeVault")); | ||
|
|
||
| if (isBaseFeeVault) { | ||
| // Deploy default implementation for BaseFeeVault | ||
| impl = Utils.getCreate2Address(salt, creationCodes[i], RevShareLibrary.CREATE2_DEPLOYER); | ||
| defaultImpl = impl; | ||
| _depositCreate2(_portal, RevShareLibrary.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, salt, creationCodes[i]); | ||
| } else if (isL1FeeVault) { | ||
| // Reuse the default implementation for L1FeeVault | ||
| impl = defaultImpl; | ||
| } else { | ||
| // Deploy specific implementations for OperatorFeeVault and SequencerFeeVault | ||
| impl = Utils.getCreate2Address(salt, creationCodes[i], RevShareLibrary.CREATE2_DEPLOYER); | ||
| _depositCreate2(_portal, RevShareLibrary.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, salt, creationCodes[i]); | ||
| } | ||
|
|
||
| _depositCall( | ||
| _portal, | ||
| address(RevShareLibrary.PROXY_ADMIN), | ||
| RevShareLibrary.UPGRADE_GAS_LIMIT, | ||
| abi.encodeCall( | ||
| IProxyAdmin.upgradeAndCall, | ||
| ( | ||
| payable(vaultProxies[i]), | ||
| impl, | ||
| abi.encodeCall( | ||
| IFeeVault.initialize, (RevShareLibrary.FEE_SPLITTER, 0, IFeeVault.WithdrawalNetwork.L2) | ||
| ) | ||
| ) | ||
| ) | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| /// @notice Helper for CREATE2 contract deployments via depositTransaction. | ||
| /// @param _portal The OptimismPortal2 address | ||
| /// @param _gasLimit Gas limit for the transaction | ||
| /// @param _salt CREATE2 salt | ||
| /// @param _initCode Contract creation code with constructor args | ||
| function _depositCreate2(address _portal, uint64 _gasLimit, bytes32 _salt, bytes memory _initCode) private { | ||
| IOptimismPortal2(payable(_portal)).depositTransaction( | ||
| address(RevShareLibrary.CREATE2_DEPLOYER), | ||
| 0, | ||
| _gasLimit, | ||
| false, | ||
| abi.encodeCall(ICreate2Deployer.deploy, (0, _salt, _initCode)) | ||
| ); | ||
| } | ||
|
|
||
| /// @notice Helper for regular function calls via depositTransaction. | ||
| /// @param _portal The OptimismPortal2 address | ||
| /// @param _target Target contract address | ||
| /// @param _gasLimit Gas limit for the transaction | ||
| /// @param _data Encoded function call data | ||
| function _depositCall(address _portal, address _target, uint64 _gasLimit, bytes memory _data) private { | ||
| IOptimismPortal2(payable(_portal)).depositTransaction(_target, 0, _gasLimit, false, _data); | ||
| } | ||
|
|
||
| /// @notice Generates a unique salt for CREATE2 deployments based on the contract suffix. | ||
| /// @param _suffix The suffix to append to the base salt seed | ||
| /// @return The generated salt as bytes32 | ||
| function _getSalt(string memory _suffix) private pure returns (bytes32) { | ||
| return keccak256(abi.encodePacked(SALT_SEED, ":", _suffix)); | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| // SPDX-License-Identifier: MIT | ||
| pragma solidity 0.8.15; | ||
|
|
||
| /// @notice Interface of the Create2 Preinstall in L2. | ||
| interface ICreate2Deployer { | ||
| function deploy(uint256 _value, bytes32 _salt, bytes memory _code) external; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| // SPDX-License-Identifier: MIT | ||
| pragma solidity 0.8.15; | ||
|
|
||
| /// @notice Interface for the FeeSplitter in L2. | ||
| interface IFeeSplitter { | ||
| function initialize(address _sharesCalculator) external; | ||
| function sharesCalculator() external view returns (address); | ||
| function setSharesCalculator(address _calculator) external; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| // SPDX-License-Identifier: MIT | ||
| pragma solidity 0.8.15; | ||
|
|
||
| interface IFeeVault { | ||
| enum WithdrawalNetwork { | ||
| L1, | ||
| L2 | ||
| } | ||
|
|
||
| function initialize(address _recipient, uint256 _minWithdrawalAmount, WithdrawalNetwork _withdrawalNetwork) external; | ||
|
|
||
| function RECIPIENT() external view returns (address); | ||
| function MIN_WITHDRAWAL_AMOUNT() external view returns (uint256); | ||
| function WITHDRAWAL_NETWORK() external view returns (WithdrawalNetwork); | ||
| function minWithdrawalAmount() external view returns (uint256); | ||
| function recipient() external view returns (address); | ||
| function withdrawalNetwork() external view returns (WithdrawalNetwork); | ||
|
|
||
| function setRecipient(address _recipient) external; | ||
| function setMinWithdrawalAmount(uint256 _minWithdrawalAmount) external; | ||
| function setWithdrawalNetwork(WithdrawalNetwork _withdrawalNetwork) external; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| // SPDX-License-Identifier: MIT | ||
| pragma solidity 0.8.15; | ||
|
|
||
| interface IL1Withdrawer { | ||
| function minWithdrawalAmount() external view returns (uint256); | ||
| function recipient() external view returns (address); | ||
| function withdrawalGasLimit() external view returns (uint32); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| // SPDX-License-Identifier: MIT | ||
| pragma solidity ^0.8.0; | ||
|
|
||
| interface IRevShareContractsUpgrader { | ||
| error PortalCannotBeZeroAddress(); | ||
| error L1WithdrawerRecipientCannotBeZeroAddress(); | ||
| error ChainFeesRecipientCannotBeZeroAddress(); | ||
| error GasLimitCannotBeZero(); | ||
| error EmptyArray(); | ||
|
|
||
| event ChainProcessed(address portal, uint256 chainIndex); | ||
|
|
||
| struct L1WithdrawerConfig { | ||
| uint256 minWithdrawalAmount; | ||
| address recipient; | ||
| uint32 gasLimit; | ||
| } | ||
|
|
||
| struct RevShareConfig { | ||
| address portal; | ||
| L1WithdrawerConfig l1WithdrawerConfig; | ||
| address chainFeesRecipient; | ||
| } | ||
|
|
||
| function upgradeAndSetupRevShare(RevShareConfig[] calldata _configs) external; | ||
| function setupRevShare(RevShareConfig[] calldata _configs) external; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| // SPDX-License-Identifier: MIT | ||
| pragma solidity 0.8.15; | ||
|
|
||
| interface ISuperchainRevSharesCalculator { | ||
| function shareRecipient() external view returns (address payable); | ||
| function remainderRecipient() external view returns (address payable); | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The readibility here got a bit worse because we decided to only deploy one implementation
FeeVaultfor bothBaseFeeVaultandL1FeeVaultgiven they use the exact same bytecode.On the previous way, the loop was way cleaner but it required an extra deployment, something that is not trivial given that the accumulation of deposits on the block are expensive in terms on gas, and we have a limit there (usually 20m gas).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Curious about wdyt about this @funkornaut001 @0xng
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It makes sense to me as is. Previously, with the four deployments, were you approaching the block gas limit?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We were deploying four vaults, one per each, even though
BaseFeeVaultandL1FeeVaultshare the same oneThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's ok, but it's incohesive. Not the code itself, but the practice. I find two things off about this approach:
BaseFeeVault. This is awkward for the "L1FeeVault" in terms of following the practices. There's no real reason why it uses the salt of that vault over the other.Does any of these two points matter in practice? Not really. Point 2 could be an "issue" if this contract was meant to be reusable as the contracts evolved, because the bytecodes could technically differ at some point. But that's not the case, so fair game.