From 895728279967d79649604d08674d78cf3c0e7312 Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Tue, 4 Nov 2025 12:50:46 -0300 Subject: [PATCH 01/69] feat: add rev share upgrader --- src/RevShareContractsUpgrader.sol | 235 ++++++++++++++++++++++++++++++ 1 file changed, 235 insertions(+) create mode 100644 src/RevShareContractsUpgrader.sol diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol new file mode 100644 index 0000000000..de3cc5f7cf --- /dev/null +++ b/src/RevShareContractsUpgrader.sol @@ -0,0 +1,235 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import {RevSharePredeploys} from "src/libraries/RevSharePredeploys.sol"; +import {RevShareCodeRepo} from "src/libraries/RevShareCodeRepo.sol"; +import {RevShareGasLimits} from "src/libraries/RevShareGasLimits.sol"; +import {Utils} from "src/libraries/Utils.sol"; + +/// @notice Interface for the OptimismPortal2 in L1. +interface IOptimismPortal2 { + function depositTransaction(address _to, uint256 _value, uint64 _gasLimit, bool _isCreation, bytes memory _data) + external + payable; +} + +/// @notice Interface of the Create2 Preinstall in L2. +interface ICreate2Deployer { + function deploy(uint256 _value, bytes32 _salt, bytes memory _code) external; +} + +/// @notice Interface for ProxyAdmin. +interface IProxyAdmin { + function upgradeAndCall(address payable _proxy, address _implementation, bytes memory _data) external; +} + +/// @notice Interface for the FeeSplitter in L2. +interface IFeeSplitter { + function initialize(address _sharesCalculator) external; +} + +/// @notice Interface for the vaults in L2. +interface IFeeVault { + function initialize(address _recipient, uint256 _minWithdrawalAmount, uint8 _withdrawalNetwork) external; +} + +/// @title RevShareContractsManager +/// @notice Upgrader contract that deploys fee vaults and fee splitter via delegatecall. +/// The fee splitter is initialized with address(0) calculator (disabled state). +contract RevShareContractsManager is RevSharePredeploys { + /// @notice The address of the OptimismPortal2 through which we make deposit transactions. + address public immutable portal; + + /// @notice The salt seed to be used for the L2 deployments. + string public saltSeed; + + /// @notice The withdrawal network configuration for the fee vaults. + uint8 public constant FEE_VAULT_WITHDRAWAL_NETWORK = 1; + + /// @notice The minimum withdrawal amount configuration for the fee vaults. + uint256 public constant FEE_VAULT_MIN_WITHDRAWAL_AMOUNT = 0; + + /// @notice Constructor sets the portal and saltSeed. + /// @param _portal The address of the OptimismPortal2. + /// @param _saltSeed The salt seed for CREATE2 deployments. + constructor(address _portal, string memory _saltSeed) { + require(_portal != address(0), "portal must be set"); + require(bytes(_saltSeed).length != 0, "saltSeed must be set"); + + portal = _portal; + saltSeed = _saltSeed; + } + + /// @notice Deploys fee vaults and fee splitter to L2 via OptimismPortal2. + /// The fee splitter is initialized with address(0) calculator (disabled). + function deployVaultsAndSplitter() external { + _deployFeeVaults(); + _deployFeeSplitter(); + } + + /// @notice Deploys the fee vaults implementation and upgrades the proxies. + function _deployFeeVaults() private { + // Deploy OperatorFeeVault + bytes32 operatorSalt = _getSalt(saltSeed, "OperatorFeeVault"); + bytes memory operatorInitCode = RevShareCodeRepo.operatorFeeVaultCreationCode; + address operatorFeeVaultImpl = + Utils.getCreate2Address(operatorSalt, operatorInitCode, CREATE2_DEPLOYER); + + IOptimismPortal2(payable(portal)).depositTransaction( + address(CREATE2_DEPLOYER), + 0, + RevShareGasLimits.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, + false, + abi.encodeCall(ICreate2Deployer.deploy, (0, operatorSalt, operatorInitCode)) + ); + + IOptimismPortal2(payable(portal)).depositTransaction( + address(PROXY_ADMIN), + 0, + RevShareGasLimits.UPGRADE_GAS_LIMIT, + false, + abi.encodeCall( + IProxyAdmin.upgradeAndCall, + ( + payable(OPERATOR_FEE_VAULT), + operatorFeeVaultImpl, + abi.encodeCall( + IFeeVault.initialize, + (FEE_VAULT_RECIPIENT, FEE_VAULT_MIN_WITHDRAWAL_AMOUNT, FEE_VAULT_WITHDRAWAL_NETWORK) + ) + ) + ) + ); + + // Deploy SequencerFeeVault + bytes32 sequencerSalt = _getSalt(saltSeed, "SequencerFeeVault"); + bytes memory sequencerInitCode = RevShareCodeRepo.sequencerFeeVaultCreationCode; + address sequencerFeeVaultImpl = + Utils.getCreate2Address(sequencerSalt, sequencerInitCode, CREATE2_DEPLOYER); + + IOptimismPortal2(payable(portal)).depositTransaction( + address(CREATE2_DEPLOYER), + 0, + RevShareGasLimits.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, + false, + abi.encodeCall(ICreate2Deployer.deploy, (0, sequencerSalt, sequencerInitCode)) + ); + + IOptimismPortal2(payable(portal)).depositTransaction( + address(PROXY_ADMIN), + 0, + RevShareGasLimits.UPGRADE_GAS_LIMIT, + false, + abi.encodeCall( + IProxyAdmin.upgradeAndCall, + ( + payable(SEQUENCER_FEE_WALLET), + sequencerFeeVaultImpl, + abi.encodeCall( + IFeeVault.initialize, + (FEE_VAULT_RECIPIENT, FEE_VAULT_MIN_WITHDRAWAL_AMOUNT, FEE_VAULT_WITHDRAWAL_NETWORK) + ) + ) + ) + ); + + // Deploy BaseFeeVault + bytes32 baseSalt = _getSalt(saltSeed, "BaseFeeVault"); + bytes memory baseInitCode = RevShareCodeRepo.baseFeeVaultCreationCode; + address baseFeeVaultImpl = Utils.getCreate2Address(baseSalt, baseInitCode, CREATE2_DEPLOYER); + + IOptimismPortal2(payable(portal)).depositTransaction( + address(CREATE2_DEPLOYER), + 0, + RevShareGasLimits.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, + false, + abi.encodeCall(ICreate2Deployer.deploy, (0, baseSalt, baseInitCode)) + ); + + IOptimismPortal2(payable(portal)).depositTransaction( + address(PROXY_ADMIN), + 0, + RevShareGasLimits.UPGRADE_GAS_LIMIT, + false, + abi.encodeCall( + IProxyAdmin.upgradeAndCall, + ( + payable(BASE_FEE_VAULT), + baseFeeVaultImpl, + abi.encodeCall( + IFeeVault.initialize, + (FEE_VAULT_RECIPIENT, FEE_VAULT_MIN_WITHDRAWAL_AMOUNT, FEE_VAULT_WITHDRAWAL_NETWORK) + ) + ) + ) + ); + + // Deploy L1FeeVault + bytes32 l1Salt = _getSalt(saltSeed, "L1FeeVault"); + bytes memory l1InitCode = RevShareCodeRepo.l1FeeVaultCreationCode; + address l1FeeVaultImpl = Utils.getCreate2Address(l1Salt, l1InitCode, CREATE2_DEPLOYER); + + IOptimismPortal2(payable(portal)).depositTransaction( + address(CREATE2_DEPLOYER), + 0, + RevShareGasLimits.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, + false, + abi.encodeCall(ICreate2Deployer.deploy, (0, l1Salt, l1InitCode)) + ); + + IOptimismPortal2(payable(portal)).depositTransaction( + address(PROXY_ADMIN), + 0, + RevShareGasLimits.UPGRADE_GAS_LIMIT, + false, + abi.encodeCall( + IProxyAdmin.upgradeAndCall, + ( + payable(L1_FEE_VAULT), + l1FeeVaultImpl, + abi.encodeCall( + IFeeVault.initialize, + (FEE_VAULT_RECIPIENT, FEE_VAULT_MIN_WITHDRAWAL_AMOUNT, FEE_VAULT_WITHDRAWAL_NETWORK) + ) + ) + ) + ); + } + + /// @notice Deploys the fee splitter implementation using Create2. + function _deployFeeSplitter() private { + bytes32 feeSplitterSalt = _getSalt(saltSeed, "FeeSplitter"); + bytes memory feeSplitterInitCode = RevShareCodeRepo.feeSplitterCreationCode; + address feeSplitterImpl = + Utils.getCreate2Address(feeSplitterSalt, feeSplitterInitCode, CREATE2_DEPLOYER); + + // Deploy FeeSplitter implementation + IOptimismPortal2(payable(portal)).depositTransaction( + address(CREATE2_DEPLOYER), + 0, + RevShareGasLimits.FEE_SPLITTER_DEPLOYMENT_GAS_LIMIT, + false, + abi.encodeCall(ICreate2Deployer.deploy, (0, feeSplitterSalt, feeSplitterInitCode)) + ); + + // Upgrade FeeSplitter proxy and initialize with address(0) calculator (disabled) + IOptimismPortal2(payable(portal)).depositTransaction( + address(PROXY_ADMIN), + 0, + RevShareGasLimits.UPGRADE_GAS_LIMIT, + false, + abi.encodeCall( + IProxyAdmin.upgradeAndCall, + (payable(FEE_SPLITTER), feeSplitterImpl, abi.encodeCall(IFeeSplitter.initialize, (address(0)))) + ) + ); + } + + /// @notice Generates a salt from a prefix and suffix. + /// @param _prefix The prefix for the salt. + /// @param _suffix The suffix for the salt. + /// @return The generated salt. + function _getSalt(string memory _prefix, string memory _suffix) private pure returns (bytes32) { + return keccak256(abi.encodePacked(bytes(_prefix), bytes(":"), bytes(_suffix))); + } +} From f081a19b704a20d7c344372cc8ee2e44ef62e3ab Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Tue, 4 Nov 2025 15:11:00 -0300 Subject: [PATCH 02/69] feat: add upgrade function --- src/RevShareContractsUpgrader.sol | 339 +++++++++++++++++++----------- 1 file changed, 212 insertions(+), 127 deletions(-) diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol index de3cc5f7cf..5ccb786141 100644 --- a/src/RevShareContractsUpgrader.sol +++ b/src/RevShareContractsUpgrader.sol @@ -28,94 +28,153 @@ interface IFeeSplitter { function initialize(address _sharesCalculator) external; } -/// @notice Interface for the vaults in L2. +/// @notice Interface for the vaults in L2 (initialization). interface IFeeVault { function initialize(address _recipient, uint256 _minWithdrawalAmount, uint8 _withdrawalNetwork) external; } +/// @notice Interface for vault setters (RevShare vaults have mutable storage). +interface IFeeVaultSetters { + function setRecipient(address _recipient) external; + function setMinWithdrawalAmount(uint256 _minWithdrawalAmount) external; + function setWithdrawalNetwork(uint8 _withdrawalNetwork) external; +} + +/// @notice Interface for FeeSplitter setter. +interface IFeeSplitterSetter { + function setSharesCalculator(address _calculator) external; +} + /// @title RevShareContractsManager -/// @notice Upgrader contract that deploys fee vaults and fee splitter via delegatecall. -/// The fee splitter is initialized with address(0) calculator (disabled state). +/// @notice Upgrader contract that manages RevShare deployments and configuration via delegatecall. +/// Supports three main operations: +/// 1. Upgrade vault and splitter contracts +/// 2. Setup revenue sharing with default calculator +/// 3. Setup revenue sharing with custom calculator contract RevShareContractsManager is RevSharePredeploys { - /// @notice The address of the OptimismPortal2 through which we make deposit transactions. - address public immutable portal; + /// @notice Struct for vault configuration. + struct VaultConfig { + address proxy; // Vault proxy address + address recipient; // Withdrawal recipient + uint256 minWithdrawal; // Minimum withdrawal amount + uint8 withdrawalNetwork; // Network for withdrawals (0=L1, 1=L2) + } - /// @notice The salt seed to be used for the L2 deployments. - string public saltSeed; + /// @notice Struct for L1Withdrawer configuration. + struct L1WithdrawerConfig { + uint256 minWithdrawalAmount; + address recipient; + uint32 gasLimit; + } - /// @notice The withdrawal network configuration for the fee vaults. - uint8 public constant FEE_VAULT_WITHDRAWAL_NETWORK = 1; + /// @notice Struct for SuperchainRevenueShareCalculator configuration. + struct CalculatorConfig { + address chainFeesRecipient; + } - /// @notice The minimum withdrawal amount configuration for the fee vaults. - uint256 public constant FEE_VAULT_MIN_WITHDRAWAL_AMOUNT = 0; + /// @notice Tracks which portals have been upgraded. + mapping(address => bool) public upgradedPortals; - /// @notice Constructor sets the portal and saltSeed. - /// @param _portal The address of the OptimismPortal2. + /// @notice Upgrades vault and fee splitter contracts. + /// @param _portal The OptimismPortal2 address for the target L2. /// @param _saltSeed The salt seed for CREATE2 deployments. - constructor(address _portal, string memory _saltSeed) { - require(_portal != address(0), "portal must be set"); - require(bytes(_saltSeed).length != 0, "saltSeed must be set"); + /// @param _vaults Array of vault configurations to upgrade. + function upgradeContracts(address _portal, string memory _saltSeed, VaultConfig[] memory _vaults) external { + require(_portal != address(0), "portal cannot be zero address"); + require(bytes(_saltSeed).length != 0, "saltSeed cannot be empty"); + + // Deploy and upgrade each vault + for (uint256 i = 0; i < _vaults.length; i++) { + _upgradeVault(_portal, _saltSeed, _vaults[i]); + } + + // Deploy and upgrade fee splitter with address(0) calculator (disabled) + _deployAndUpgradeFeeSplitter(_portal, _saltSeed); - portal = _portal; - saltSeed = _saltSeed; + // Mark this portal as upgraded + upgradedPortals[_portal] = true; } - /// @notice Deploys fee vaults and fee splitter to L2 via OptimismPortal2. - /// The fee splitter is initialized with address(0) calculator (disabled). - function deployVaultsAndSplitter() external { - _deployFeeVaults(); - _deployFeeSplitter(); + /// @notice Setup revenue sharing with default calculator (deploys L1Withdrawer + Calculator, configures vaults + splitter). + /// @param _portal The OptimismPortal2 address for the target L2. + /// @param _saltSeed The salt seed for CREATE2 deployments. + /// @param _l1Config L1Withdrawer configuration. + /// @param _calcConfig SuperchainRevenueShareCalculator configuration. + function setupRevShareWithDefaultCalculator( + address _portal, + string memory _saltSeed, + L1WithdrawerConfig memory _l1Config, + CalculatorConfig memory _calcConfig + ) external { + require(upgradedPortals[_portal], "Must upgrade contracts first"); + require(_l1Config.recipient != address(0), "L1Withdrawer recipient cannot be zero address"); + require(_calcConfig.chainFeesRecipient != address(0), "Calculator chainFeesRecipient cannot be zero address"); + + // Deploy L1Withdrawer + address l1Withdrawer = _deployL1Withdrawer(_portal, _saltSeed, _l1Config); + + // Deploy SuperchainRevenueShareCalculator + address calculator = _deployCalculator(_portal, _saltSeed, l1Withdrawer, _calcConfig); + + // Configure all 4 vaults for revenue sharing + _configureVaultsForRevShare(_portal); + + // Set calculator on fee splitter + _setFeeSplitterCalculator(_portal, calculator); } - /// @notice Deploys the fee vaults implementation and upgrades the proxies. - function _deployFeeVaults() private { - // Deploy OperatorFeeVault - bytes32 operatorSalt = _getSalt(saltSeed, "OperatorFeeVault"); - bytes memory operatorInitCode = RevShareCodeRepo.operatorFeeVaultCreationCode; - address operatorFeeVaultImpl = - Utils.getCreate2Address(operatorSalt, operatorInitCode, CREATE2_DEPLOYER); + /// @notice Setup revenue sharing with custom calculator (configures vaults + splitter only). + /// @param _portal The OptimismPortal2 address for the target L2. + /// @param _calculator The custom calculator address. + function setupRevShareWithCustomCalculator(address _portal, address _calculator) external { + require(upgradedPortals[_portal], "Must upgrade contracts first"); + require(_calculator != address(0), "Calculator cannot be zero address"); - IOptimismPortal2(payable(portal)).depositTransaction( - address(CREATE2_DEPLOYER), - 0, - RevShareGasLimits.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, - false, - abi.encodeCall(ICreate2Deployer.deploy, (0, operatorSalt, operatorInitCode)) - ); + // Configure all 4 vaults for revenue sharing + _configureVaultsForRevShare(_portal); - IOptimismPortal2(payable(portal)).depositTransaction( - address(PROXY_ADMIN), - 0, - RevShareGasLimits.UPGRADE_GAS_LIMIT, - false, - abi.encodeCall( - IProxyAdmin.upgradeAndCall, - ( - payable(OPERATOR_FEE_VAULT), - operatorFeeVaultImpl, - abi.encodeCall( - IFeeVault.initialize, - (FEE_VAULT_RECIPIENT, FEE_VAULT_MIN_WITHDRAWAL_AMOUNT, FEE_VAULT_WITHDRAWAL_NETWORK) - ) - ) - ) - ); + // Set calculator on fee splitter + _setFeeSplitterCalculator(_portal, _calculator); + } - // Deploy SequencerFeeVault - bytes32 sequencerSalt = _getSalt(saltSeed, "SequencerFeeVault"); - bytes memory sequencerInitCode = RevShareCodeRepo.sequencerFeeVaultCreationCode; - address sequencerFeeVaultImpl = - Utils.getCreate2Address(sequencerSalt, sequencerInitCode, CREATE2_DEPLOYER); + /// @notice Deploys and upgrades a single vault. + function _upgradeVault(address _portal, string memory _saltSeed, VaultConfig memory _config) private { + require(_config.proxy != address(0), "Vault proxy cannot be zero address"); - IOptimismPortal2(payable(portal)).depositTransaction( + // Determine which vault type and get the appropriate creation code + bytes memory creationCode; + string memory vaultName; + + if (_config.proxy == OPERATOR_FEE_VAULT) { + creationCode = RevShareCodeRepo.operatorFeeVaultCreationCode; + vaultName = "OperatorFeeVault"; + } else if (_config.proxy == SEQUENCER_FEE_WALLET) { + creationCode = RevShareCodeRepo.sequencerFeeVaultCreationCode; + vaultName = "SequencerFeeVault"; + } else if (_config.proxy == BASE_FEE_VAULT) { + creationCode = RevShareCodeRepo.baseFeeVaultCreationCode; + vaultName = "BaseFeeVault"; + } else if (_config.proxy == L1_FEE_VAULT) { + creationCode = RevShareCodeRepo.l1FeeVaultCreationCode; + vaultName = "L1FeeVault"; + } else { + revert("Unknown vault proxy address"); + } + + bytes32 salt = _getSalt(_saltSeed, vaultName); + address impl = Utils.getCreate2Address(salt, creationCode, CREATE2_DEPLOYER); + + // Deploy implementation + IOptimismPortal2(payable(_portal)).depositTransaction( address(CREATE2_DEPLOYER), 0, RevShareGasLimits.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, false, - abi.encodeCall(ICreate2Deployer.deploy, (0, sequencerSalt, sequencerInitCode)) + abi.encodeCall(ICreate2Deployer.deploy, (0, salt, creationCode)) ); - IOptimismPortal2(payable(portal)).depositTransaction( + // Upgrade proxy and initialize + IOptimismPortal2(payable(_portal)).depositTransaction( address(PROXY_ADMIN), 0, RevShareGasLimits.UPGRADE_GAS_LIMIT, @@ -123,112 +182,138 @@ contract RevShareContractsManager is RevSharePredeploys { abi.encodeCall( IProxyAdmin.upgradeAndCall, ( - payable(SEQUENCER_FEE_WALLET), - sequencerFeeVaultImpl, + payable(_config.proxy), + impl, abi.encodeCall( - IFeeVault.initialize, - (FEE_VAULT_RECIPIENT, FEE_VAULT_MIN_WITHDRAWAL_AMOUNT, FEE_VAULT_WITHDRAWAL_NETWORK) + IFeeVault.initialize, (_config.recipient, _config.minWithdrawal, _config.withdrawalNetwork) ) ) ) ); + } - // Deploy BaseFeeVault - bytes32 baseSalt = _getSalt(saltSeed, "BaseFeeVault"); - bytes memory baseInitCode = RevShareCodeRepo.baseFeeVaultCreationCode; - address baseFeeVaultImpl = Utils.getCreate2Address(baseSalt, baseInitCode, CREATE2_DEPLOYER); + /// @notice Deploys and upgrades the fee splitter. + function _deployAndUpgradeFeeSplitter(address _portal, string memory _saltSeed) private { + bytes32 salt = _getSalt(_saltSeed, "FeeSplitter"); + bytes memory creationCode = RevShareCodeRepo.feeSplitterCreationCode; + address impl = Utils.getCreate2Address(salt, creationCode, CREATE2_DEPLOYER); - IOptimismPortal2(payable(portal)).depositTransaction( + // Deploy implementation + IOptimismPortal2(payable(_portal)).depositTransaction( address(CREATE2_DEPLOYER), 0, - RevShareGasLimits.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, + RevShareGasLimits.FEE_SPLITTER_DEPLOYMENT_GAS_LIMIT, false, - abi.encodeCall(ICreate2Deployer.deploy, (0, baseSalt, baseInitCode)) + abi.encodeCall(ICreate2Deployer.deploy, (0, salt, creationCode)) ); - IOptimismPortal2(payable(portal)).depositTransaction( + // Upgrade proxy and initialize with address(0) calculator (disabled) + IOptimismPortal2(payable(_portal)).depositTransaction( address(PROXY_ADMIN), 0, RevShareGasLimits.UPGRADE_GAS_LIMIT, false, abi.encodeCall( IProxyAdmin.upgradeAndCall, - ( - payable(BASE_FEE_VAULT), - baseFeeVaultImpl, - abi.encodeCall( - IFeeVault.initialize, - (FEE_VAULT_RECIPIENT, FEE_VAULT_MIN_WITHDRAWAL_AMOUNT, FEE_VAULT_WITHDRAWAL_NETWORK) - ) - ) + (payable(FEE_SPLITTER), impl, abi.encodeCall(IFeeSplitter.initialize, (address(0)))) ) ); + } - // Deploy L1FeeVault - bytes32 l1Salt = _getSalt(saltSeed, "L1FeeVault"); - bytes memory l1InitCode = RevShareCodeRepo.l1FeeVaultCreationCode; - address l1FeeVaultImpl = Utils.getCreate2Address(l1Salt, l1InitCode, CREATE2_DEPLOYER); + /// @notice Deploys L1Withdrawer to L2. + function _deployL1Withdrawer(address _portal, string memory _saltSeed, L1WithdrawerConfig memory _config) + private + returns (address) + { + bytes memory initCode = bytes.concat( + RevShareCodeRepo.l1WithdrawerCreationCode, + abi.encode(_config.minWithdrawalAmount, _config.recipient, _config.gasLimit) + ); + bytes32 salt = _getSalt(_saltSeed, "L1Withdrawer"); + address l1Withdrawer = Utils.getCreate2Address(salt, initCode, CREATE2_DEPLOYER); - IOptimismPortal2(payable(portal)).depositTransaction( + IOptimismPortal2(payable(_portal)).depositTransaction( address(CREATE2_DEPLOYER), 0, - RevShareGasLimits.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, + RevShareGasLimits.L1_WITHDRAWER_DEPLOYMENT_GAS_LIMIT, false, - abi.encodeCall(ICreate2Deployer.deploy, (0, l1Salt, l1InitCode)) + abi.encodeCall(ICreate2Deployer.deploy, (0, salt, initCode)) ); - IOptimismPortal2(payable(portal)).depositTransaction( - address(PROXY_ADMIN), - 0, - RevShareGasLimits.UPGRADE_GAS_LIMIT, - false, - abi.encodeCall( - IProxyAdmin.upgradeAndCall, - ( - payable(L1_FEE_VAULT), - l1FeeVaultImpl, - abi.encodeCall( - IFeeVault.initialize, - (FEE_VAULT_RECIPIENT, FEE_VAULT_MIN_WITHDRAWAL_AMOUNT, FEE_VAULT_WITHDRAWAL_NETWORK) - ) - ) - ) - ); + return l1Withdrawer; } - /// @notice Deploys the fee splitter implementation using Create2. - function _deployFeeSplitter() private { - bytes32 feeSplitterSalt = _getSalt(saltSeed, "FeeSplitter"); - bytes memory feeSplitterInitCode = RevShareCodeRepo.feeSplitterCreationCode; - address feeSplitterImpl = - Utils.getCreate2Address(feeSplitterSalt, feeSplitterInitCode, CREATE2_DEPLOYER); + /// @notice Deploys SuperchainRevenueShareCalculator to L2. + function _deployCalculator( + address _portal, + string memory _saltSeed, + address _l1Withdrawer, + CalculatorConfig memory _config + ) private returns (address) { + bytes memory initCode = bytes.concat( + RevShareCodeRepo.scRevShareCalculatorCreationCode, abi.encode(_l1Withdrawer, _config.chainFeesRecipient) + ); + bytes32 salt = _getSalt(_saltSeed, "SCRevShareCalculator"); + address calculator = Utils.getCreate2Address(salt, initCode, CREATE2_DEPLOYER); - // Deploy FeeSplitter implementation - IOptimismPortal2(payable(portal)).depositTransaction( + IOptimismPortal2(payable(_portal)).depositTransaction( address(CREATE2_DEPLOYER), 0, - RevShareGasLimits.FEE_SPLITTER_DEPLOYMENT_GAS_LIMIT, + RevShareGasLimits.SC_REV_SHARE_CALCULATOR_DEPLOYMENT_GAS_LIMIT, false, - abi.encodeCall(ICreate2Deployer.deploy, (0, feeSplitterSalt, feeSplitterInitCode)) + abi.encodeCall(ICreate2Deployer.deploy, (0, salt, initCode)) ); - // Upgrade FeeSplitter proxy and initialize with address(0) calculator (disabled) - IOptimismPortal2(payable(portal)).depositTransaction( - address(PROXY_ADMIN), + return calculator; + } + + /// @notice Configures all 4 vaults for revenue sharing (recipient=FeeSplitter, minWithdrawal=0, network=L2). + function _configureVaultsForRevShare(address _portal) private { + address[4] memory vaults = + [OPERATOR_FEE_VAULT, SEQUENCER_FEE_WALLET, BASE_FEE_VAULT, L1_FEE_VAULT]; + + for (uint256 i = 0; i < vaults.length; i++) { + // Set recipient to FeeSplitter + IOptimismPortal2(payable(_portal)).depositTransaction( + vaults[i], + 0, + RevShareGasLimits.SETTERS_GAS_LIMIT, + false, + abi.encodeCall(IFeeVaultSetters.setRecipient, (FEE_SPLITTER)) + ); + + // Set minWithdrawalAmount to 0 + IOptimismPortal2(payable(_portal)).depositTransaction( + vaults[i], + 0, + RevShareGasLimits.SETTERS_GAS_LIMIT, + false, + abi.encodeCall(IFeeVaultSetters.setMinWithdrawalAmount, (0)) + ); + + // Set withdrawalNetwork to L2 (1) + IOptimismPortal2(payable(_portal)).depositTransaction( + vaults[i], + 0, + RevShareGasLimits.SETTERS_GAS_LIMIT, + false, + abi.encodeCall(IFeeVaultSetters.setWithdrawalNetwork, (1)) + ); + } + } + + /// @notice Sets the calculator on the fee splitter. + function _setFeeSplitterCalculator(address _portal, address _calculator) private { + IOptimismPortal2(payable(_portal)).depositTransaction( + FEE_SPLITTER, 0, - RevShareGasLimits.UPGRADE_GAS_LIMIT, + RevShareGasLimits.SETTERS_GAS_LIMIT, false, - abi.encodeCall( - IProxyAdmin.upgradeAndCall, - (payable(FEE_SPLITTER), feeSplitterImpl, abi.encodeCall(IFeeSplitter.initialize, (address(0)))) - ) + abi.encodeCall(IFeeSplitterSetter.setSharesCalculator, (_calculator)) ); } /// @notice Generates a salt from a prefix and suffix. - /// @param _prefix The prefix for the salt. - /// @param _suffix The suffix for the salt. - /// @return The generated salt. function _getSalt(string memory _prefix, string memory _suffix) private pure returns (bytes32) { return keccak256(abi.encodePacked(bytes(_prefix), bytes(":"), bytes(_suffix))); } From d0f52d6064a3eacc0a28af690bac8f3488e2deb0 Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Wed, 5 Nov 2025 00:09:31 -0300 Subject: [PATCH 03/69] chore: remove wrong checks --- src/RevShareContractsUpgrader.sol | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol index 5ccb786141..b3bf22df80 100644 --- a/src/RevShareContractsUpgrader.sol +++ b/src/RevShareContractsUpgrader.sol @@ -72,9 +72,6 @@ contract RevShareContractsManager is RevSharePredeploys { address chainFeesRecipient; } - /// @notice Tracks which portals have been upgraded. - mapping(address => bool) public upgradedPortals; - /// @notice Upgrades vault and fee splitter contracts. /// @param _portal The OptimismPortal2 address for the target L2. /// @param _saltSeed The salt seed for CREATE2 deployments. @@ -90,9 +87,6 @@ contract RevShareContractsManager is RevSharePredeploys { // Deploy and upgrade fee splitter with address(0) calculator (disabled) _deployAndUpgradeFeeSplitter(_portal, _saltSeed); - - // Mark this portal as upgraded - upgradedPortals[_portal] = true; } /// @notice Setup revenue sharing with default calculator (deploys L1Withdrawer + Calculator, configures vaults + splitter). @@ -106,7 +100,6 @@ contract RevShareContractsManager is RevSharePredeploys { L1WithdrawerConfig memory _l1Config, CalculatorConfig memory _calcConfig ) external { - require(upgradedPortals[_portal], "Must upgrade contracts first"); require(_l1Config.recipient != address(0), "L1Withdrawer recipient cannot be zero address"); require(_calcConfig.chainFeesRecipient != address(0), "Calculator chainFeesRecipient cannot be zero address"); @@ -127,7 +120,6 @@ contract RevShareContractsManager is RevSharePredeploys { /// @param _portal The OptimismPortal2 address for the target L2. /// @param _calculator The custom calculator address. function setupRevShareWithCustomCalculator(address _portal, address _calculator) external { - require(upgradedPortals[_portal], "Must upgrade contracts first"); require(_calculator != address(0), "Calculator cannot be zero address"); // Configure all 4 vaults for revenue sharing From 7910b0c32dbe605226ef275f745a78e31307dc20 Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Wed, 5 Nov 2025 00:23:38 -0300 Subject: [PATCH 04/69] feat: add combined path --- src/RevShareContractsUpgrader.sol | 154 ++++++++++++++++++++++++++---- 1 file changed, 135 insertions(+), 19 deletions(-) diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol index b3bf22df80..1728aa23f7 100644 --- a/src/RevShareContractsUpgrader.sol +++ b/src/RevShareContractsUpgrader.sol @@ -79,6 +79,7 @@ contract RevShareContractsManager is RevSharePredeploys { function upgradeContracts(address _portal, string memory _saltSeed, VaultConfig[] memory _vaults) external { require(_portal != address(0), "portal cannot be zero address"); require(bytes(_saltSeed).length != 0, "saltSeed cannot be empty"); + require(_vaults.length == 4, "vaults must be an array of 4"); // Deploy and upgrade each vault for (uint256 i = 0; i < _vaults.length; i++) { @@ -89,25 +90,36 @@ contract RevShareContractsManager is RevSharePredeploys { _deployAndUpgradeFeeSplitter(_portal, _saltSeed); } - /// @notice Setup revenue sharing with default calculator (deploys L1Withdrawer + Calculator, configures vaults + splitter). + /// @notice Setup revenue sharing (deploys calculator if needed, configures vaults + splitter). /// @param _portal The OptimismPortal2 address for the target L2. - /// @param _saltSeed The salt seed for CREATE2 deployments. - /// @param _l1Config L1Withdrawer configuration. - /// @param _calcConfig SuperchainRevenueShareCalculator configuration. - function setupRevShareWithDefaultCalculator( + /// @param _saltSeed The salt seed for CREATE2 deployments (only used if useDefaultCalculator=true). + /// @param _useDefaultCalculator Whether to deploy the default calculator (L1Withdrawer + Calculator). + /// @param _customCalculator The custom calculator address (used if useDefaultCalculator=false). + /// @param _l1Config L1Withdrawer configuration (only used if useDefaultCalculator=true). + /// @param _calcConfig SuperchainRevenueShareCalculator configuration (only used if useDefaultCalculator=true). + function setupRevShare( address _portal, string memory _saltSeed, + bool _useDefaultCalculator, + address _customCalculator, L1WithdrawerConfig memory _l1Config, CalculatorConfig memory _calcConfig ) external { - require(_l1Config.recipient != address(0), "L1Withdrawer recipient cannot be zero address"); - require(_calcConfig.chainFeesRecipient != address(0), "Calculator chainFeesRecipient cannot be zero address"); + address calculator; + + if (_useDefaultCalculator) { + require(_l1Config.recipient != address(0), "L1Withdrawer recipient cannot be zero address"); + require(_calcConfig.chainFeesRecipient != address(0), "Calculator chainFeesRecipient cannot be zero address"); - // Deploy L1Withdrawer - address l1Withdrawer = _deployL1Withdrawer(_portal, _saltSeed, _l1Config); + // Deploy L1Withdrawer + address l1Withdrawer = _deployL1Withdrawer(_portal, _saltSeed, _l1Config); - // Deploy SuperchainRevenueShareCalculator - address calculator = _deployCalculator(_portal, _saltSeed, l1Withdrawer, _calcConfig); + // Deploy SuperchainRevenueShareCalculator + calculator = _deployCalculator(_portal, _saltSeed, l1Withdrawer, _calcConfig); + } else { + require(_customCalculator != address(0), "Calculator cannot be zero address"); + calculator = _customCalculator; + } // Configure all 4 vaults for revenue sharing _configureVaultsForRevShare(_portal); @@ -116,17 +128,46 @@ contract RevShareContractsManager is RevSharePredeploys { _setFeeSplitterCalculator(_portal, calculator); } - /// @notice Setup revenue sharing with custom calculator (configures vaults + splitter only). + /// @notice Upgrades contracts and sets up revenue sharing in a single transaction. + /// This is more efficient as vaults are initialized with RevShare config from the start. /// @param _portal The OptimismPortal2 address for the target L2. - /// @param _calculator The custom calculator address. - function setupRevShareWithCustomCalculator(address _portal, address _calculator) external { - require(_calculator != address(0), "Calculator cannot be zero address"); + /// @param _saltSeed The salt seed for CREATE2 deployments. + /// @param _useDefaultCalculator Whether to deploy the default calculator (L1Withdrawer + Calculator). + /// @param _customCalculator The custom calculator address (used if useDefaultCalculator=false). + /// @param _l1Config L1Withdrawer configuration (only used if useDefaultCalculator=true). + /// @param _calcConfig SuperchainRevenueShareCalculator configuration (only used if useDefaultCalculator=true). + function upgradeAndSetupRevShare( + address _portal, + string memory _saltSeed, + bool _useDefaultCalculator, + address _customCalculator, + L1WithdrawerConfig memory _l1Config, + CalculatorConfig memory _calcConfig + ) external { + require(_portal != address(0), "portal cannot be zero address"); + require(bytes(_saltSeed).length != 0, "saltSeed cannot be empty"); - // Configure all 4 vaults for revenue sharing - _configureVaultsForRevShare(_portal); + address calculator; - // Set calculator on fee splitter - _setFeeSplitterCalculator(_portal, _calculator); + if (_useDefaultCalculator) { + require(_l1Config.recipient != address(0), "L1Withdrawer recipient cannot be zero address"); + require(_calcConfig.chainFeesRecipient != address(0), "Calculator chainFeesRecipient cannot be zero address"); + + // Deploy L1Withdrawer + address l1Withdrawer = _deployL1Withdrawer(_portal, _saltSeed, _l1Config); + + // Deploy SuperchainRevenueShareCalculator + calculator = _deployCalculator(_portal, _saltSeed, l1Withdrawer, _calcConfig); + } else { + require(_customCalculator != address(0), "Calculator cannot be zero address"); + calculator = _customCalculator; + } + + // Upgrade all 4 vaults with RevShare configuration (recipient=FeeSplitter, minWithdrawal=0, network=L2) + _upgradeVaultsWithRevShareConfig(_portal, _saltSeed); + + // Upgrade fee splitter and initialize with calculator + _deployAndUpgradeFeeSplitterWithCalculator(_portal, _saltSeed, calculator); } /// @notice Deploys and upgrades a single vault. @@ -305,6 +346,81 @@ contract RevShareContractsManager is RevSharePredeploys { ); } + /// @notice Upgrades all 4 vaults with RevShare configuration (recipient=FeeSplitter, minWithdrawal=0, network=L2). + function _upgradeVaultsWithRevShareConfig(address _portal, string memory _saltSeed) private { + address[4] memory vaultProxies = [OPERATOR_FEE_VAULT, SEQUENCER_FEE_WALLET, BASE_FEE_VAULT, L1_FEE_VAULT]; + bytes[4] memory creationCodes = [ + RevShareCodeRepo.operatorFeeVaultCreationCode, + RevShareCodeRepo.sequencerFeeVaultCreationCode, + RevShareCodeRepo.baseFeeVaultCreationCode, + RevShareCodeRepo.l1FeeVaultCreationCode + ]; + string[4] memory vaultNames = ["OperatorFeeVault", "SequencerFeeVault", "BaseFeeVault", "L1FeeVault"]; + + for (uint256 i = 0; i < 4; i++) { + bytes32 salt = _getSalt(_saltSeed, vaultNames[i]); + address impl = Utils.getCreate2Address(salt, creationCodes[i], CREATE2_DEPLOYER); + + // Deploy implementation + IOptimismPortal2(payable(_portal)).depositTransaction( + address(CREATE2_DEPLOYER), + 0, + RevShareGasLimits.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, + false, + abi.encodeCall(ICreate2Deployer.deploy, (0, salt, creationCodes[i])) + ); + + // Upgrade proxy and initialize with RevShare config + IOptimismPortal2(payable(_portal)).depositTransaction( + address(PROXY_ADMIN), + 0, + RevShareGasLimits.UPGRADE_GAS_LIMIT, + false, + abi.encodeCall( + IProxyAdmin.upgradeAndCall, + ( + payable(vaultProxies[i]), + impl, + abi.encodeCall( + IFeeVault.initialize, + (FEE_SPLITTER, 0, 1) // recipient=FeeSplitter, minWithdrawal=0, network=L2 + ) + ) + ) + ); + } + } + + /// @notice Deploys and upgrades the fee splitter with a calculator. + function _deployAndUpgradeFeeSplitterWithCalculator(address _portal, string memory _saltSeed, address _calculator) + private + { + bytes32 salt = _getSalt(_saltSeed, "FeeSplitter"); + bytes memory creationCode = RevShareCodeRepo.feeSplitterCreationCode; + address impl = Utils.getCreate2Address(salt, creationCode, CREATE2_DEPLOYER); + + // Deploy implementation + IOptimismPortal2(payable(_portal)).depositTransaction( + address(CREATE2_DEPLOYER), + 0, + RevShareGasLimits.FEE_SPLITTER_DEPLOYMENT_GAS_LIMIT, + false, + abi.encodeCall(ICreate2Deployer.deploy, (0, salt, creationCode)) + ); + + // Upgrade proxy and initialize with calculator + IOptimismPortal2(payable(_portal)).depositTransaction( + address(PROXY_ADMIN), + 0, + RevShareGasLimits.UPGRADE_GAS_LIMIT, + false, + abi.encodeCall( + IProxyAdmin.upgradeAndCall, + (payable(FEE_SPLITTER), impl, abi.encodeCall(IFeeSplitter.initialize, (_calculator))) + ) + ); + } + /// @notice Generates a salt from a prefix and suffix. function _getSalt(string memory _prefix, string memory _suffix) private pure returns (bytes32) { return keccak256(abi.encodePacked(bytes(_prefix), bytes(":"), bytes(_suffix))); From bb918b029d2ad4e2469dcae17ec2ea4af3ccf2af Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Wed, 5 Nov 2025 00:42:41 -0300 Subject: [PATCH 05/69] refactor: remove no sense struct --- src/RevShareContractsUpgrader.sol | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol index 1728aa23f7..94acfbc543 100644 --- a/src/RevShareContractsUpgrader.sol +++ b/src/RevShareContractsUpgrader.sol @@ -67,10 +67,6 @@ contract RevShareContractsManager is RevSharePredeploys { uint32 gasLimit; } - /// @notice Struct for SuperchainRevenueShareCalculator configuration. - struct CalculatorConfig { - address chainFeesRecipient; - } /// @notice Upgrades vault and fee splitter contracts. /// @param _portal The OptimismPortal2 address for the target L2. @@ -96,26 +92,26 @@ contract RevShareContractsManager is RevSharePredeploys { /// @param _useDefaultCalculator Whether to deploy the default calculator (L1Withdrawer + Calculator). /// @param _customCalculator The custom calculator address (used if useDefaultCalculator=false). /// @param _l1Config L1Withdrawer configuration (only used if useDefaultCalculator=true). - /// @param _calcConfig SuperchainRevenueShareCalculator configuration (only used if useDefaultCalculator=true). + /// @param _chainFeesRecipient The chain fees recipient for the calculator (only used if useDefaultCalculator=true). function setupRevShare( address _portal, string memory _saltSeed, bool _useDefaultCalculator, address _customCalculator, L1WithdrawerConfig memory _l1Config, - CalculatorConfig memory _calcConfig + address _chainFeesRecipient ) external { address calculator; if (_useDefaultCalculator) { require(_l1Config.recipient != address(0), "L1Withdrawer recipient cannot be zero address"); - require(_calcConfig.chainFeesRecipient != address(0), "Calculator chainFeesRecipient cannot be zero address"); + require(_chainFeesRecipient != address(0), "chainFeesRecipient cannot be zero address"); // Deploy L1Withdrawer address l1Withdrawer = _deployL1Withdrawer(_portal, _saltSeed, _l1Config); // Deploy SuperchainRevenueShareCalculator - calculator = _deployCalculator(_portal, _saltSeed, l1Withdrawer, _calcConfig); + calculator = _deployCalculator(_portal, _saltSeed, l1Withdrawer, _chainFeesRecipient); } else { require(_customCalculator != address(0), "Calculator cannot be zero address"); calculator = _customCalculator; @@ -135,14 +131,14 @@ contract RevShareContractsManager is RevSharePredeploys { /// @param _useDefaultCalculator Whether to deploy the default calculator (L1Withdrawer + Calculator). /// @param _customCalculator The custom calculator address (used if useDefaultCalculator=false). /// @param _l1Config L1Withdrawer configuration (only used if useDefaultCalculator=true). - /// @param _calcConfig SuperchainRevenueShareCalculator configuration (only used if useDefaultCalculator=true). + /// @param _chainFeesRecipient The chain fees recipient for the calculator (only used if useDefaultCalculator=true). function upgradeAndSetupRevShare( address _portal, string memory _saltSeed, bool _useDefaultCalculator, address _customCalculator, L1WithdrawerConfig memory _l1Config, - CalculatorConfig memory _calcConfig + address _chainFeesRecipient ) external { require(_portal != address(0), "portal cannot be zero address"); require(bytes(_saltSeed).length != 0, "saltSeed cannot be empty"); @@ -151,13 +147,13 @@ contract RevShareContractsManager is RevSharePredeploys { if (_useDefaultCalculator) { require(_l1Config.recipient != address(0), "L1Withdrawer recipient cannot be zero address"); - require(_calcConfig.chainFeesRecipient != address(0), "Calculator chainFeesRecipient cannot be zero address"); + require(_chainFeesRecipient != address(0), "chainFeesRecipient cannot be zero address"); // Deploy L1Withdrawer address l1Withdrawer = _deployL1Withdrawer(_portal, _saltSeed, _l1Config); // Deploy SuperchainRevenueShareCalculator - calculator = _deployCalculator(_portal, _saltSeed, l1Withdrawer, _calcConfig); + calculator = _deployCalculator(_portal, _saltSeed, l1Withdrawer, _chainFeesRecipient); } else { require(_customCalculator != address(0), "Calculator cannot be zero address"); calculator = _customCalculator; @@ -281,10 +277,10 @@ contract RevShareContractsManager is RevSharePredeploys { address _portal, string memory _saltSeed, address _l1Withdrawer, - CalculatorConfig memory _config + address _chainFeesRecipient ) private returns (address) { bytes memory initCode = bytes.concat( - RevShareCodeRepo.scRevShareCalculatorCreationCode, abi.encode(_l1Withdrawer, _config.chainFeesRecipient) + RevShareCodeRepo.scRevShareCalculatorCreationCode, abi.encode(_l1Withdrawer, _chainFeesRecipient) ); bytes32 salt = _getSalt(_saltSeed, "SCRevShareCalculator"); address calculator = Utils.getCreate2Address(salt, initCode, CREATE2_DEPLOYER); From dcd596df20035f6b0d2b2efc8d2a8978e0889b9c Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Wed, 5 Nov 2025 01:12:40 -0300 Subject: [PATCH 06/69] chore: fix comments --- src/RevShareContractsUpgrader.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol index 94acfbc543..6650c87a79 100644 --- a/src/RevShareContractsUpgrader.sol +++ b/src/RevShareContractsUpgrader.sol @@ -48,9 +48,9 @@ interface IFeeSplitterSetter { /// @title RevShareContractsManager /// @notice Upgrader contract that manages RevShare deployments and configuration via delegatecall. /// Supports three main operations: -/// 1. Upgrade vault and splitter contracts -/// 2. Setup revenue sharing with default calculator -/// 3. Setup revenue sharing with custom calculator +/// 1. Upgrade vault and splitter contracts (upgradeContracts) +/// 2. Setup revenue sharing after vaults were upgraded (setupRevShare) +/// 3. Upgrade contracts and setup revenue sharing in one call (upgradeAndSetupRevShare) contract RevShareContractsManager is RevSharePredeploys { /// @notice Struct for vault configuration. struct VaultConfig { From 6f11b329693e62dd6cdeabfea9b12136f03c9e04 Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Wed, 5 Nov 2025 13:22:05 -0300 Subject: [PATCH 07/69] feat: add templates with example configs --- src/template/RevShareContractsUpgrade.sol | 166 ++++++++++++++++ src/template/RevShareSetup.sol | 180 ++++++++++++++++++ .../config.toml | 40 ++++ .../config.toml | 22 +++ .../config.toml | 17 ++ .../config.toml | 22 +++ .../config.toml | 17 ++ 7 files changed, 464 insertions(+) create mode 100644 src/template/RevShareContractsUpgrade.sol create mode 100644 src/template/RevShareSetup.sol create mode 100644 test/tasks/example/eth/018-revshare-upgrade-contracts/config.toml create mode 100644 test/tasks/example/eth/019-revshare-setup-with-upgrade-default/config.toml create mode 100644 test/tasks/example/eth/020-revshare-setup-with-upgrade-custom/config.toml create mode 100644 test/tasks/example/eth/021-revshare-setup-without-upgrade-default/config.toml create mode 100644 test/tasks/example/eth/022-revshare-setup-without-upgrade-custom/config.toml diff --git a/src/template/RevShareContractsUpgrade.sol b/src/template/RevShareContractsUpgrade.sol new file mode 100644 index 0000000000..aef0ddffdd --- /dev/null +++ b/src/template/RevShareContractsUpgrade.sol @@ -0,0 +1,166 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import {VmSafe} from "forge-std/Vm.sol"; +import {stdToml} from "forge-std/StdToml.sol"; +import {L2TaskBase} from "src/tasks/types/L2TaskBase.sol"; +import {SuperchainAddressRegistry} from "src/SuperchainAddressRegistry.sol"; +import {Action} from "src/libraries/MultisigTypes.sol"; +import {RevSharePredeploys} from "src/libraries/RevSharePredeploys.sol"; + +/// @notice Interface for the RevShareContractsManager. +interface IRevShareContractsManager { + struct VaultConfig { + address proxy; + address recipient; + uint256 minWithdrawal; + uint8 withdrawalNetwork; + } + + function upgradeContracts(address _portal, string memory _saltSeed, VaultConfig[] memory _vaults) external; +} + +/// @notice Template for upgrading vault and fee splitter contracts via RevShareContractsManager. +/// @dev This template upgrades contracts without enabling revenue sharing. Supports multiple L2 chains. +contract RevShareContractsUpgrade is L2TaskBase, RevSharePredeploys { + using stdToml for string; + + /// @notice Temporary struct for parsing TOML (includes vault array). + struct TempChainConfig { + uint256 chainId; + string saltSeed; + IRevShareContractsManager.VaultConfig[] vaults; + } + + /// @notice Struct representing configuration for a single chain upgrade. + struct ChainConfig { + uint256 chainId; + string saltSeed; + } + + /// @notice The RevShareContractsManager contract to delegatecall. + address public REVSHARE_MANAGER; + + /// @notice Mapping of chain ID to configuration for the upgrade. + mapping(uint256 => ChainConfig) public cfg; + + /// @notice Mapping of chain ID to vault configurations (stored separately due to Solidity limitations). + mapping(uint256 => mapping(uint256 => IRevShareContractsManager.VaultConfig)) public vaultCfg; + + /// @notice Returns the safe address string identifier. + function safeAddressString() public pure override returns (string memory) { + return "ProxyAdminOwner"; + } + + /// @notice Returns the storage write permissions required for this task. + function _taskStorageWrites() internal pure virtual override returns (string[] memory) { + string[] memory _storageWrites = new string[](1); + _storageWrites[0] = "OptimismPortal"; + return _storageWrites; + } + + /// @notice Returns an array of contract names expected to have balance changes. + function _taskBalanceChanges() internal view virtual override returns (string[] memory) { + string[] memory _balanceChanges = new string[](1); + _balanceChanges[0] = "OptimismPortal"; + return _balanceChanges; + } + + /// @notice Sets up the template with configurations from a TOML file. + function _templateSetup(string memory _taskConfigFilePath, address _rootSafe) internal override { + super._templateSetup(_taskConfigFilePath, _rootSafe); + + string memory _toml = vm.readFile(_taskConfigFilePath); + SuperchainAddressRegistry.ChainInfo[] memory _chains = superchainAddrRegistry.getChains(); + + // Load RevShareContractsManager address + REVSHARE_MANAGER = _toml.readAddress(".addresses.RevShareContractsManager"); + require(REVSHARE_MANAGER != address(0), "RevShareContractsManager must be set"); + vm.label(REVSHARE_MANAGER, "RevShareContractsManager"); + + // Load per-chain configurations + // Expected TOML structure: + // [[revShareUpgrades]] + // chainId = 10 + // saltSeed = "..." + // [[revShareUpgrades.vaults]] + // proxy = "0x..." + // recipient = "0x..." + // minWithdrawal = 100000 + // withdrawalNetwork = 1 + + // Parse the raw TOML array - we need to parse the struct with vaults array separately + bytes memory rawConfigs = _toml.parseRaw(".revShareUpgrades"); + + // Decode into a temporary struct that includes the vaults array + TempChainConfig[] memory tempConfigs = abi.decode(rawConfigs, (TempChainConfig[])); + + for (uint256 i = 0; i < tempConfigs.length; i++) { + TempChainConfig memory tempCfg = tempConfigs[i]; + require(bytes(tempCfg.saltSeed).length != 0, "saltSeed must be set for each chain"); + require(tempCfg.vaults.length == 4, "Must provide exactly 4 vault configurations"); + + // Verify chainId is in the l2chains list + bool chainFound = false; + for (uint256 j = 0; j < _chains.length; j++) { + if (_chains[j].chainId == tempCfg.chainId) { + chainFound = true; + break; + } + } + require(chainFound, "Chain ID not found in l2chains list"); + + // Store basic configuration + cfg[tempCfg.chainId] = ChainConfig({chainId: tempCfg.chainId, saltSeed: tempCfg.saltSeed}); + + // Store vault configurations separately + for (uint256 j = 0; j < 4; j++) { + require(tempCfg.vaults[j].proxy != address(0), "Vault proxy cannot be zero address"); + vaultCfg[tempCfg.chainId][j] = tempCfg.vaults[j]; + } + } + } + + /// @notice Executes the vault and splitter upgrade via delegatecall for each chain. + function _build(address) internal override { + SuperchainAddressRegistry.ChainInfo[] memory chains = superchainAddrRegistry.getChains(); + + for (uint256 i = 0; i < chains.length; i++) { + uint256 chainId = chains[i].chainId; + ChainConfig memory chainCfg = cfg[chainId]; + + // Get portal address for this chain + address portal = superchainAddrRegistry.getAddress("OptimismPortal", chainId); + require(portal != address(0), "OptimismPortal not found for chain"); + + // Prepare vault configs array from separate mapping + IRevShareContractsManager.VaultConfig[] memory vaults = + new IRevShareContractsManager.VaultConfig[](4); + for (uint256 j = 0; j < 4; j++) { + vaults[j] = vaultCfg[chainId][j]; + } + + // Delegatecall to RevShareContractsManager for this chain + (bool success,) = REVSHARE_MANAGER.delegatecall( + abi.encodeCall(IRevShareContractsManager.upgradeContracts, (portal, chainCfg.saltSeed, vaults)) + ); + require(success, "RevShareContractsUpgrade: Delegatecall to upgradeContracts failed"); + } + } + + /// @notice Validates the operations executed as expected. + function _validate(VmSafe.AccountAccess[] memory, Action[] memory, address) internal view override { + // Basic validation - state changes are validated by the framework + SuperchainAddressRegistry.ChainInfo[] memory chains = superchainAddrRegistry.getChains(); + for (uint256 i = 0; i < chains.length; i++) { + uint256 chainId = chains[i].chainId; + ChainConfig memory chainCfg = cfg[chainId]; + + // Verify configuration was loaded + require(bytes(chainCfg.saltSeed).length != 0, "Configuration not loaded for chain"); + } + } + + /// @notice Returns list of addresses that should not be checked for code length. + function _getCodeExceptions() internal view virtual override returns (address[] memory) {} +} diff --git a/src/template/RevShareSetup.sol b/src/template/RevShareSetup.sol new file mode 100644 index 0000000000..3335adac43 --- /dev/null +++ b/src/template/RevShareSetup.sol @@ -0,0 +1,180 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import {VmSafe} from "forge-std/Vm.sol"; +import {LibString} from "solady/utils/LibString.sol"; +import {stdToml} from "forge-std/StdToml.sol"; +import {SimpleTaskBase} from "src/tasks/types/SimpleTaskBase.sol"; +import {Action} from "src/libraries/MultisigTypes.sol"; +import {RevSharePredeploys} from "src/libraries/RevSharePredeploys.sol"; + +/// @notice Interface for the RevShareContractsManager. +interface IRevShareContractsManager { + struct L1WithdrawerConfig { + uint256 minWithdrawalAmount; + address recipient; + uint32 gasLimit; + } + + function setupRevShare( + address _portal, + string memory _saltSeed, + bool _useDefaultCalculator, + address _customCalculator, + L1WithdrawerConfig memory _l1Config, + address _chainFeesRecipient + ) external; + + function upgradeAndSetupRevShare( + address _portal, + string memory _saltSeed, + bool _useDefaultCalculator, + address _customCalculator, + L1WithdrawerConfig memory _l1Config, + address _chainFeesRecipient + ) external; +} + +/// @notice Template for setting up revenue sharing via RevShareContractsManager. +/// @dev This template can either: +/// 1. Setup revenue sharing on already-upgraded contracts (setupRevShare) +/// 2. Upgrade contracts and setup revenue sharing in one transaction (upgradeAndSetupRevShare) +contract RevShareSetup is SimpleTaskBase, RevSharePredeploys { + using LibString for string; + using stdToml for string; + + /// @notice The RevShareContractsManager contract to delegatecall. + address public REVSHARE_MANAGER; + + /// @notice The OptimismPortal2 address for the target L2. + address public portal; + + /// @notice The salt seed for CREATE2 deployments. + string public saltSeed; + + /// @notice Whether to upgrade contracts before setting up revenue sharing. + bool public shouldUpgradeContracts; + + /// @notice Whether to deploy the default calculator (L1Withdrawer + SC Rev Share Calculator). + bool public useDefaultCalculator; + + /// @notice L1Withdrawer configuration (only used if useDefaultCalculator=true). + IRevShareContractsManager.L1WithdrawerConfig public l1Config; + + /// @notice Chain fees recipient for the calculator (only used if useDefaultCalculator=true). + address public chainFeesRecipient; + + /// @notice Custom calculator address (only used if useDefaultCalculator=false). + address public customCalculator; + + /// @notice Returns the safe address string identifier. + function safeAddressString() public pure override returns (string memory) { + return "ProxyAdminOwner"; + } + + /// @notice Returns the storage write permissions required for this task. + function _taskStorageWrites() internal pure virtual override returns (string[] memory) { + string[] memory _storageWrites = new string[](1); + _storageWrites[0] = "OptimismPortal"; + return _storageWrites; + } + + /// @notice Returns an array of contract names expected to have balance changes. + function _taskBalanceChanges() internal view virtual override returns (string[] memory) { + string[] memory _balanceChanges = new string[](1); + _balanceChanges[0] = "OptimismPortal"; + return _balanceChanges; + } + + /// @notice Sets up the template with configurations from a TOML file. + function _templateSetup(string memory _taskConfigFilePath, address) internal override { + string memory _toml = vm.readFile(_taskConfigFilePath); + + // Load RevShareContractsManager address + REVSHARE_MANAGER = _toml.readAddress(".addresses.RevShareContractsManager"); + require(REVSHARE_MANAGER != address(0), "RevShareContractsManager must be set"); + vm.label(REVSHARE_MANAGER, "RevShareContractsManager"); + + // Load portal and salt seed + portal = _toml.readAddress(".portal"); + require(portal != address(0), "portal must be set"); + vm.label(portal, "OptimismPortal"); + + saltSeed = _toml.readString(".saltSeed"); + require(bytes(saltSeed).length != 0, "saltSeed must be set"); + + // Load mode flags + shouldUpgradeContracts = _toml.readBool(".shouldUpgradeContracts"); + useDefaultCalculator = _toml.readBool(".useDefaultCalculator"); + + // Load calculator configuration based on mode + if (useDefaultCalculator) { + // Load L1Withdrawer configuration + uint256 l1MinWithdrawal = _toml.readUint(".l1WithdrawerMinWithdrawalAmount"); + address l1Recipient = _toml.readAddress(".l1WithdrawerRecipient"); + require(l1Recipient != address(0), "l1WithdrawerRecipient must be set"); + + uint256 l1GasLimitRaw = _toml.readUint(".l1WithdrawerGasLimit"); + require(l1GasLimitRaw > 0, "l1WithdrawerGasLimit must be greater than 0"); + require(l1GasLimitRaw <= type(uint32).max, "l1WithdrawerGasLimit must fit in uint32"); + uint32 l1GasLimit = uint32(l1GasLimitRaw); + + l1Config = IRevShareContractsManager.L1WithdrawerConfig({ + minWithdrawalAmount: l1MinWithdrawal, + recipient: l1Recipient, + gasLimit: l1GasLimit + }); + + // Load chain fees recipient + chainFeesRecipient = _toml.readAddress(".scRevShareCalcChainFeesRecipient"); + require(chainFeesRecipient != address(0), "scRevShareCalcChainFeesRecipient must be set"); + } else { + // Load custom calculator address + customCalculator = _toml.readAddress(".customCalculator"); + require(customCalculator != address(0), "customCalculator must be set when useDefaultCalculator is false"); + + // Set dummy values for l1Config (not used) + l1Config = IRevShareContractsManager.L1WithdrawerConfig({ + minWithdrawalAmount: 0, + recipient: address(0), + gasLimit: 0 + }); + chainFeesRecipient = address(0); + } + } + + /// @notice Executes revenue sharing setup via delegatecall. + function _build(address) internal override { + // Prepare parameters for delegatecall + address calcAddress = useDefaultCalculator ? address(0) : customCalculator; + + if (shouldUpgradeContracts) { + // Call upgradeAndSetupRevShare + (bool success,) = REVSHARE_MANAGER.delegatecall( + abi.encodeCall( + IRevShareContractsManager.upgradeAndSetupRevShare, + (portal, saltSeed, useDefaultCalculator, calcAddress, l1Config, chainFeesRecipient) + ) + ); + require(success, "RevShareSetup: Delegatecall to upgradeAndSetupRevShare failed"); + } else { + // Call setupRevShare + (bool success,) = REVSHARE_MANAGER.delegatecall( + abi.encodeCall( + IRevShareContractsManager.setupRevShare, + (portal, saltSeed, useDefaultCalculator, calcAddress, l1Config, chainFeesRecipient) + ) + ); + require(success, "RevShareSetup: Delegatecall to setupRevShare failed"); + } + } + + /// @notice Validates the operations executed as expected. + function _validate(VmSafe.AccountAccess[] memory, Action[] memory, address) internal view override { + // Basic validation - can be extended with specific checks + // The actual state changes validation is handled by the framework + } + + /// @notice Returns list of addresses that should not be checked for code length. + function _getCodeExceptions() internal view virtual override returns (address[] memory) {} +} diff --git a/test/tasks/example/eth/018-revshare-upgrade-contracts/config.toml b/test/tasks/example/eth/018-revshare-upgrade-contracts/config.toml new file mode 100644 index 0000000000..8d6e45e2d9 --- /dev/null +++ b/test/tasks/example/eth/018-revshare-upgrade-contracts/config.toml @@ -0,0 +1,40 @@ +# L2 chains to upgrade +l2chains = [{name = "OP Mainnet", chainId = 10}] + +templateName = "RevShareContractsUpgrade" + +# Per-chain upgrade configurations +[[revShareUpgrades]] +chainId = 10 +saltSeed = "DeploymentSaltV1" + +[[revShareUpgrades.vaults]] +proxy = "0x420000000000000000000000000000000000001b" # OperatorFeeVault +recipient = "0x8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b" # Custom recipient +minWithdrawal = 100000 # Minimum withdrawal amount in wei +withdrawalNetwork = 1 # 0=L1, 1=L2 + +[[revShareUpgrades.vaults]] +proxy = "0x4200000000000000000000000000000000000011" # SequencerFeeWallet +recipient = "0x8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b" +minWithdrawal = 100000 +withdrawalNetwork = 1 + +[[revShareUpgrades.vaults]] +proxy = "0x4200000000000000000000000000000000000019" # BaseFeeVault +recipient = "0x8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b" +minWithdrawal = 100000 +withdrawalNetwork = 1 + +[[revShareUpgrades.vaults]] +proxy = "0x420000000000000000000000000000000000001A" # L1FeeVault +recipient = "0x8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b" +minWithdrawal = 100000 +withdrawalNetwork = 1 + +[addresses] +ProxyAdminOwner = "0x5a0Aae59D09fccBdDb6C6CcEB07B7279367C3d2A" +RevShareContractsManager = "0x0000000000000000000000000000000000000000" # TODO: Set actual deployed address + +# Per-chain addresses (discovered automatically by SuperchainAddressRegistry) +# OptimismPortal for chainId 10 will be looked up automatically diff --git a/test/tasks/example/eth/019-revshare-setup-with-upgrade-default/config.toml b/test/tasks/example/eth/019-revshare-setup-with-upgrade-default/config.toml new file mode 100644 index 0000000000..af4f82a63f --- /dev/null +++ b/test/tasks/example/eth/019-revshare-setup-with-upgrade-default/config.toml @@ -0,0 +1,22 @@ +templateName = "RevShareSetup" + +# Portal and deployment configuration +portal = "0xbEb5Fc579115071764c7423A4f12eDde41f106Ed" # OptimismPortal address +saltSeed = "DeploymentSaltV1" # Deployment salt seed + +# Mode Configuration +shouldUpgradeContracts = true # Upgrade contracts AND setup revenue sharing in one transaction +useDefaultCalculator = true # Deploy default SC Rev Share Calculator and L1Withdrawer + +# L1 Withdrawer Configuration (used when useDefaultCalculator = true) +l1WithdrawerMinWithdrawalAmount = 350000 +l1WithdrawerRecipient = "0x742d35Cc6634C0532925a3b8D0C0C8b8B0c0C8b8" # L1 recipient address (e.g., FeesDepositor) +l1WithdrawerGasLimit = 800000 # Gas limit for L1 withdrawal transactions + +# SC Rev Share Calculator Configuration (used when useDefaultCalculator = true) +scRevShareCalcChainFeesRecipient = "0x8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b" # Chain fees recipient + +[addresses] +ProxyAdminOwner = "0x5a0Aae59D09fccBdDb6C6CcEB07B7279367C3d2A" +OptimismPortal = "0xbEb5Fc579115071764c7423A4f12eDde41f106Ed" +RevShareContractsManager = "0x0000000000000000000000000000000000000000" # TODO: Set actual deployed address diff --git a/test/tasks/example/eth/020-revshare-setup-with-upgrade-custom/config.toml b/test/tasks/example/eth/020-revshare-setup-with-upgrade-custom/config.toml new file mode 100644 index 0000000000..10597c48cc --- /dev/null +++ b/test/tasks/example/eth/020-revshare-setup-with-upgrade-custom/config.toml @@ -0,0 +1,17 @@ +templateName = "RevShareSetup" + +# Portal and deployment configuration +portal = "0xbEb5Fc579115071764c7423A4f12eDde41f106Ed" # OptimismPortal address +saltSeed = "DeploymentSaltV1" # Deployment salt seed + +# Mode Configuration +shouldUpgradeContracts = true # Upgrade contracts AND setup revenue sharing in one transaction +useDefaultCalculator = false # Use a custom calculator (skip deploying L1Withdrawer and SC Rev Share Calculator) + +# Custom Calculator Configuration (used when useDefaultCalculator = false) +customCalculator = "0x8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b" # Address of custom calculator contract + +[addresses] +ProxyAdminOwner = "0x5a0Aae59D09fccBdDb6C6CcEB07B7279367C3d2A" +OptimismPortal = "0xbEb5Fc579115071764c7423A4f12eDde41f106Ed" +RevShareContractsManager = "0x0000000000000000000000000000000000000000" # TODO: Set actual deployed address diff --git a/test/tasks/example/eth/021-revshare-setup-without-upgrade-default/config.toml b/test/tasks/example/eth/021-revshare-setup-without-upgrade-default/config.toml new file mode 100644 index 0000000000..2f22d454b1 --- /dev/null +++ b/test/tasks/example/eth/021-revshare-setup-without-upgrade-default/config.toml @@ -0,0 +1,22 @@ +templateName = "RevShareSetup" + +# Portal and deployment configuration +portal = "0xbEb5Fc579115071764c7423A4f12eDde41f106Ed" # OptimismPortal address +saltSeed = "DeploymentSaltV1" # Deployment salt seed + +# Mode Configuration +shouldUpgradeContracts = false # Setup revenue sharing on already-upgraded contracts +useDefaultCalculator = true # Deploy default SC Rev Share Calculator and L1Withdrawer + +# L1 Withdrawer Configuration (used when useDefaultCalculator = true) +l1WithdrawerMinWithdrawalAmount = 350000 +l1WithdrawerRecipient = "0x742d35Cc6634C0532925a3b8D0C0C8b8B0c0C8b8" # L1 recipient address (e.g., FeesDepositor) +l1WithdrawerGasLimit = 800000 # Gas limit for L1 withdrawal transactions + +# SC Rev Share Calculator Configuration (used when useDefaultCalculator = true) +scRevShareCalcChainFeesRecipient = "0x8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b" # Chain fees recipient + +[addresses] +ProxyAdminOwner = "0x5a0Aae59D09fccBdDb6C6CcEB07B7279367C3d2A" +OptimismPortal = "0xbEb5Fc579115071764c7423A4f12eDde41f106Ed" +RevShareContractsManager = "0x0000000000000000000000000000000000000000" # TODO: Set actual deployed address diff --git a/test/tasks/example/eth/022-revshare-setup-without-upgrade-custom/config.toml b/test/tasks/example/eth/022-revshare-setup-without-upgrade-custom/config.toml new file mode 100644 index 0000000000..86bdd7270c --- /dev/null +++ b/test/tasks/example/eth/022-revshare-setup-without-upgrade-custom/config.toml @@ -0,0 +1,17 @@ +templateName = "RevShareSetup" + +# Portal and deployment configuration +portal = "0xbEb5Fc579115071764c7423A4f12eDde41f106Ed" # OptimismPortal address +saltSeed = "DeploymentSaltV1" # Deployment salt seed + +# Mode Configuration +shouldUpgradeContracts = false # Setup revenue sharing on already-upgraded contracts +useDefaultCalculator = false # Use a custom calculator (skip deploying L1Withdrawer and SC Rev Share Calculator) + +# Custom Calculator Configuration (used when useDefaultCalculator = false) +customCalculator = "0x8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b" # Address of custom calculator contract + +[addresses] +ProxyAdminOwner = "0x5a0Aae59D09fccBdDb6C6CcEB07B7279367C3d2A" +OptimismPortal = "0xbEb5Fc579115071764c7423A4f12eDde41f106Ed" +RevShareContractsManager = "0x0000000000000000000000000000000000000000" # TODO: Set actual deployed address From 1c7c0708d57ba4baca82fc30eaee08cc33385676 Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Wed, 5 Nov 2025 18:13:29 -0300 Subject: [PATCH 08/69] chore: descope --- src/RevShareContractsUpgrader.sol | 110 ++++------- src/template/RevShareSetup.sol | 180 ------------------ ...pgrade.sol => RevShareUpgradeAndSetup.sol} | 102 +++++----- .../config.toml | 40 ++++ .../config.toml | 40 ---- .../config.toml | 22 --- .../config.toml | 17 -- .../config.toml | 22 --- .../config.toml | 17 -- 9 files changed, 126 insertions(+), 424 deletions(-) delete mode 100644 src/template/RevShareSetup.sol rename src/template/{RevShareContractsUpgrade.sol => RevShareUpgradeAndSetup.sol} (61%) create mode 100644 test/tasks/example/eth/018-revshare-upgrade-and-setup/config.toml delete mode 100644 test/tasks/example/eth/018-revshare-upgrade-contracts/config.toml delete mode 100644 test/tasks/example/eth/019-revshare-setup-with-upgrade-default/config.toml delete mode 100644 test/tasks/example/eth/020-revshare-setup-with-upgrade-custom/config.toml delete mode 100644 test/tasks/example/eth/021-revshare-setup-without-upgrade-default/config.toml delete mode 100644 test/tasks/example/eth/022-revshare-setup-without-upgrade-custom/config.toml diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol index 6650c87a79..0c272524f3 100644 --- a/src/RevShareContractsUpgrader.sol +++ b/src/RevShareContractsUpgrader.sol @@ -47,10 +47,11 @@ interface IFeeSplitterSetter { /// @title RevShareContractsManager /// @notice Upgrader contract that manages RevShare deployments and configuration via delegatecall. -/// Supports three main operations: -/// 1. Upgrade vault and splitter contracts (upgradeContracts) -/// 2. Setup revenue sharing after vaults were upgraded (setupRevShare) -/// 3. Upgrade contracts and setup revenue sharing in one call (upgradeAndSetupRevShare) +/// Supports three operations: +/// 1. upgradeContracts() - Upgrade vault and splitter implementations only +/// 2. setupRevShare() - Setup revenue sharing on already-upgraded contracts +/// 3. upgradeAndSetupRevShare() - Combined upgrade + setup (most efficient) +/// All operations use the default calculator (L1Withdrawer + SuperchainRevenueShareCalculator). contract RevShareContractsManager is RevSharePredeploys { /// @notice Struct for vault configuration. struct VaultConfig { @@ -67,17 +68,17 @@ contract RevShareContractsManager is RevSharePredeploys { uint32 gasLimit; } - - /// @notice Upgrades vault and fee splitter contracts. + /// @notice Upgrades vault and fee splitter contracts with custom configurations. + /// Vaults are NOT configured for revenue sharing - use setupRevShare() afterwards. /// @param _portal The OptimismPortal2 address for the target L2. /// @param _saltSeed The salt seed for CREATE2 deployments. - /// @param _vaults Array of vault configurations to upgrade. + /// @param _vaults Array of 4 vault configurations. function upgradeContracts(address _portal, string memory _saltSeed, VaultConfig[] memory _vaults) external { require(_portal != address(0), "portal cannot be zero address"); require(bytes(_saltSeed).length != 0, "saltSeed cannot be empty"); require(_vaults.length == 4, "vaults must be an array of 4"); - // Deploy and upgrade each vault + // Deploy and upgrade each vault with custom config for (uint256 i = 0; i < _vaults.length; i++) { _upgradeVault(_portal, _saltSeed, _vaults[i]); } @@ -86,36 +87,28 @@ contract RevShareContractsManager is RevSharePredeploys { _deployAndUpgradeFeeSplitter(_portal, _saltSeed); } - /// @notice Setup revenue sharing (deploys calculator if needed, configures vaults + splitter). + /// @notice Setup revenue sharing on already-upgraded contracts. + /// Deploys L1Withdrawer and calculator, then configures vaults and splitter. /// @param _portal The OptimismPortal2 address for the target L2. - /// @param _saltSeed The salt seed for CREATE2 deployments (only used if useDefaultCalculator=true). - /// @param _useDefaultCalculator Whether to deploy the default calculator (L1Withdrawer + Calculator). - /// @param _customCalculator The custom calculator address (used if useDefaultCalculator=false). - /// @param _l1Config L1Withdrawer configuration (only used if useDefaultCalculator=true). - /// @param _chainFeesRecipient The chain fees recipient for the calculator (only used if useDefaultCalculator=true). + /// @param _saltSeed The salt seed for CREATE2 deployments. + /// @param _l1Config L1Withdrawer configuration. + /// @param _chainFeesRecipient The chain fees recipient for the calculator. function setupRevShare( address _portal, string memory _saltSeed, - bool _useDefaultCalculator, - address _customCalculator, L1WithdrawerConfig memory _l1Config, address _chainFeesRecipient ) external { - address calculator; + require(_portal != address(0), "portal cannot be zero address"); + require(bytes(_saltSeed).length != 0, "saltSeed cannot be empty"); + require(_l1Config.recipient != address(0), "L1Withdrawer recipient cannot be zero address"); + require(_chainFeesRecipient != address(0), "chainFeesRecipient cannot be zero address"); - if (_useDefaultCalculator) { - require(_l1Config.recipient != address(0), "L1Withdrawer recipient cannot be zero address"); - require(_chainFeesRecipient != address(0), "chainFeesRecipient cannot be zero address"); + // Deploy L1Withdrawer + address l1Withdrawer = _deployL1Withdrawer(_portal, _saltSeed, _l1Config); - // Deploy L1Withdrawer - address l1Withdrawer = _deployL1Withdrawer(_portal, _saltSeed, _l1Config); - - // Deploy SuperchainRevenueShareCalculator - calculator = _deployCalculator(_portal, _saltSeed, l1Withdrawer, _chainFeesRecipient); - } else { - require(_customCalculator != address(0), "Calculator cannot be zero address"); - calculator = _customCalculator; - } + // Deploy SuperchainRevenueShareCalculator + address calculator = _deployCalculator(_portal, _saltSeed, l1Withdrawer, _chainFeesRecipient); // Configure all 4 vaults for revenue sharing _configureVaultsForRevShare(_portal); @@ -124,40 +117,28 @@ contract RevShareContractsManager is RevSharePredeploys { _setFeeSplitterCalculator(_portal, calculator); } - /// @notice Upgrades contracts and sets up revenue sharing in a single transaction. - /// This is more efficient as vaults are initialized with RevShare config from the start. + /// @notice Upgrades vault and splitter contracts and sets up revenue sharing in one transaction. + /// This is the most efficient path as vaults are initialized with RevShare config from the start. /// @param _portal The OptimismPortal2 address for the target L2. /// @param _saltSeed The salt seed for CREATE2 deployments. - /// @param _useDefaultCalculator Whether to deploy the default calculator (L1Withdrawer + Calculator). - /// @param _customCalculator The custom calculator address (used if useDefaultCalculator=false). - /// @param _l1Config L1Withdrawer configuration (only used if useDefaultCalculator=true). - /// @param _chainFeesRecipient The chain fees recipient for the calculator (only used if useDefaultCalculator=true). + /// @param _l1Config L1Withdrawer configuration. + /// @param _chainFeesRecipient The chain fees recipient for the calculator. function upgradeAndSetupRevShare( address _portal, string memory _saltSeed, - bool _useDefaultCalculator, - address _customCalculator, L1WithdrawerConfig memory _l1Config, address _chainFeesRecipient ) external { require(_portal != address(0), "portal cannot be zero address"); require(bytes(_saltSeed).length != 0, "saltSeed cannot be empty"); + require(_l1Config.recipient != address(0), "L1Withdrawer recipient cannot be zero address"); + require(_chainFeesRecipient != address(0), "chainFeesRecipient cannot be zero address"); - address calculator; + // Deploy L1Withdrawer + address l1Withdrawer = _deployL1Withdrawer(_portal, _saltSeed, _l1Config); - if (_useDefaultCalculator) { - require(_l1Config.recipient != address(0), "L1Withdrawer recipient cannot be zero address"); - require(_chainFeesRecipient != address(0), "chainFeesRecipient cannot be zero address"); - - // Deploy L1Withdrawer - address l1Withdrawer = _deployL1Withdrawer(_portal, _saltSeed, _l1Config); - - // Deploy SuperchainRevenueShareCalculator - calculator = _deployCalculator(_portal, _saltSeed, l1Withdrawer, _chainFeesRecipient); - } else { - require(_customCalculator != address(0), "Calculator cannot be zero address"); - calculator = _customCalculator; - } + // Deploy SuperchainRevenueShareCalculator + address calculator = _deployCalculator(_portal, _saltSeed, l1Withdrawer, _chainFeesRecipient); // Upgrade all 4 vaults with RevShare configuration (recipient=FeeSplitter, minWithdrawal=0, network=L2) _upgradeVaultsWithRevShareConfig(_portal, _saltSeed); @@ -166,7 +147,7 @@ contract RevShareContractsManager is RevSharePredeploys { _deployAndUpgradeFeeSplitterWithCalculator(_portal, _saltSeed, calculator); } - /// @notice Deploys and upgrades a single vault. + /// @notice Deploys and upgrades a single vault with custom configuration. function _upgradeVault(address _portal, string memory _saltSeed, VaultConfig memory _config) private { require(_config.proxy != address(0), "Vault proxy cannot be zero address"); @@ -202,7 +183,7 @@ contract RevShareContractsManager is RevSharePredeploys { abi.encodeCall(ICreate2Deployer.deploy, (0, salt, creationCode)) ); - // Upgrade proxy and initialize + // Upgrade proxy and initialize with custom config IOptimismPortal2(payable(_portal)).depositTransaction( address(PROXY_ADMIN), 0, @@ -221,7 +202,7 @@ contract RevShareContractsManager is RevSharePredeploys { ); } - /// @notice Deploys and upgrades the fee splitter. + /// @notice Deploys and upgrades the fee splitter with address(0) calculator (disabled). function _deployAndUpgradeFeeSplitter(address _portal, string memory _saltSeed) private { bytes32 salt = _getSalt(_saltSeed, "FeeSplitter"); bytes memory creationCode = RevShareCodeRepo.feeSplitterCreationCode; @@ -298,35 +279,22 @@ contract RevShareContractsManager is RevSharePredeploys { /// @notice Configures all 4 vaults for revenue sharing (recipient=FeeSplitter, minWithdrawal=0, network=L2). function _configureVaultsForRevShare(address _portal) private { - address[4] memory vaults = - [OPERATOR_FEE_VAULT, SEQUENCER_FEE_WALLET, BASE_FEE_VAULT, L1_FEE_VAULT]; + address[4] memory vaults = [OPERATOR_FEE_VAULT, SEQUENCER_FEE_WALLET, BASE_FEE_VAULT, L1_FEE_VAULT]; for (uint256 i = 0; i < vaults.length; i++) { // Set recipient to FeeSplitter IOptimismPortal2(payable(_portal)).depositTransaction( - vaults[i], - 0, - RevShareGasLimits.SETTERS_GAS_LIMIT, - false, - abi.encodeCall(IFeeVaultSetters.setRecipient, (FEE_SPLITTER)) + vaults[i], 0, RevShareGasLimits.SETTERS_GAS_LIMIT, false, abi.encodeCall(IFeeVaultSetters.setRecipient, (FEE_SPLITTER)) ); // Set minWithdrawalAmount to 0 IOptimismPortal2(payable(_portal)).depositTransaction( - vaults[i], - 0, - RevShareGasLimits.SETTERS_GAS_LIMIT, - false, - abi.encodeCall(IFeeVaultSetters.setMinWithdrawalAmount, (0)) + vaults[i], 0, RevShareGasLimits.SETTERS_GAS_LIMIT, false, abi.encodeCall(IFeeVaultSetters.setMinWithdrawalAmount, (0)) ); // Set withdrawalNetwork to L2 (1) IOptimismPortal2(payable(_portal)).depositTransaction( - vaults[i], - 0, - RevShareGasLimits.SETTERS_GAS_LIMIT, - false, - abi.encodeCall(IFeeVaultSetters.setWithdrawalNetwork, (1)) + vaults[i], 0, RevShareGasLimits.SETTERS_GAS_LIMIT, false, abi.encodeCall(IFeeVaultSetters.setWithdrawalNetwork, (1)) ); } } diff --git a/src/template/RevShareSetup.sol b/src/template/RevShareSetup.sol deleted file mode 100644 index 3335adac43..0000000000 --- a/src/template/RevShareSetup.sol +++ /dev/null @@ -1,180 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.15; - -import {VmSafe} from "forge-std/Vm.sol"; -import {LibString} from "solady/utils/LibString.sol"; -import {stdToml} from "forge-std/StdToml.sol"; -import {SimpleTaskBase} from "src/tasks/types/SimpleTaskBase.sol"; -import {Action} from "src/libraries/MultisigTypes.sol"; -import {RevSharePredeploys} from "src/libraries/RevSharePredeploys.sol"; - -/// @notice Interface for the RevShareContractsManager. -interface IRevShareContractsManager { - struct L1WithdrawerConfig { - uint256 minWithdrawalAmount; - address recipient; - uint32 gasLimit; - } - - function setupRevShare( - address _portal, - string memory _saltSeed, - bool _useDefaultCalculator, - address _customCalculator, - L1WithdrawerConfig memory _l1Config, - address _chainFeesRecipient - ) external; - - function upgradeAndSetupRevShare( - address _portal, - string memory _saltSeed, - bool _useDefaultCalculator, - address _customCalculator, - L1WithdrawerConfig memory _l1Config, - address _chainFeesRecipient - ) external; -} - -/// @notice Template for setting up revenue sharing via RevShareContractsManager. -/// @dev This template can either: -/// 1. Setup revenue sharing on already-upgraded contracts (setupRevShare) -/// 2. Upgrade contracts and setup revenue sharing in one transaction (upgradeAndSetupRevShare) -contract RevShareSetup is SimpleTaskBase, RevSharePredeploys { - using LibString for string; - using stdToml for string; - - /// @notice The RevShareContractsManager contract to delegatecall. - address public REVSHARE_MANAGER; - - /// @notice The OptimismPortal2 address for the target L2. - address public portal; - - /// @notice The salt seed for CREATE2 deployments. - string public saltSeed; - - /// @notice Whether to upgrade contracts before setting up revenue sharing. - bool public shouldUpgradeContracts; - - /// @notice Whether to deploy the default calculator (L1Withdrawer + SC Rev Share Calculator). - bool public useDefaultCalculator; - - /// @notice L1Withdrawer configuration (only used if useDefaultCalculator=true). - IRevShareContractsManager.L1WithdrawerConfig public l1Config; - - /// @notice Chain fees recipient for the calculator (only used if useDefaultCalculator=true). - address public chainFeesRecipient; - - /// @notice Custom calculator address (only used if useDefaultCalculator=false). - address public customCalculator; - - /// @notice Returns the safe address string identifier. - function safeAddressString() public pure override returns (string memory) { - return "ProxyAdminOwner"; - } - - /// @notice Returns the storage write permissions required for this task. - function _taskStorageWrites() internal pure virtual override returns (string[] memory) { - string[] memory _storageWrites = new string[](1); - _storageWrites[0] = "OptimismPortal"; - return _storageWrites; - } - - /// @notice Returns an array of contract names expected to have balance changes. - function _taskBalanceChanges() internal view virtual override returns (string[] memory) { - string[] memory _balanceChanges = new string[](1); - _balanceChanges[0] = "OptimismPortal"; - return _balanceChanges; - } - - /// @notice Sets up the template with configurations from a TOML file. - function _templateSetup(string memory _taskConfigFilePath, address) internal override { - string memory _toml = vm.readFile(_taskConfigFilePath); - - // Load RevShareContractsManager address - REVSHARE_MANAGER = _toml.readAddress(".addresses.RevShareContractsManager"); - require(REVSHARE_MANAGER != address(0), "RevShareContractsManager must be set"); - vm.label(REVSHARE_MANAGER, "RevShareContractsManager"); - - // Load portal and salt seed - portal = _toml.readAddress(".portal"); - require(portal != address(0), "portal must be set"); - vm.label(portal, "OptimismPortal"); - - saltSeed = _toml.readString(".saltSeed"); - require(bytes(saltSeed).length != 0, "saltSeed must be set"); - - // Load mode flags - shouldUpgradeContracts = _toml.readBool(".shouldUpgradeContracts"); - useDefaultCalculator = _toml.readBool(".useDefaultCalculator"); - - // Load calculator configuration based on mode - if (useDefaultCalculator) { - // Load L1Withdrawer configuration - uint256 l1MinWithdrawal = _toml.readUint(".l1WithdrawerMinWithdrawalAmount"); - address l1Recipient = _toml.readAddress(".l1WithdrawerRecipient"); - require(l1Recipient != address(0), "l1WithdrawerRecipient must be set"); - - uint256 l1GasLimitRaw = _toml.readUint(".l1WithdrawerGasLimit"); - require(l1GasLimitRaw > 0, "l1WithdrawerGasLimit must be greater than 0"); - require(l1GasLimitRaw <= type(uint32).max, "l1WithdrawerGasLimit must fit in uint32"); - uint32 l1GasLimit = uint32(l1GasLimitRaw); - - l1Config = IRevShareContractsManager.L1WithdrawerConfig({ - minWithdrawalAmount: l1MinWithdrawal, - recipient: l1Recipient, - gasLimit: l1GasLimit - }); - - // Load chain fees recipient - chainFeesRecipient = _toml.readAddress(".scRevShareCalcChainFeesRecipient"); - require(chainFeesRecipient != address(0), "scRevShareCalcChainFeesRecipient must be set"); - } else { - // Load custom calculator address - customCalculator = _toml.readAddress(".customCalculator"); - require(customCalculator != address(0), "customCalculator must be set when useDefaultCalculator is false"); - - // Set dummy values for l1Config (not used) - l1Config = IRevShareContractsManager.L1WithdrawerConfig({ - minWithdrawalAmount: 0, - recipient: address(0), - gasLimit: 0 - }); - chainFeesRecipient = address(0); - } - } - - /// @notice Executes revenue sharing setup via delegatecall. - function _build(address) internal override { - // Prepare parameters for delegatecall - address calcAddress = useDefaultCalculator ? address(0) : customCalculator; - - if (shouldUpgradeContracts) { - // Call upgradeAndSetupRevShare - (bool success,) = REVSHARE_MANAGER.delegatecall( - abi.encodeCall( - IRevShareContractsManager.upgradeAndSetupRevShare, - (portal, saltSeed, useDefaultCalculator, calcAddress, l1Config, chainFeesRecipient) - ) - ); - require(success, "RevShareSetup: Delegatecall to upgradeAndSetupRevShare failed"); - } else { - // Call setupRevShare - (bool success,) = REVSHARE_MANAGER.delegatecall( - abi.encodeCall( - IRevShareContractsManager.setupRevShare, - (portal, saltSeed, useDefaultCalculator, calcAddress, l1Config, chainFeesRecipient) - ) - ); - require(success, "RevShareSetup: Delegatecall to setupRevShare failed"); - } - } - - /// @notice Validates the operations executed as expected. - function _validate(VmSafe.AccountAccess[] memory, Action[] memory, address) internal view override { - // Basic validation - can be extended with specific checks - // The actual state changes validation is handled by the framework - } - - /// @notice Returns list of addresses that should not be checked for code length. - function _getCodeExceptions() internal view virtual override returns (address[] memory) {} -} diff --git a/src/template/RevShareContractsUpgrade.sol b/src/template/RevShareUpgradeAndSetup.sol similarity index 61% rename from src/template/RevShareContractsUpgrade.sol rename to src/template/RevShareUpgradeAndSetup.sol index aef0ddffdd..4d0f98bd8f 100644 --- a/src/template/RevShareContractsUpgrade.sol +++ b/src/template/RevShareUpgradeAndSetup.sol @@ -10,43 +10,41 @@ import {RevSharePredeploys} from "src/libraries/RevSharePredeploys.sol"; /// @notice Interface for the RevShareContractsManager. interface IRevShareContractsManager { - struct VaultConfig { - address proxy; + struct L1WithdrawerConfig { + uint256 minWithdrawalAmount; address recipient; - uint256 minWithdrawal; - uint8 withdrawalNetwork; + uint32 gasLimit; } - function upgradeContracts(address _portal, string memory _saltSeed, VaultConfig[] memory _vaults) external; + function upgradeAndSetupRevShare( + address _portal, + string memory _saltSeed, + L1WithdrawerConfig memory _l1Config, + address _chainFeesRecipient + ) external; } -/// @notice Template for upgrading vault and fee splitter contracts via RevShareContractsManager. -/// @dev This template upgrades contracts without enabling revenue sharing. Supports multiple L2 chains. -contract RevShareContractsUpgrade is L2TaskBase, RevSharePredeploys { +/// @notice Template for upgrading vault and fee splitter contracts AND enabling revenue sharing. +/// @dev This template performs the complete upgrade and setup with default calculator. Supports multiple L2 chains. +contract RevShareUpgradeAndSetup is L2TaskBase, RevSharePredeploys { using stdToml for string; - /// @notice Temporary struct for parsing TOML (includes vault array). - struct TempChainConfig { - uint256 chainId; - string saltSeed; - IRevShareContractsManager.VaultConfig[] vaults; - } - - /// @notice Struct representing configuration for a single chain upgrade. + /// @notice Struct representing configuration for a single chain. struct ChainConfig { uint256 chainId; string saltSeed; + uint256 l1WithdrawerMinWithdrawalAmount; + address l1WithdrawerRecipient; + uint32 l1WithdrawerGasLimit; + address chainFeesRecipient; } /// @notice The RevShareContractsManager contract to delegatecall. address public REVSHARE_MANAGER; - /// @notice Mapping of chain ID to configuration for the upgrade. + /// @notice Mapping of chain ID to configuration. mapping(uint256 => ChainConfig) public cfg; - /// @notice Mapping of chain ID to vault configurations (stored separately due to Solidity limitations). - mapping(uint256 => mapping(uint256 => IRevShareContractsManager.VaultConfig)) public vaultCfg; - /// @notice Returns the safe address string identifier. function safeAddressString() public pure override returns (string memory) { return "ProxyAdminOwner"; @@ -80,48 +78,38 @@ contract RevShareContractsUpgrade is L2TaskBase, RevSharePredeploys { // Load per-chain configurations // Expected TOML structure: - // [[revShareUpgrades]] + // [[revShareSetups]] // chainId = 10 // saltSeed = "..." - // [[revShareUpgrades.vaults]] - // proxy = "0x..." - // recipient = "0x..." - // minWithdrawal = 100000 - // withdrawalNetwork = 1 - - // Parse the raw TOML array - we need to parse the struct with vaults array separately - bytes memory rawConfigs = _toml.parseRaw(".revShareUpgrades"); - - // Decode into a temporary struct that includes the vaults array - TempChainConfig[] memory tempConfigs = abi.decode(rawConfigs, (TempChainConfig[])); - - for (uint256 i = 0; i < tempConfigs.length; i++) { - TempChainConfig memory tempCfg = tempConfigs[i]; - require(bytes(tempCfg.saltSeed).length != 0, "saltSeed must be set for each chain"); - require(tempCfg.vaults.length == 4, "Must provide exactly 4 vault configurations"); + // l1WithdrawerMinWithdrawalAmount = 350000 + // l1WithdrawerRecipient = "0x..." + // l1WithdrawerGasLimit = 800000 + // chainFeesRecipient = "0x..." + ChainConfig[] memory _configs = abi.decode(_toml.parseRaw(".revShareSetups"), (ChainConfig[])); + + for (uint256 i = 0; i < _configs.length; i++) { + ChainConfig memory _config = _configs[i]; + require(bytes(_config.saltSeed).length != 0, "saltSeed must be set for each chain"); + require(_config.l1WithdrawerRecipient != address(0), "l1WithdrawerRecipient must be set"); + require(_config.chainFeesRecipient != address(0), "chainFeesRecipient must be set"); + require(_config.l1WithdrawerGasLimit > 0, "l1WithdrawerGasLimit must be greater than 0"); // Verify chainId is in the l2chains list bool chainFound = false; for (uint256 j = 0; j < _chains.length; j++) { - if (_chains[j].chainId == tempCfg.chainId) { + if (_chains[j].chainId == _config.chainId) { chainFound = true; break; } } require(chainFound, "Chain ID not found in l2chains list"); - // Store basic configuration - cfg[tempCfg.chainId] = ChainConfig({chainId: tempCfg.chainId, saltSeed: tempCfg.saltSeed}); - - // Store vault configurations separately - for (uint256 j = 0; j < 4; j++) { - require(tempCfg.vaults[j].proxy != address(0), "Vault proxy cannot be zero address"); - vaultCfg[tempCfg.chainId][j] = tempCfg.vaults[j]; - } + // Store configuration + cfg[_config.chainId] = _config; } } - /// @notice Executes the vault and splitter upgrade via delegatecall for each chain. + /// @notice Executes the vault/splitter upgrade and revenue sharing setup via delegatecall for each chain. function _build(address) internal override { SuperchainAddressRegistry.ChainInfo[] memory chains = superchainAddrRegistry.getChains(); @@ -133,18 +121,22 @@ contract RevShareContractsUpgrade is L2TaskBase, RevSharePredeploys { address portal = superchainAddrRegistry.getAddress("OptimismPortal", chainId); require(portal != address(0), "OptimismPortal not found for chain"); - // Prepare vault configs array from separate mapping - IRevShareContractsManager.VaultConfig[] memory vaults = - new IRevShareContractsManager.VaultConfig[](4); - for (uint256 j = 0; j < 4; j++) { - vaults[j] = vaultCfg[chainId][j]; - } + // Prepare L1Withdrawer config + IRevShareContractsManager.L1WithdrawerConfig memory l1Config = IRevShareContractsManager + .L1WithdrawerConfig({ + minWithdrawalAmount: chainCfg.l1WithdrawerMinWithdrawalAmount, + recipient: chainCfg.l1WithdrawerRecipient, + gasLimit: chainCfg.l1WithdrawerGasLimit + }); // Delegatecall to RevShareContractsManager for this chain (bool success,) = REVSHARE_MANAGER.delegatecall( - abi.encodeCall(IRevShareContractsManager.upgradeContracts, (portal, chainCfg.saltSeed, vaults)) + abi.encodeCall( + IRevShareContractsManager.upgradeAndSetupRevShare, + (portal, chainCfg.saltSeed, l1Config, chainCfg.chainFeesRecipient) + ) ); - require(success, "RevShareContractsUpgrade: Delegatecall to upgradeContracts failed"); + require(success, "RevShareUpgradeAndSetup: Delegatecall to upgradeAndSetupRevShare failed"); } } diff --git a/test/tasks/example/eth/018-revshare-upgrade-and-setup/config.toml b/test/tasks/example/eth/018-revshare-upgrade-and-setup/config.toml new file mode 100644 index 0000000000..4ea1b3b4b4 --- /dev/null +++ b/test/tasks/example/eth/018-revshare-upgrade-and-setup/config.toml @@ -0,0 +1,40 @@ +# L2 chains to upgrade and enable revenue sharing +l2chains = [ + {name = "OP Mainnet", chainId = 10}, + {name = "Base", chainId = 8453} +] + +templateName = "RevShareUpgradeAndSetup" + +# OP Mainnet configuration +[[revShareSetups]] +chainId = 10 +saltSeed = "DeploymentSaltV1-OP" + +# L1 Withdrawer configuration +l1WithdrawerMinWithdrawalAmount = 350000 +l1WithdrawerRecipient = "0x742d35Cc6634C0532925a3b8D0C0C8b8B0c0C8b8" # L1 recipient (e.g., FeesDepositor) +l1WithdrawerGasLimit = 800000 + +# Superchain Revenue Share Calculator configuration +chainFeesRecipient = "0x8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b" # Chain fees recipient + +# Base Mainnet configuration +[[revShareSetups]] +chainId = 8453 +saltSeed = "DeploymentSaltV1-Base" + +# L1 Withdrawer configuration +l1WithdrawerMinWithdrawalAmount = 350000 +l1WithdrawerRecipient = "0x742d35Cc6634C0532925a3b8D0C0C8b8B0c0C8b8" # L1 recipient (e.g., FeesDepositor) +l1WithdrawerGasLimit = 800000 + +# Superchain Revenue Share Calculator configuration +chainFeesRecipient = "0x9B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C9B" # Chain fees recipient + +[addresses] +ProxyAdminOwner = "0x5a0Aae59D09fccBdDb6C6CcEB07B7279367C3d2A" +RevShareContractsManager = "0x0000000000000000000000000000000000000000" # TODO: Set actual deployed address + +# Per-chain addresses (discovered automatically by SuperchainAddressRegistry) +# OptimismPortal addresses will be looked up automatically for each chain diff --git a/test/tasks/example/eth/018-revshare-upgrade-contracts/config.toml b/test/tasks/example/eth/018-revshare-upgrade-contracts/config.toml deleted file mode 100644 index 8d6e45e2d9..0000000000 --- a/test/tasks/example/eth/018-revshare-upgrade-contracts/config.toml +++ /dev/null @@ -1,40 +0,0 @@ -# L2 chains to upgrade -l2chains = [{name = "OP Mainnet", chainId = 10}] - -templateName = "RevShareContractsUpgrade" - -# Per-chain upgrade configurations -[[revShareUpgrades]] -chainId = 10 -saltSeed = "DeploymentSaltV1" - -[[revShareUpgrades.vaults]] -proxy = "0x420000000000000000000000000000000000001b" # OperatorFeeVault -recipient = "0x8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b" # Custom recipient -minWithdrawal = 100000 # Minimum withdrawal amount in wei -withdrawalNetwork = 1 # 0=L1, 1=L2 - -[[revShareUpgrades.vaults]] -proxy = "0x4200000000000000000000000000000000000011" # SequencerFeeWallet -recipient = "0x8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b" -minWithdrawal = 100000 -withdrawalNetwork = 1 - -[[revShareUpgrades.vaults]] -proxy = "0x4200000000000000000000000000000000000019" # BaseFeeVault -recipient = "0x8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b" -minWithdrawal = 100000 -withdrawalNetwork = 1 - -[[revShareUpgrades.vaults]] -proxy = "0x420000000000000000000000000000000000001A" # L1FeeVault -recipient = "0x8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b" -minWithdrawal = 100000 -withdrawalNetwork = 1 - -[addresses] -ProxyAdminOwner = "0x5a0Aae59D09fccBdDb6C6CcEB07B7279367C3d2A" -RevShareContractsManager = "0x0000000000000000000000000000000000000000" # TODO: Set actual deployed address - -# Per-chain addresses (discovered automatically by SuperchainAddressRegistry) -# OptimismPortal for chainId 10 will be looked up automatically diff --git a/test/tasks/example/eth/019-revshare-setup-with-upgrade-default/config.toml b/test/tasks/example/eth/019-revshare-setup-with-upgrade-default/config.toml deleted file mode 100644 index af4f82a63f..0000000000 --- a/test/tasks/example/eth/019-revshare-setup-with-upgrade-default/config.toml +++ /dev/null @@ -1,22 +0,0 @@ -templateName = "RevShareSetup" - -# Portal and deployment configuration -portal = "0xbEb5Fc579115071764c7423A4f12eDde41f106Ed" # OptimismPortal address -saltSeed = "DeploymentSaltV1" # Deployment salt seed - -# Mode Configuration -shouldUpgradeContracts = true # Upgrade contracts AND setup revenue sharing in one transaction -useDefaultCalculator = true # Deploy default SC Rev Share Calculator and L1Withdrawer - -# L1 Withdrawer Configuration (used when useDefaultCalculator = true) -l1WithdrawerMinWithdrawalAmount = 350000 -l1WithdrawerRecipient = "0x742d35Cc6634C0532925a3b8D0C0C8b8B0c0C8b8" # L1 recipient address (e.g., FeesDepositor) -l1WithdrawerGasLimit = 800000 # Gas limit for L1 withdrawal transactions - -# SC Rev Share Calculator Configuration (used when useDefaultCalculator = true) -scRevShareCalcChainFeesRecipient = "0x8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b" # Chain fees recipient - -[addresses] -ProxyAdminOwner = "0x5a0Aae59D09fccBdDb6C6CcEB07B7279367C3d2A" -OptimismPortal = "0xbEb5Fc579115071764c7423A4f12eDde41f106Ed" -RevShareContractsManager = "0x0000000000000000000000000000000000000000" # TODO: Set actual deployed address diff --git a/test/tasks/example/eth/020-revshare-setup-with-upgrade-custom/config.toml b/test/tasks/example/eth/020-revshare-setup-with-upgrade-custom/config.toml deleted file mode 100644 index 10597c48cc..0000000000 --- a/test/tasks/example/eth/020-revshare-setup-with-upgrade-custom/config.toml +++ /dev/null @@ -1,17 +0,0 @@ -templateName = "RevShareSetup" - -# Portal and deployment configuration -portal = "0xbEb5Fc579115071764c7423A4f12eDde41f106Ed" # OptimismPortal address -saltSeed = "DeploymentSaltV1" # Deployment salt seed - -# Mode Configuration -shouldUpgradeContracts = true # Upgrade contracts AND setup revenue sharing in one transaction -useDefaultCalculator = false # Use a custom calculator (skip deploying L1Withdrawer and SC Rev Share Calculator) - -# Custom Calculator Configuration (used when useDefaultCalculator = false) -customCalculator = "0x8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b" # Address of custom calculator contract - -[addresses] -ProxyAdminOwner = "0x5a0Aae59D09fccBdDb6C6CcEB07B7279367C3d2A" -OptimismPortal = "0xbEb5Fc579115071764c7423A4f12eDde41f106Ed" -RevShareContractsManager = "0x0000000000000000000000000000000000000000" # TODO: Set actual deployed address diff --git a/test/tasks/example/eth/021-revshare-setup-without-upgrade-default/config.toml b/test/tasks/example/eth/021-revshare-setup-without-upgrade-default/config.toml deleted file mode 100644 index 2f22d454b1..0000000000 --- a/test/tasks/example/eth/021-revshare-setup-without-upgrade-default/config.toml +++ /dev/null @@ -1,22 +0,0 @@ -templateName = "RevShareSetup" - -# Portal and deployment configuration -portal = "0xbEb5Fc579115071764c7423A4f12eDde41f106Ed" # OptimismPortal address -saltSeed = "DeploymentSaltV1" # Deployment salt seed - -# Mode Configuration -shouldUpgradeContracts = false # Setup revenue sharing on already-upgraded contracts -useDefaultCalculator = true # Deploy default SC Rev Share Calculator and L1Withdrawer - -# L1 Withdrawer Configuration (used when useDefaultCalculator = true) -l1WithdrawerMinWithdrawalAmount = 350000 -l1WithdrawerRecipient = "0x742d35Cc6634C0532925a3b8D0C0C8b8B0c0C8b8" # L1 recipient address (e.g., FeesDepositor) -l1WithdrawerGasLimit = 800000 # Gas limit for L1 withdrawal transactions - -# SC Rev Share Calculator Configuration (used when useDefaultCalculator = true) -scRevShareCalcChainFeesRecipient = "0x8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b" # Chain fees recipient - -[addresses] -ProxyAdminOwner = "0x5a0Aae59D09fccBdDb6C6CcEB07B7279367C3d2A" -OptimismPortal = "0xbEb5Fc579115071764c7423A4f12eDde41f106Ed" -RevShareContractsManager = "0x0000000000000000000000000000000000000000" # TODO: Set actual deployed address diff --git a/test/tasks/example/eth/022-revshare-setup-without-upgrade-custom/config.toml b/test/tasks/example/eth/022-revshare-setup-without-upgrade-custom/config.toml deleted file mode 100644 index 86bdd7270c..0000000000 --- a/test/tasks/example/eth/022-revshare-setup-without-upgrade-custom/config.toml +++ /dev/null @@ -1,17 +0,0 @@ -templateName = "RevShareSetup" - -# Portal and deployment configuration -portal = "0xbEb5Fc579115071764c7423A4f12eDde41f106Ed" # OptimismPortal address -saltSeed = "DeploymentSaltV1" # Deployment salt seed - -# Mode Configuration -shouldUpgradeContracts = false # Setup revenue sharing on already-upgraded contracts -useDefaultCalculator = false # Use a custom calculator (skip deploying L1Withdrawer and SC Rev Share Calculator) - -# Custom Calculator Configuration (used when useDefaultCalculator = false) -customCalculator = "0x8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b" # Address of custom calculator contract - -[addresses] -ProxyAdminOwner = "0x5a0Aae59D09fccBdDb6C6CcEB07B7279367C3d2A" -OptimismPortal = "0xbEb5Fc579115071764c7423A4f12eDde41f106Ed" -RevShareContractsManager = "0x0000000000000000000000000000000000000000" # TODO: Set actual deployed address From 29b0cc7ae8b0ea7cdf581939761b0ebeab7c4eb2 Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Thu, 6 Nov 2025 15:19:23 -0300 Subject: [PATCH 09/69] refactor: move interfaces to single files --- src/RevShareContractsUpgrader.sol | 51 ++++++--------------------- src/interfaces/ICreate2Deployer.sol | 7 ++++ src/interfaces/IFeeSplitter.sol | 7 ++++ src/interfaces/IFeeSplitterSetter.sol | 7 ++++ src/interfaces/IFeeVault.sol | 9 +++++ 5 files changed, 40 insertions(+), 41 deletions(-) create mode 100644 src/interfaces/ICreate2Deployer.sol create mode 100644 src/interfaces/IFeeSplitter.sol create mode 100644 src/interfaces/IFeeSplitterSetter.sol create mode 100644 src/interfaces/IFeeVault.sol diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol index 0c272524f3..ecc39fcf65 100644 --- a/src/RevShareContractsUpgrader.sol +++ b/src/RevShareContractsUpgrader.sol @@ -6,44 +6,13 @@ import {RevShareCodeRepo} from "src/libraries/RevShareCodeRepo.sol"; import {RevShareGasLimits} from "src/libraries/RevShareGasLimits.sol"; import {Utils} from "src/libraries/Utils.sol"; -/// @notice Interface for the OptimismPortal2 in L1. -interface IOptimismPortal2 { - function depositTransaction(address _to, uint256 _value, uint64 _gasLimit, bool _isCreation, bytes memory _data) - external - payable; -} - -/// @notice Interface of the Create2 Preinstall in L2. -interface ICreate2Deployer { - function deploy(uint256 _value, bytes32 _salt, bytes memory _code) external; -} - -/// @notice Interface for ProxyAdmin. -interface IProxyAdmin { - function upgradeAndCall(address payable _proxy, address _implementation, bytes memory _data) external; -} - -/// @notice Interface for the FeeSplitter in L2. -interface IFeeSplitter { - function initialize(address _sharesCalculator) external; -} - -/// @notice Interface for the vaults in L2 (initialization). -interface IFeeVault { - function initialize(address _recipient, uint256 _minWithdrawalAmount, uint8 _withdrawalNetwork) external; -} - -/// @notice Interface for vault setters (RevShare vaults have mutable storage). -interface IFeeVaultSetters { - function setRecipient(address _recipient) external; - function setMinWithdrawalAmount(uint256 _minWithdrawalAmount) external; - function setWithdrawalNetwork(uint8 _withdrawalNetwork) external; -} - -/// @notice Interface for FeeSplitter setter. -interface IFeeSplitterSetter { - function setSharesCalculator(address _calculator) external; -} +// 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 {IFeeSplitterSetter} from "src/interfaces/IFeeSplitterSetter.sol"; +import {IFeeVault} from "src/interfaces/IFeeVault.sol"; /// @title RevShareContractsManager /// @notice Upgrader contract that manages RevShare deployments and configuration via delegatecall. @@ -284,17 +253,17 @@ contract RevShareContractsManager is RevSharePredeploys { for (uint256 i = 0; i < vaults.length; i++) { // Set recipient to FeeSplitter IOptimismPortal2(payable(_portal)).depositTransaction( - vaults[i], 0, RevShareGasLimits.SETTERS_GAS_LIMIT, false, abi.encodeCall(IFeeVaultSetters.setRecipient, (FEE_SPLITTER)) + vaults[i], 0, RevShareGasLimits.SETTERS_GAS_LIMIT, false, abi.encodeCall(IFeeVault.setRecipient, (FEE_SPLITTER)) ); // Set minWithdrawalAmount to 0 IOptimismPortal2(payable(_portal)).depositTransaction( - vaults[i], 0, RevShareGasLimits.SETTERS_GAS_LIMIT, false, abi.encodeCall(IFeeVaultSetters.setMinWithdrawalAmount, (0)) + vaults[i], 0, RevShareGasLimits.SETTERS_GAS_LIMIT, false, abi.encodeCall(IFeeVault.setMinWithdrawalAmount, (0)) ); // Set withdrawalNetwork to L2 (1) IOptimismPortal2(payable(_portal)).depositTransaction( - vaults[i], 0, RevShareGasLimits.SETTERS_GAS_LIMIT, false, abi.encodeCall(IFeeVaultSetters.setWithdrawalNetwork, (1)) + vaults[i], 0, RevShareGasLimits.SETTERS_GAS_LIMIT, false, abi.encodeCall(IFeeVault.setWithdrawalNetwork, (1)) ); } } diff --git a/src/interfaces/ICreate2Deployer.sol b/src/interfaces/ICreate2Deployer.sol new file mode 100644 index 0000000000..23b37a16bd --- /dev/null +++ b/src/interfaces/ICreate2Deployer.sol @@ -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; +} diff --git a/src/interfaces/IFeeSplitter.sol b/src/interfaces/IFeeSplitter.sol new file mode 100644 index 0000000000..50a3de4269 --- /dev/null +++ b/src/interfaces/IFeeSplitter.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +/// @notice Interface for the FeeSplitter in L2. +interface IFeeSplitter { + function initialize(address _sharesCalculator) external; +} diff --git a/src/interfaces/IFeeSplitterSetter.sol b/src/interfaces/IFeeSplitterSetter.sol new file mode 100644 index 0000000000..1bc20b2046 --- /dev/null +++ b/src/interfaces/IFeeSplitterSetter.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +/// @notice Interface for FeeSplitter setter. +interface IFeeSplitterSetter { + function setSharesCalculator(address _calculator) external; +} diff --git a/src/interfaces/IFeeVault.sol b/src/interfaces/IFeeVault.sol new file mode 100644 index 0000000000..b28111628e --- /dev/null +++ b/src/interfaces/IFeeVault.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +interface IFeeVault { + function initialize(address _recipient, uint256 _minWithdrawalAmount, uint8 _withdrawalNetwork) external; + function setRecipient(address _recipient) external; + function setMinWithdrawalAmount(uint256 _minWithdrawalAmount) external; + function setWithdrawalNetwork(uint8 _withdrawalNetwork) external; +} From 64a483894b79307add3bceb0fc009ab4d8ec1bf8 Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Thu, 6 Nov 2025 15:23:24 -0300 Subject: [PATCH 10/69] docs: natspec --- src/RevShareContractsUpgrader.sol | 42 +++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol index ecc39fcf65..b6c3d5cdea 100644 --- a/src/RevShareContractsUpgrader.sol +++ b/src/RevShareContractsUpgrader.sol @@ -16,21 +16,28 @@ import {IFeeVault} from "src/interfaces/IFeeVault.sol"; /// @title RevShareContractsManager /// @notice Upgrader contract that manages RevShare deployments and configuration via delegatecall. -/// Supports three operations: +/// @dev Supports three operations: /// 1. upgradeContracts() - Upgrade vault and splitter implementations only /// 2. setupRevShare() - Setup revenue sharing on already-upgraded contracts /// 3. upgradeAndSetupRevShare() - Combined upgrade + setup (most efficient) /// All operations use the default calculator (L1Withdrawer + SuperchainRevenueShareCalculator). contract RevShareContractsManager is RevSharePredeploys { /// @notice Struct for vault configuration. + /// @param proxy Vault proxy address + /// @param recipient Withdrawal recipient + /// @param minWithdrawal Minimum withdrawal amount + /// @param withdrawalNetwork Network for withdrawals (0=L1, 1=L2) struct VaultConfig { - address proxy; // Vault proxy address - address recipient; // Withdrawal recipient - uint256 minWithdrawal; // Minimum withdrawal amount - uint8 withdrawalNetwork; // Network for withdrawals (0=L1, 1=L2) + address proxy; + address recipient; + uint256 minWithdrawal; + uint8 withdrawalNetwork; } /// @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; @@ -117,6 +124,9 @@ contract RevShareContractsManager is RevSharePredeploys { } /// @notice Deploys and upgrades a single vault with custom configuration. + /// @param _portal The OptimismPortal2 address for the target L2 + /// @param _saltSeed The salt seed for CREATE2 deployments + /// @param _config Vault configuration containing proxy address and initialization parameters function _upgradeVault(address _portal, string memory _saltSeed, VaultConfig memory _config) private { require(_config.proxy != address(0), "Vault proxy cannot be zero address"); @@ -172,6 +182,8 @@ contract RevShareContractsManager is RevSharePredeploys { } /// @notice Deploys and upgrades the fee splitter with address(0) calculator (disabled). + /// @param _portal The OptimismPortal2 address for the target L2 + /// @param _saltSeed The salt seed for CREATE2 deployments function _deployAndUpgradeFeeSplitter(address _portal, string memory _saltSeed) private { bytes32 salt = _getSalt(_saltSeed, "FeeSplitter"); bytes memory creationCode = RevShareCodeRepo.feeSplitterCreationCode; @@ -200,6 +212,10 @@ contract RevShareContractsManager is RevSharePredeploys { } /// @notice Deploys L1Withdrawer to L2. + /// @param _portal The OptimismPortal2 address for the target L2 + /// @param _saltSeed The salt seed for CREATE2 deployments + /// @param _config L1Withdrawer configuration + /// @return The deployed L1Withdrawer address function _deployL1Withdrawer(address _portal, string memory _saltSeed, L1WithdrawerConfig memory _config) private returns (address) @@ -223,6 +239,11 @@ contract RevShareContractsManager is RevSharePredeploys { } /// @notice Deploys SuperchainRevenueShareCalculator to L2. + /// @param _portal The OptimismPortal2 address for the target L2 + /// @param _saltSeed The salt seed for CREATE2 deployments + /// @param _l1Withdrawer The L1Withdrawer address + /// @param _chainFeesRecipient The chain fees recipient address + /// @return The deployed calculator address function _deployCalculator( address _portal, string memory _saltSeed, @@ -247,6 +268,7 @@ contract RevShareContractsManager is RevSharePredeploys { } /// @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 = [OPERATOR_FEE_VAULT, SEQUENCER_FEE_WALLET, BASE_FEE_VAULT, L1_FEE_VAULT]; @@ -269,6 +291,8 @@ contract RevShareContractsManager is RevSharePredeploys { } /// @notice Sets the calculator on the fee splitter. + /// @param _portal The OptimismPortal2 address for the target L2 + /// @param _calculator The calculator address to set function _setFeeSplitterCalculator(address _portal, address _calculator) private { IOptimismPortal2(payable(_portal)).depositTransaction( FEE_SPLITTER, @@ -280,6 +304,8 @@ contract RevShareContractsManager is RevSharePredeploys { } /// @notice Upgrades all 4 vaults with RevShare configuration (recipient=FeeSplitter, minWithdrawal=0, network=L2). + /// @param _portal The OptimismPortal2 address for the target L2 + /// @param _saltSeed The salt seed for CREATE2 deployments function _upgradeVaultsWithRevShareConfig(address _portal, string memory _saltSeed) private { address[4] memory vaultProxies = [OPERATOR_FEE_VAULT, SEQUENCER_FEE_WALLET, BASE_FEE_VAULT, L1_FEE_VAULT]; bytes[4] memory creationCodes = [ @@ -325,6 +351,9 @@ contract RevShareContractsManager is RevSharePredeploys { } /// @notice Deploys and upgrades the fee splitter with a calculator. + /// @param _portal The OptimismPortal2 address for the target L2 + /// @param _saltSeed The salt seed for CREATE2 deployments + /// @param _calculator The calculator address to initialize with function _deployAndUpgradeFeeSplitterWithCalculator(address _portal, string memory _saltSeed, address _calculator) private { @@ -355,6 +384,9 @@ contract RevShareContractsManager is RevSharePredeploys { } /// @notice Generates a salt from a prefix and suffix. + /// @param _prefix The prefix string + /// @param _suffix The suffix string + /// @return The generated salt as bytes32 function _getSalt(string memory _prefix, string memory _suffix) private pure returns (bytes32) { return keccak256(abi.encodePacked(bytes(_prefix), bytes(":"), bytes(_suffix))); } From f628e32c481541332f9cb13ab97dd1b33d15ea99 Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Thu, 6 Nov 2025 15:26:37 -0300 Subject: [PATCH 11/69] refactor: use custom errors --- src/RevShareContractsUpgrader.sol | 47 ++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol index b6c3d5cdea..86cca9f547 100644 --- a/src/RevShareContractsUpgrader.sol +++ b/src/RevShareContractsUpgrader.sol @@ -22,6 +22,27 @@ import {IFeeVault} from "src/interfaces/IFeeVault.sol"; /// 3. upgradeAndSetupRevShare() - Combined upgrade + setup (most efficient) /// All operations use the default calculator (L1Withdrawer + SuperchainRevenueShareCalculator). contract RevShareContractsManager is RevSharePredeploys { + /// @notice Thrown when portal address is zero + error PortalCannotBeZeroAddress(); + + /// @notice Thrown when salt seed is empty + error SaltSeedCannotBeEmpty(); + + /// @notice Thrown when vaults array length is not 4 + error VaultsMustBeArrayOf4(); + + /// @notice Thrown when L1Withdrawer recipient is zero address + error L1WithdrawerRecipientCannotBeZeroAddress(); + + /// @notice Thrown when chain fees recipient is zero address + error ChainFeesRecipientCannotBeZeroAddress(); + + /// @notice Thrown when vault proxy address is zero + error VaultProxyCannotBeZeroAddress(); + + /// @notice Thrown when vault proxy address is unknown + error UnknownVaultProxyAddress(); + /// @notice Struct for vault configuration. /// @param proxy Vault proxy address /// @param recipient Withdrawal recipient @@ -50,9 +71,9 @@ contract RevShareContractsManager is RevSharePredeploys { /// @param _saltSeed The salt seed for CREATE2 deployments. /// @param _vaults Array of 4 vault configurations. function upgradeContracts(address _portal, string memory _saltSeed, VaultConfig[] memory _vaults) external { - require(_portal != address(0), "portal cannot be zero address"); - require(bytes(_saltSeed).length != 0, "saltSeed cannot be empty"); - require(_vaults.length == 4, "vaults must be an array of 4"); + if (_portal == address(0)) revert PortalCannotBeZeroAddress(); + if (bytes(_saltSeed).length == 0) revert SaltSeedCannotBeEmpty(); + if (_vaults.length != 4) revert VaultsMustBeArrayOf4(); // Deploy and upgrade each vault with custom config for (uint256 i = 0; i < _vaults.length; i++) { @@ -75,10 +96,10 @@ contract RevShareContractsManager is RevSharePredeploys { L1WithdrawerConfig memory _l1Config, address _chainFeesRecipient ) external { - require(_portal != address(0), "portal cannot be zero address"); - require(bytes(_saltSeed).length != 0, "saltSeed cannot be empty"); - require(_l1Config.recipient != address(0), "L1Withdrawer recipient cannot be zero address"); - require(_chainFeesRecipient != address(0), "chainFeesRecipient cannot be zero address"); + if (_portal == address(0)) revert PortalCannotBeZeroAddress(); + if (bytes(_saltSeed).length == 0) revert SaltSeedCannotBeEmpty(); + if (_l1Config.recipient == address(0)) revert L1WithdrawerRecipientCannotBeZeroAddress(); + if (_chainFeesRecipient == address(0)) revert ChainFeesRecipientCannotBeZeroAddress(); // Deploy L1Withdrawer address l1Withdrawer = _deployL1Withdrawer(_portal, _saltSeed, _l1Config); @@ -105,10 +126,10 @@ contract RevShareContractsManager is RevSharePredeploys { L1WithdrawerConfig memory _l1Config, address _chainFeesRecipient ) external { - require(_portal != address(0), "portal cannot be zero address"); - require(bytes(_saltSeed).length != 0, "saltSeed cannot be empty"); - require(_l1Config.recipient != address(0), "L1Withdrawer recipient cannot be zero address"); - require(_chainFeesRecipient != address(0), "chainFeesRecipient cannot be zero address"); + if (_portal == address(0)) revert PortalCannotBeZeroAddress(); + if (bytes(_saltSeed).length == 0) revert SaltSeedCannotBeEmpty(); + if (_l1Config.recipient == address(0)) revert L1WithdrawerRecipientCannotBeZeroAddress(); + if (_chainFeesRecipient == address(0)) revert ChainFeesRecipientCannotBeZeroAddress(); // Deploy L1Withdrawer address l1Withdrawer = _deployL1Withdrawer(_portal, _saltSeed, _l1Config); @@ -128,7 +149,7 @@ contract RevShareContractsManager is RevSharePredeploys { /// @param _saltSeed The salt seed for CREATE2 deployments /// @param _config Vault configuration containing proxy address and initialization parameters function _upgradeVault(address _portal, string memory _saltSeed, VaultConfig memory _config) private { - require(_config.proxy != address(0), "Vault proxy cannot be zero address"); + if (_config.proxy == address(0)) revert VaultProxyCannotBeZeroAddress(); // Determine which vault type and get the appropriate creation code bytes memory creationCode; @@ -147,7 +168,7 @@ contract RevShareContractsManager is RevSharePredeploys { creationCode = RevShareCodeRepo.l1FeeVaultCreationCode; vaultName = "L1FeeVault"; } else { - revert("Unknown vault proxy address"); + revert UnknownVaultProxyAddress(); } bytes32 salt = _getSalt(_saltSeed, vaultName); From 90ffdeae74b5c39a87eb5f191a72aab01c69845b Mon Sep 17 00:00:00 2001 From: Chiin <77933451+0xChin@users.noreply.github.com> Date: Thu, 6 Nov 2025 15:27:37 -0300 Subject: [PATCH 12/69] chore: improve comments Co-authored-by: Disco <131301107+0xDiscotech@users.noreply.github.com> Signed-off-by: Chiin <77933451+0xChin@users.noreply.github.com> --- src/RevShareContractsUpgrader.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol index 86cca9f547..d8e7b23f8f 100644 --- a/src/RevShareContractsUpgrader.sol +++ b/src/RevShareContractsUpgrader.sol @@ -65,7 +65,7 @@ contract RevShareContractsManager is RevSharePredeploys { uint32 gasLimit; } - /// @notice Upgrades vault and fee splitter contracts with custom configurations. + /// @notice Upgrades vault initializing them with custom configuration and deploys fee splitter initializing it with 0 address as shares calculator since revenue sharing is disabled. /// Vaults are NOT configured for revenue sharing - use setupRevShare() afterwards. /// @param _portal The OptimismPortal2 address for the target L2. /// @param _saltSeed The salt seed for CREATE2 deployments. From 495ecb195d69b6764ea1b09c1f5821e880ff9263 Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Thu, 6 Nov 2025 15:28:22 -0300 Subject: [PATCH 13/69] fix: reorder contracts deployment --- src/RevShareContractsUpgrader.sol | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol index d8e7b23f8f..9d8a1891b4 100644 --- a/src/RevShareContractsUpgrader.sol +++ b/src/RevShareContractsUpgrader.sol @@ -137,11 +137,12 @@ contract RevShareContractsManager is RevSharePredeploys { // Deploy SuperchainRevenueShareCalculator address calculator = _deployCalculator(_portal, _saltSeed, l1Withdrawer, _chainFeesRecipient); + // Upgrade fee splitter and initialize with calculator FIRST + // This prevents the edge case where fees could be sent to an uninitialized FeeSplitter + _deployAndUpgradeFeeSplitterWithCalculator(_portal, _saltSeed, calculator); + // Upgrade all 4 vaults with RevShare configuration (recipient=FeeSplitter, minWithdrawal=0, network=L2) _upgradeVaultsWithRevShareConfig(_portal, _saltSeed); - - // Upgrade fee splitter and initialize with calculator - _deployAndUpgradeFeeSplitterWithCalculator(_portal, _saltSeed, calculator); } /// @notice Deploys and upgrades a single vault with custom configuration. From 96acf0b248061ebb032174193b5f80d504f9a7d8 Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Thu, 6 Nov 2025 15:30:23 -0300 Subject: [PATCH 14/69] chore: improve function naming --- src/RevShareContractsUpgrader.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol index 9d8a1891b4..3f32e9b7f1 100644 --- a/src/RevShareContractsUpgrader.sol +++ b/src/RevShareContractsUpgrader.sol @@ -77,7 +77,7 @@ contract RevShareContractsManager is RevSharePredeploys { // Deploy and upgrade each vault with custom config for (uint256 i = 0; i < _vaults.length; i++) { - _upgradeVault(_portal, _saltSeed, _vaults[i]); + _upgradeVaultWithCustomConfig(_portal, _saltSeed, _vaults[i]); } // Deploy and upgrade fee splitter with address(0) calculator (disabled) @@ -149,7 +149,7 @@ contract RevShareContractsManager is RevSharePredeploys { /// @param _portal The OptimismPortal2 address for the target L2 /// @param _saltSeed The salt seed for CREATE2 deployments /// @param _config Vault configuration containing proxy address and initialization parameters - function _upgradeVault(address _portal, string memory _saltSeed, VaultConfig memory _config) private { + function _upgradeVaultWithCustomConfig(address _portal, string memory _saltSeed, VaultConfig memory _config) private { if (_config.proxy == address(0)) revert VaultProxyCannotBeZeroAddress(); // Determine which vault type and get the appropriate creation code From 4650303b9cc647f976cf3672f689d04bcb536a97 Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Thu, 6 Nov 2025 15:32:42 -0300 Subject: [PATCH 15/69] chore: improve function naming --- src/RevShareContractsUpgrader.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol index 3f32e9b7f1..9c7fef34a8 100644 --- a/src/RevShareContractsUpgrader.sol +++ b/src/RevShareContractsUpgrader.sol @@ -81,7 +81,7 @@ contract RevShareContractsManager is RevSharePredeploys { } // Deploy and upgrade fee splitter with address(0) calculator (disabled) - _deployAndUpgradeFeeSplitter(_portal, _saltSeed); + _deployAndUpgradeFeeSplitterDisabled(_portal, _saltSeed); } /// @notice Setup revenue sharing on already-upgraded contracts. @@ -203,10 +203,10 @@ contract RevShareContractsManager is RevSharePredeploys { ); } - /// @notice Deploys and upgrades the fee splitter with address(0) calculator (disabled). + /// @notice Deploys and upgrades the fee splitter with address(0) calculator (revenue sharing disabled). /// @param _portal The OptimismPortal2 address for the target L2 /// @param _saltSeed The salt seed for CREATE2 deployments - function _deployAndUpgradeFeeSplitter(address _portal, string memory _saltSeed) private { + function _deployAndUpgradeFeeSplitterDisabled(address _portal, string memory _saltSeed) private { bytes32 salt = _getSalt(_saltSeed, "FeeSplitter"); bytes memory creationCode = RevShareCodeRepo.feeSplitterCreationCode; address impl = Utils.getCreate2Address(salt, creationCode, CREATE2_DEPLOYER); From 80d93a19f253e440e173d391b64c1765258359fa Mon Sep 17 00:00:00 2001 From: Chiin <77933451+0xChin@users.noreply.github.com> Date: Thu, 6 Nov 2025 15:34:06 -0300 Subject: [PATCH 16/69] chore: improve comments Co-authored-by: Disco <131301107+0xDiscotech@users.noreply.github.com> Signed-off-by: Chiin <77933451+0xChin@users.noreply.github.com> --- src/RevShareContractsUpgrader.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol index 9c7fef34a8..278d25e29f 100644 --- a/src/RevShareContractsUpgrader.sol +++ b/src/RevShareContractsUpgrader.sol @@ -84,7 +84,7 @@ contract RevShareContractsManager is RevSharePredeploys { _deployAndUpgradeFeeSplitterDisabled(_portal, _saltSeed); } - /// @notice Setup revenue sharing on already-upgraded contracts. + /// @notice Enables revenue sharing after vaults have been upgraded and `FeeSplitter` initialized. /// Deploys L1Withdrawer and calculator, then configures vaults and splitter. /// @param _portal The OptimismPortal2 address for the target L2. /// @param _saltSeed The salt seed for CREATE2 deployments. From 4fb859182ff71c7965f9b8c5c0a88df243add69c Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Fri, 7 Nov 2025 01:24:29 -0300 Subject: [PATCH 17/69] chore(descope): remove upgradeContracts function --- src/RevShareContractsUpgrader.sol | 135 +----------------------------- 1 file changed, 3 insertions(+), 132 deletions(-) diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol index 278d25e29f..e831e4e921 100644 --- a/src/RevShareContractsUpgrader.sol +++ b/src/RevShareContractsUpgrader.sol @@ -16,10 +16,9 @@ import {IFeeVault} from "src/interfaces/IFeeVault.sol"; /// @title RevShareContractsManager /// @notice Upgrader contract that manages RevShare deployments and configuration via delegatecall. -/// @dev Supports three operations: -/// 1. upgradeContracts() - Upgrade vault and splitter implementations only -/// 2. setupRevShare() - Setup revenue sharing on already-upgraded contracts -/// 3. upgradeAndSetupRevShare() - Combined upgrade + setup (most efficient) +/// @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 RevShareContractsManager is RevSharePredeploys { /// @notice Thrown when portal address is zero @@ -28,33 +27,12 @@ contract RevShareContractsManager is RevSharePredeploys { /// @notice Thrown when salt seed is empty error SaltSeedCannotBeEmpty(); - /// @notice Thrown when vaults array length is not 4 - error VaultsMustBeArrayOf4(); - /// @notice Thrown when L1Withdrawer recipient is zero address error L1WithdrawerRecipientCannotBeZeroAddress(); /// @notice Thrown when chain fees recipient is zero address error ChainFeesRecipientCannotBeZeroAddress(); - /// @notice Thrown when vault proxy address is zero - error VaultProxyCannotBeZeroAddress(); - - /// @notice Thrown when vault proxy address is unknown - error UnknownVaultProxyAddress(); - - /// @notice Struct for vault configuration. - /// @param proxy Vault proxy address - /// @param recipient Withdrawal recipient - /// @param minWithdrawal Minimum withdrawal amount - /// @param withdrawalNetwork Network for withdrawals (0=L1, 1=L2) - struct VaultConfig { - address proxy; - address recipient; - uint256 minWithdrawal; - uint8 withdrawalNetwork; - } - /// @notice Struct for L1Withdrawer configuration. /// @param minWithdrawalAmount Minimum withdrawal amount /// @param recipient Recipient address for withdrawals @@ -65,25 +43,6 @@ contract RevShareContractsManager is RevSharePredeploys { uint32 gasLimit; } - /// @notice Upgrades vault initializing them with custom configuration and deploys fee splitter initializing it with 0 address as shares calculator since revenue sharing is disabled. - /// Vaults are NOT configured for revenue sharing - use setupRevShare() afterwards. - /// @param _portal The OptimismPortal2 address for the target L2. - /// @param _saltSeed The salt seed for CREATE2 deployments. - /// @param _vaults Array of 4 vault configurations. - function upgradeContracts(address _portal, string memory _saltSeed, VaultConfig[] memory _vaults) external { - if (_portal == address(0)) revert PortalCannotBeZeroAddress(); - if (bytes(_saltSeed).length == 0) revert SaltSeedCannotBeEmpty(); - if (_vaults.length != 4) revert VaultsMustBeArrayOf4(); - - // Deploy and upgrade each vault with custom config - for (uint256 i = 0; i < _vaults.length; i++) { - _upgradeVaultWithCustomConfig(_portal, _saltSeed, _vaults[i]); - } - - // Deploy and upgrade fee splitter with address(0) calculator (disabled) - _deployAndUpgradeFeeSplitterDisabled(_portal, _saltSeed); - } - /// @notice Enables revenue sharing after vaults have been upgraded and `FeeSplitter` initialized. /// Deploys L1Withdrawer and calculator, then configures vaults and splitter. /// @param _portal The OptimismPortal2 address for the target L2. @@ -145,94 +104,6 @@ contract RevShareContractsManager is RevSharePredeploys { _upgradeVaultsWithRevShareConfig(_portal, _saltSeed); } - /// @notice Deploys and upgrades a single vault with custom configuration. - /// @param _portal The OptimismPortal2 address for the target L2 - /// @param _saltSeed The salt seed for CREATE2 deployments - /// @param _config Vault configuration containing proxy address and initialization parameters - function _upgradeVaultWithCustomConfig(address _portal, string memory _saltSeed, VaultConfig memory _config) private { - if (_config.proxy == address(0)) revert VaultProxyCannotBeZeroAddress(); - - // Determine which vault type and get the appropriate creation code - bytes memory creationCode; - string memory vaultName; - - if (_config.proxy == OPERATOR_FEE_VAULT) { - creationCode = RevShareCodeRepo.operatorFeeVaultCreationCode; - vaultName = "OperatorFeeVault"; - } else if (_config.proxy == SEQUENCER_FEE_WALLET) { - creationCode = RevShareCodeRepo.sequencerFeeVaultCreationCode; - vaultName = "SequencerFeeVault"; - } else if (_config.proxy == BASE_FEE_VAULT) { - creationCode = RevShareCodeRepo.baseFeeVaultCreationCode; - vaultName = "BaseFeeVault"; - } else if (_config.proxy == L1_FEE_VAULT) { - creationCode = RevShareCodeRepo.l1FeeVaultCreationCode; - vaultName = "L1FeeVault"; - } else { - revert UnknownVaultProxyAddress(); - } - - bytes32 salt = _getSalt(_saltSeed, vaultName); - address impl = Utils.getCreate2Address(salt, creationCode, CREATE2_DEPLOYER); - - // Deploy implementation - IOptimismPortal2(payable(_portal)).depositTransaction( - address(CREATE2_DEPLOYER), - 0, - RevShareGasLimits.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, - false, - abi.encodeCall(ICreate2Deployer.deploy, (0, salt, creationCode)) - ); - - // Upgrade proxy and initialize with custom config - IOptimismPortal2(payable(_portal)).depositTransaction( - address(PROXY_ADMIN), - 0, - RevShareGasLimits.UPGRADE_GAS_LIMIT, - false, - abi.encodeCall( - IProxyAdmin.upgradeAndCall, - ( - payable(_config.proxy), - impl, - abi.encodeCall( - IFeeVault.initialize, (_config.recipient, _config.minWithdrawal, _config.withdrawalNetwork) - ) - ) - ) - ); - } - - /// @notice Deploys and upgrades the fee splitter with address(0) calculator (revenue sharing disabled). - /// @param _portal The OptimismPortal2 address for the target L2 - /// @param _saltSeed The salt seed for CREATE2 deployments - function _deployAndUpgradeFeeSplitterDisabled(address _portal, string memory _saltSeed) private { - bytes32 salt = _getSalt(_saltSeed, "FeeSplitter"); - bytes memory creationCode = RevShareCodeRepo.feeSplitterCreationCode; - address impl = Utils.getCreate2Address(salt, creationCode, CREATE2_DEPLOYER); - - // Deploy implementation - IOptimismPortal2(payable(_portal)).depositTransaction( - address(CREATE2_DEPLOYER), - 0, - RevShareGasLimits.FEE_SPLITTER_DEPLOYMENT_GAS_LIMIT, - false, - abi.encodeCall(ICreate2Deployer.deploy, (0, salt, creationCode)) - ); - - // Upgrade proxy and initialize with address(0) calculator (disabled) - IOptimismPortal2(payable(_portal)).depositTransaction( - address(PROXY_ADMIN), - 0, - RevShareGasLimits.UPGRADE_GAS_LIMIT, - false, - abi.encodeCall( - IProxyAdmin.upgradeAndCall, - (payable(FEE_SPLITTER), impl, abi.encodeCall(IFeeSplitter.initialize, (address(0)))) - ) - ); - } - /// @notice Deploys L1Withdrawer to L2. /// @param _portal The OptimismPortal2 address for the target L2 /// @param _saltSeed The salt seed for CREATE2 deployments From 8378bb9295d4eb2fbf36a171964afb2e70d2b0b9 Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Fri, 7 Nov 2025 01:27:57 -0300 Subject: [PATCH 18/69] chore(descope): hardcode saltSeed --- src/RevShareContractsUpgrader.sol | 73 +++++++++++-------------------- 1 file changed, 26 insertions(+), 47 deletions(-) diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol index e831e4e921..dad1fdd11e 100644 --- a/src/RevShareContractsUpgrader.sol +++ b/src/RevShareContractsUpgrader.sol @@ -21,12 +21,12 @@ import {IFeeVault} from "src/interfaces/IFeeVault.sol"; /// 2. upgradeAndSetupRevShare() - Combined upgrade + setup (most efficient) /// All operations use the default calculator (L1Withdrawer + SuperchainRevenueShareCalculator). contract RevShareContractsManager is RevSharePredeploys { + /// @notice Salt seed used for CREATE2 deployments + string private constant SALT_SEED = "RevShare"; + /// @notice Thrown when portal address is zero error PortalCannotBeZeroAddress(); - /// @notice Thrown when salt seed is empty - error SaltSeedCannotBeEmpty(); - /// @notice Thrown when L1Withdrawer recipient is zero address error L1WithdrawerRecipientCannotBeZeroAddress(); @@ -46,25 +46,20 @@ contract RevShareContractsManager is RevSharePredeploys { /// @notice Enables revenue sharing after vaults have been upgraded and `FeeSplitter` initialized. /// Deploys L1Withdrawer and calculator, then configures vaults and splitter. /// @param _portal The OptimismPortal2 address for the target L2. - /// @param _saltSeed The salt seed for CREATE2 deployments. /// @param _l1Config L1Withdrawer configuration. /// @param _chainFeesRecipient The chain fees recipient for the calculator. - function setupRevShare( - address _portal, - string memory _saltSeed, - L1WithdrawerConfig memory _l1Config, - address _chainFeesRecipient - ) external { + function setupRevShare(address _portal, L1WithdrawerConfig memory _l1Config, address _chainFeesRecipient) + external + { if (_portal == address(0)) revert PortalCannotBeZeroAddress(); - if (bytes(_saltSeed).length == 0) revert SaltSeedCannotBeEmpty(); if (_l1Config.recipient == address(0)) revert L1WithdrawerRecipientCannotBeZeroAddress(); if (_chainFeesRecipient == address(0)) revert ChainFeesRecipientCannotBeZeroAddress(); // Deploy L1Withdrawer - address l1Withdrawer = _deployL1Withdrawer(_portal, _saltSeed, _l1Config); + address l1Withdrawer = _deployL1Withdrawer(_portal, _l1Config); // Deploy SuperchainRevenueShareCalculator - address calculator = _deployCalculator(_portal, _saltSeed, l1Withdrawer, _chainFeesRecipient); + address calculator = _deployCalculator(_portal, l1Withdrawer, _chainFeesRecipient); // Configure all 4 vaults for revenue sharing _configureVaultsForRevShare(_portal); @@ -76,48 +71,39 @@ contract RevShareContractsManager is RevSharePredeploys { /// @notice Upgrades vault and splitter contracts and sets up revenue sharing in one transaction. /// This is the most efficient path as vaults are initialized with RevShare config from the start. /// @param _portal The OptimismPortal2 address for the target L2. - /// @param _saltSeed The salt seed for CREATE2 deployments. /// @param _l1Config L1Withdrawer configuration. /// @param _chainFeesRecipient The chain fees recipient for the calculator. - function upgradeAndSetupRevShare( - address _portal, - string memory _saltSeed, - L1WithdrawerConfig memory _l1Config, - address _chainFeesRecipient - ) external { + function upgradeAndSetupRevShare(address _portal, L1WithdrawerConfig memory _l1Config, address _chainFeesRecipient) + external + { if (_portal == address(0)) revert PortalCannotBeZeroAddress(); - if (bytes(_saltSeed).length == 0) revert SaltSeedCannotBeEmpty(); if (_l1Config.recipient == address(0)) revert L1WithdrawerRecipientCannotBeZeroAddress(); if (_chainFeesRecipient == address(0)) revert ChainFeesRecipientCannotBeZeroAddress(); // Deploy L1Withdrawer - address l1Withdrawer = _deployL1Withdrawer(_portal, _saltSeed, _l1Config); + address l1Withdrawer = _deployL1Withdrawer(_portal, _l1Config); // Deploy SuperchainRevenueShareCalculator - address calculator = _deployCalculator(_portal, _saltSeed, l1Withdrawer, _chainFeesRecipient); + address calculator = _deployCalculator(_portal, l1Withdrawer, _chainFeesRecipient); // Upgrade fee splitter and initialize with calculator FIRST // This prevents the edge case where fees could be sent to an uninitialized FeeSplitter - _deployAndUpgradeFeeSplitterWithCalculator(_portal, _saltSeed, calculator); + _deployAndUpgradeFeeSplitterWithCalculator(_portal, calculator); // Upgrade all 4 vaults with RevShare configuration (recipient=FeeSplitter, minWithdrawal=0, network=L2) - _upgradeVaultsWithRevShareConfig(_portal, _saltSeed); + _upgradeVaultsWithRevShareConfig(_portal); } /// @notice Deploys L1Withdrawer to L2. /// @param _portal The OptimismPortal2 address for the target L2 - /// @param _saltSeed The salt seed for CREATE2 deployments /// @param _config L1Withdrawer configuration /// @return The deployed L1Withdrawer address - function _deployL1Withdrawer(address _portal, string memory _saltSeed, L1WithdrawerConfig memory _config) - private - returns (address) - { + function _deployL1Withdrawer(address _portal, L1WithdrawerConfig memory _config) private returns (address) { bytes memory initCode = bytes.concat( RevShareCodeRepo.l1WithdrawerCreationCode, abi.encode(_config.minWithdrawalAmount, _config.recipient, _config.gasLimit) ); - bytes32 salt = _getSalt(_saltSeed, "L1Withdrawer"); + bytes32 salt = _getSalt(SALT_SEED, "L1Withdrawer"); address l1Withdrawer = Utils.getCreate2Address(salt, initCode, CREATE2_DEPLOYER); IOptimismPortal2(payable(_portal)).depositTransaction( @@ -133,20 +119,17 @@ contract RevShareContractsManager is RevSharePredeploys { /// @notice Deploys SuperchainRevenueShareCalculator to L2. /// @param _portal The OptimismPortal2 address for the target L2 - /// @param _saltSeed The salt seed for CREATE2 deployments /// @param _l1Withdrawer The L1Withdrawer address /// @param _chainFeesRecipient The chain fees recipient address /// @return The deployed calculator address - function _deployCalculator( - address _portal, - string memory _saltSeed, - address _l1Withdrawer, - address _chainFeesRecipient - ) private returns (address) { + function _deployCalculator(address _portal, address _l1Withdrawer, address _chainFeesRecipient) + private + returns (address) + { bytes memory initCode = bytes.concat( RevShareCodeRepo.scRevShareCalculatorCreationCode, abi.encode(_l1Withdrawer, _chainFeesRecipient) ); - bytes32 salt = _getSalt(_saltSeed, "SCRevShareCalculator"); + bytes32 salt = _getSalt(SALT_SEED, "SCRevShareCalculator"); address calculator = Utils.getCreate2Address(salt, initCode, CREATE2_DEPLOYER); IOptimismPortal2(payable(_portal)).depositTransaction( @@ -198,8 +181,7 @@ contract RevShareContractsManager is RevSharePredeploys { /// @notice Upgrades all 4 vaults with RevShare configuration (recipient=FeeSplitter, minWithdrawal=0, network=L2). /// @param _portal The OptimismPortal2 address for the target L2 - /// @param _saltSeed The salt seed for CREATE2 deployments - function _upgradeVaultsWithRevShareConfig(address _portal, string memory _saltSeed) private { + function _upgradeVaultsWithRevShareConfig(address _portal) private { address[4] memory vaultProxies = [OPERATOR_FEE_VAULT, SEQUENCER_FEE_WALLET, BASE_FEE_VAULT, L1_FEE_VAULT]; bytes[4] memory creationCodes = [ RevShareCodeRepo.operatorFeeVaultCreationCode, @@ -210,7 +192,7 @@ contract RevShareContractsManager is RevSharePredeploys { string[4] memory vaultNames = ["OperatorFeeVault", "SequencerFeeVault", "BaseFeeVault", "L1FeeVault"]; for (uint256 i = 0; i < 4; i++) { - bytes32 salt = _getSalt(_saltSeed, vaultNames[i]); + bytes32 salt = _getSalt(SALT_SEED, vaultNames[i]); address impl = Utils.getCreate2Address(salt, creationCodes[i], CREATE2_DEPLOYER); // Deploy implementation @@ -245,12 +227,9 @@ contract RevShareContractsManager is RevSharePredeploys { /// @notice Deploys and upgrades the fee splitter with a calculator. /// @param _portal The OptimismPortal2 address for the target L2 - /// @param _saltSeed The salt seed for CREATE2 deployments /// @param _calculator The calculator address to initialize with - function _deployAndUpgradeFeeSplitterWithCalculator(address _portal, string memory _saltSeed, address _calculator) - private - { - bytes32 salt = _getSalt(_saltSeed, "FeeSplitter"); + function _deployAndUpgradeFeeSplitterWithCalculator(address _portal, address _calculator) private { + bytes32 salt = _getSalt(SALT_SEED, "FeeSplitter"); bytes memory creationCode = RevShareCodeRepo.feeSplitterCreationCode; address impl = Utils.getCreate2Address(salt, creationCode, CREATE2_DEPLOYER); From 27503498a9df066651078509aabbf6648afcedd5 Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Fri, 7 Nov 2025 01:37:04 -0300 Subject: [PATCH 19/69] chore(descope): hardcode same salt for all contracts --- src/RevShareContractsUpgrader.sol | 33 ++++++++++--------------------- 1 file changed, 10 insertions(+), 23 deletions(-) diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol index dad1fdd11e..f26a24ec10 100644 --- a/src/RevShareContractsUpgrader.sol +++ b/src/RevShareContractsUpgrader.sol @@ -21,8 +21,8 @@ import {IFeeVault} from "src/interfaces/IFeeVault.sol"; /// 2. upgradeAndSetupRevShare() - Combined upgrade + setup (most efficient) /// All operations use the default calculator (L1Withdrawer + SuperchainRevenueShareCalculator). contract RevShareContractsManager is RevSharePredeploys { - /// @notice Salt seed used for CREATE2 deployments - string private constant SALT_SEED = "RevShare"; + /// @notice Salt used for all CREATE2 deployments + bytes32 private constant SALT = keccak256("RevShare"); /// @notice Thrown when portal address is zero error PortalCannotBeZeroAddress(); @@ -103,15 +103,14 @@ contract RevShareContractsManager is RevSharePredeploys { RevShareCodeRepo.l1WithdrawerCreationCode, abi.encode(_config.minWithdrawalAmount, _config.recipient, _config.gasLimit) ); - bytes32 salt = _getSalt(SALT_SEED, "L1Withdrawer"); - address l1Withdrawer = Utils.getCreate2Address(salt, initCode, CREATE2_DEPLOYER); + address l1Withdrawer = Utils.getCreate2Address(SALT, initCode, CREATE2_DEPLOYER); IOptimismPortal2(payable(_portal)).depositTransaction( address(CREATE2_DEPLOYER), 0, RevShareGasLimits.L1_WITHDRAWER_DEPLOYMENT_GAS_LIMIT, false, - abi.encodeCall(ICreate2Deployer.deploy, (0, salt, initCode)) + abi.encodeCall(ICreate2Deployer.deploy, (0, SALT, initCode)) ); return l1Withdrawer; @@ -129,15 +128,14 @@ contract RevShareContractsManager is RevSharePredeploys { bytes memory initCode = bytes.concat( RevShareCodeRepo.scRevShareCalculatorCreationCode, abi.encode(_l1Withdrawer, _chainFeesRecipient) ); - bytes32 salt = _getSalt(SALT_SEED, "SCRevShareCalculator"); - address calculator = Utils.getCreate2Address(salt, initCode, CREATE2_DEPLOYER); + address calculator = Utils.getCreate2Address(SALT, initCode, CREATE2_DEPLOYER); IOptimismPortal2(payable(_portal)).depositTransaction( address(CREATE2_DEPLOYER), 0, RevShareGasLimits.SC_REV_SHARE_CALCULATOR_DEPLOYMENT_GAS_LIMIT, false, - abi.encodeCall(ICreate2Deployer.deploy, (0, salt, initCode)) + abi.encodeCall(ICreate2Deployer.deploy, (0, SALT, initCode)) ); return calculator; @@ -189,11 +187,9 @@ contract RevShareContractsManager is RevSharePredeploys { RevShareCodeRepo.baseFeeVaultCreationCode, RevShareCodeRepo.l1FeeVaultCreationCode ]; - string[4] memory vaultNames = ["OperatorFeeVault", "SequencerFeeVault", "BaseFeeVault", "L1FeeVault"]; for (uint256 i = 0; i < 4; i++) { - bytes32 salt = _getSalt(SALT_SEED, vaultNames[i]); - address impl = Utils.getCreate2Address(salt, creationCodes[i], CREATE2_DEPLOYER); + address impl = Utils.getCreate2Address(SALT, creationCodes[i], CREATE2_DEPLOYER); // Deploy implementation IOptimismPortal2(payable(_portal)).depositTransaction( @@ -201,7 +197,7 @@ contract RevShareContractsManager is RevSharePredeploys { 0, RevShareGasLimits.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, false, - abi.encodeCall(ICreate2Deployer.deploy, (0, salt, creationCodes[i])) + abi.encodeCall(ICreate2Deployer.deploy, (0, SALT, creationCodes[i])) ); // Upgrade proxy and initialize with RevShare config @@ -229,9 +225,8 @@ contract RevShareContractsManager is RevSharePredeploys { /// @param _portal The OptimismPortal2 address for the target L2 /// @param _calculator The calculator address to initialize with function _deployAndUpgradeFeeSplitterWithCalculator(address _portal, address _calculator) private { - bytes32 salt = _getSalt(SALT_SEED, "FeeSplitter"); bytes memory creationCode = RevShareCodeRepo.feeSplitterCreationCode; - address impl = Utils.getCreate2Address(salt, creationCode, CREATE2_DEPLOYER); + address impl = Utils.getCreate2Address(SALT, creationCode, CREATE2_DEPLOYER); // Deploy implementation IOptimismPortal2(payable(_portal)).depositTransaction( @@ -239,7 +234,7 @@ contract RevShareContractsManager is RevSharePredeploys { 0, RevShareGasLimits.FEE_SPLITTER_DEPLOYMENT_GAS_LIMIT, false, - abi.encodeCall(ICreate2Deployer.deploy, (0, salt, creationCode)) + abi.encodeCall(ICreate2Deployer.deploy, (0, SALT, creationCode)) ); // Upgrade proxy and initialize with calculator @@ -254,12 +249,4 @@ contract RevShareContractsManager is RevSharePredeploys { ) ); } - - /// @notice Generates a salt from a prefix and suffix. - /// @param _prefix The prefix string - /// @param _suffix The suffix string - /// @return The generated salt as bytes32 - function _getSalt(string memory _prefix, string memory _suffix) private pure returns (bytes32) { - return keccak256(abi.encodePacked(bytes(_prefix), bytes(":"), bytes(_suffix))); - } } From 21e825aba973546f62328e27b50c5262996ce511 Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Fri, 7 Nov 2025 01:44:44 -0300 Subject: [PATCH 20/69] feat: allow multiple chain upgrades at once goooood --- src/RevShareContractsUpgrader.sol | 93 +++++++++++++++++++------------ 1 file changed, 56 insertions(+), 37 deletions(-) diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol index f26a24ec10..e4ed9ae829 100644 --- a/src/RevShareContractsUpgrader.sol +++ b/src/RevShareContractsUpgrader.sol @@ -33,6 +33,9 @@ contract RevShareContractsManager is RevSharePredeploys { /// @notice Thrown when chain fees recipient is zero address error ChainFeesRecipientCannotBeZeroAddress(); + /// @notice Thrown when array lengths don't match + error ArrayLengthMismatch(); + /// @notice Struct for L1Withdrawer configuration. /// @param minWithdrawalAmount Minimum withdrawal amount /// @param recipient Recipient address for withdrawals @@ -44,54 +47,70 @@ contract RevShareContractsManager is RevSharePredeploys { } /// @notice Enables revenue sharing after vaults have been upgraded and `FeeSplitter` initialized. - /// Deploys L1Withdrawer and calculator, then configures vaults and splitter. - /// @param _portal The OptimismPortal2 address for the target L2. - /// @param _l1Config L1Withdrawer configuration. - /// @param _chainFeesRecipient The chain fees recipient for the calculator. - function setupRevShare(address _portal, L1WithdrawerConfig memory _l1Config, address _chainFeesRecipient) - external - { - if (_portal == address(0)) revert PortalCannotBeZeroAddress(); - if (_l1Config.recipient == address(0)) revert L1WithdrawerRecipientCannotBeZeroAddress(); - if (_chainFeesRecipient == address(0)) revert ChainFeesRecipientCannotBeZeroAddress(); + /// Deploys L1Withdrawer and calculator, then configures vaults and splitter for multiple chains. + /// @param _portals Array of OptimismPortal2 addresses for the target L2s. + /// @param _l1Configs Array of L1Withdrawer configurations. + /// @param _chainFeesRecipients Array of chain fees recipients for the calculators. + function setupRevShare( + address[] calldata _portals, + L1WithdrawerConfig[] calldata _l1Configs, + address[] calldata _chainFeesRecipients + ) external { + if (_portals.length != _l1Configs.length || _portals.length != _chainFeesRecipients.length) { + revert ArrayLengthMismatch(); + } - // Deploy L1Withdrawer - address l1Withdrawer = _deployL1Withdrawer(_portal, _l1Config); + for (uint256 i = 0; i < _portals.length; i++) { + if (_portals[i] == address(0)) revert PortalCannotBeZeroAddress(); + if (_l1Configs[i].recipient == address(0)) revert L1WithdrawerRecipientCannotBeZeroAddress(); + if (_chainFeesRecipients[i] == address(0)) revert ChainFeesRecipientCannotBeZeroAddress(); - // Deploy SuperchainRevenueShareCalculator - address calculator = _deployCalculator(_portal, l1Withdrawer, _chainFeesRecipient); + // Deploy L1Withdrawer + address l1Withdrawer = _deployL1Withdrawer(_portals[i], _l1Configs[i]); - // Configure all 4 vaults for revenue sharing - _configureVaultsForRevShare(_portal); + // Deploy SuperchainRevenueShareCalculator + address calculator = _deployCalculator(_portals[i], l1Withdrawer, _chainFeesRecipients[i]); - // Set calculator on fee splitter - _setFeeSplitterCalculator(_portal, calculator); + // Configure all 4 vaults for revenue sharing + _configureVaultsForRevShare(_portals[i]); + + // Set calculator on fee splitter + _setFeeSplitterCalculator(_portals[i], calculator); + } } - /// @notice Upgrades vault and splitter contracts and sets up revenue sharing in one transaction. + /// @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 _portal The OptimismPortal2 address for the target L2. - /// @param _l1Config L1Withdrawer configuration. - /// @param _chainFeesRecipient The chain fees recipient for the calculator. - function upgradeAndSetupRevShare(address _portal, L1WithdrawerConfig memory _l1Config, address _chainFeesRecipient) - external - { - if (_portal == address(0)) revert PortalCannotBeZeroAddress(); - if (_l1Config.recipient == address(0)) revert L1WithdrawerRecipientCannotBeZeroAddress(); - if (_chainFeesRecipient == address(0)) revert ChainFeesRecipientCannotBeZeroAddress(); + /// @param _portals Array of OptimismPortal2 addresses for the target L2s. + /// @param _l1Configs Array of L1Withdrawer configurations. + /// @param _chainFeesRecipients Array of chain fees recipients for the calculators. + function upgradeAndSetupRevShare( + address[] calldata _portals, + L1WithdrawerConfig[] calldata _l1Configs, + address[] calldata _chainFeesRecipients + ) external { + if (_portals.length != _l1Configs.length || _portals.length != _chainFeesRecipients.length) { + revert ArrayLengthMismatch(); + } - // Deploy L1Withdrawer - address l1Withdrawer = _deployL1Withdrawer(_portal, _l1Config); + for (uint256 i = 0; i < _portals.length; i++) { + if (_portals[i] == address(0)) revert PortalCannotBeZeroAddress(); + if (_l1Configs[i].recipient == address(0)) revert L1WithdrawerRecipientCannotBeZeroAddress(); + if (_chainFeesRecipients[i] == address(0)) revert ChainFeesRecipientCannotBeZeroAddress(); - // Deploy SuperchainRevenueShareCalculator - address calculator = _deployCalculator(_portal, l1Withdrawer, _chainFeesRecipient); + // Deploy L1Withdrawer + address l1Withdrawer = _deployL1Withdrawer(_portals[i], _l1Configs[i]); - // Upgrade fee splitter and initialize with calculator FIRST - // This prevents the edge case where fees could be sent to an uninitialized FeeSplitter - _deployAndUpgradeFeeSplitterWithCalculator(_portal, calculator); + // Deploy SuperchainRevenueShareCalculator + address calculator = _deployCalculator(_portals[i], l1Withdrawer, _chainFeesRecipients[i]); - // Upgrade all 4 vaults with RevShare configuration (recipient=FeeSplitter, minWithdrawal=0, network=L2) - _upgradeVaultsWithRevShareConfig(_portal); + // Upgrade fee splitter and initialize with calculator FIRST + // This prevents the edge case where fees could be sent to an uninitialized FeeSplitter + _deployAndUpgradeFeeSplitterWithCalculator(_portals[i], calculator); + + // Upgrade all 4 vaults with RevShare configuration (recipient=FeeSplitter, minWithdrawal=0, network=L2) + _upgradeVaultsWithRevShareConfig(_portals[i]); + } } /// @notice Deploys L1Withdrawer to L2. From 30d8d7dd565d73918fb7a88ac80b760754d5302d Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Fri, 7 Nov 2025 02:00:28 -0300 Subject: [PATCH 21/69] test: add integration test --- ...RevShareContractsUpgraderIntegration.t.sol | 186 ++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 test/integration/RevShareContractsUpgraderIntegration.t.sol diff --git a/test/integration/RevShareContractsUpgraderIntegration.t.sol b/test/integration/RevShareContractsUpgraderIntegration.t.sol new file mode 100644 index 0000000000..739808b05f --- /dev/null +++ b/test/integration/RevShareContractsUpgraderIntegration.t.sol @@ -0,0 +1,186 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import {RevShareContractsManager} from "src/RevShareContractsUpgrader.sol"; +import {IntegrationBase} from "./IntegrationBase.t.sol"; +import {Test} from "forge-std/Test.sol"; + +enum WithdrawalNetwork { + L1, + L2 +} + +interface IFeeVault { + function MIN_WITHDRAWAL_AMOUNT() external view returns (uint256); + function RECIPIENT() external view returns (address); + 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); +} + +interface IFeeSplitter { + function sharesCalculator() external view returns (address); +} + +interface IL1Withdrawer { + function minWithdrawalAmount() external view returns (uint256); + function recipient() external view returns (address); + function withdrawalGasLimit() external view returns (uint32); +} + +interface ISuperchainRevSharesCalculator { + function shareRecipient() external view returns (address payable); + function remainderRecipient() external view returns (address payable); +} + +contract RevShareContractsUpgraderIntegrationTest is IntegrationBase { + RevShareContractsManager public revShareManager; + + // Fork IDs + uint256 internal _mainnetForkId; + uint256 internal _opMainnetForkId; + + // L1 addresses + address internal constant PROXY_ADMIN_OWNER = 0x5a0Aae59D09fccBdDb6C6CcEB07B7279367C3d2A; + address internal constant OP_MAINNET_PORTAL = 0xbEb5Fc579115071764c7423A4f12eDde41f106Ed; + + // L2 predeploys (same across all OP Stack chains) + address internal constant SEQUENCER_FEE_VAULT = 0x4200000000000000000000000000000000000011; + address internal constant OPERATOR_FEE_VAULT = 0x420000000000000000000000000000000000001b; + address internal constant BASE_FEE_VAULT = 0x4200000000000000000000000000000000000019; + address internal constant L1_FEE_VAULT = 0x420000000000000000000000000000000000001A; + address internal constant FEE_SPLITTER = 0x420000000000000000000000000000000000002B; + + // Expected deployed contracts (precalculated with CREATE2 and hardcoded SALT) + // These addresses are deterministic based on the SALT = keccak256("RevShare") + address internal constant L1_WITHDRAWER = 0x524E512Dd372C70E7866a7825481385b7b533af0; + address internal constant REV_SHARE_CALCULATOR = 0x72aa66CaA04C9bd83Ecc43c65cff2Cf837EE4BB3; + + // Test configuration + uint256 internal constant MIN_WITHDRAWAL_AMOUNT = 350000; + address internal constant L1_WITHDRAWAL_RECIPIENT = address(1); // Placeholder + uint32 internal constant WITHDRAWAL_GAS_LIMIT = 800000; + address internal constant CHAIN_FEES_RECIPIENT = address(1); // Placeholder + + function setUp() public { + // Create forks for L1 (mainnet) and L2 (OP Mainnet) + _mainnetForkId = vm.createFork("http://127.0.0.1:8545"); + _opMainnetForkId = vm.createFork("http://127.0.0.1:9545"); + + // Deploy RevShareContractsManager on L1 + vm.selectFork(_mainnetForkId); + revShareManager = new RevShareContractsManager(); + } + + /// @notice Test the integration of upgradeAndSetupRevShare + function test_upgradeAndSetupRevShare_integration() public { + // Step 1: Record logs for L1→L2 message replay + vm.recordLogs(); + + // Step 2: Prepare call parameters + address[] memory portals = new address[](1); + portals[0] = OP_MAINNET_PORTAL; + + RevShareContractsManager.L1WithdrawerConfig[] memory l1Configs = + new RevShareContractsManager.L1WithdrawerConfig[](1); + l1Configs[0] = RevShareContractsManager.L1WithdrawerConfig({ + minWithdrawalAmount: MIN_WITHDRAWAL_AMOUNT, + recipient: L1_WITHDRAWAL_RECIPIENT, + gasLimit: WITHDRAWAL_GAS_LIMIT + }); + + address[] memory chainFeesRecipients = new address[](1); + chainFeesRecipients[0] = CHAIN_FEES_RECIPIENT; + + // Step 3: Execute upgradeAndSetupRevShare via delegatecall as ProxyAdmin Owner + bytes memory callData = abi.encodeCall( + RevShareContractsManager.upgradeAndSetupRevShare, + (portals, l1Configs, chainFeesRecipients) + ); + + vm.prank(PROXY_ADMIN_OWNER); + (bool success,) = address(revShareManager).delegatecall(callData); + require(success, "Delegatecall failed"); + + // Step 4: Relay all deposit transactions from L1 to L2 + // Pass false for _isSimulate since we're not using simulate() + _relayAllMessages(_opMainnetForkId, false); + + // Step 5: Assert the state of the L2 contracts + _assertL2State(); + } + + /// @notice Assert the state of all L2 contracts after upgrade + function _assertL2State() internal view { + // L1Withdrawer: check configuration + assertEq(IL1Withdrawer(L1_WITHDRAWER).minWithdrawalAmount(), MIN_WITHDRAWAL_AMOUNT, "L1Withdrawer minWithdrawalAmount mismatch"); + assertEq(IL1Withdrawer(L1_WITHDRAWER).recipient(), L1_WITHDRAWAL_RECIPIENT, "L1Withdrawer recipient mismatch"); + assertEq(IL1Withdrawer(L1_WITHDRAWER).withdrawalGasLimit(), WITHDRAWAL_GAS_LIMIT, "L1Withdrawer gasLimit mismatch"); + + // Rev Share Calculator: check it's linked correctly + assertEq( + ISuperchainRevSharesCalculator(REV_SHARE_CALCULATOR).shareRecipient(), + L1_WITHDRAWER, + "Calculator shareRecipient should be L1Withdrawer" + ); + assertEq( + ISuperchainRevSharesCalculator(REV_SHARE_CALCULATOR).remainderRecipient(), + CHAIN_FEES_RECIPIENT, + "Calculator remainderRecipient mismatch" + ); + + // Fee Splitter: check calculator is set + assertEq( + IFeeSplitter(FEE_SPLITTER).sharesCalculator(), + REV_SHARE_CALCULATOR, + "FeeSplitter calculator should be set to RevShareCalculator" + ); + + // Vaults: recipient should be fee splitter, withdrawal network should be L2, min withdrawal amount 0 + _assertFeeVaultsState(); + } + + /// @notice Assert the configuration of all fee vaults + function _assertFeeVaultsState() internal view { + _assertVaultGetters(SEQUENCER_FEE_VAULT, FEE_SPLITTER, WithdrawalNetwork.L2, 0); + _assertVaultGetters(OPERATOR_FEE_VAULT, FEE_SPLITTER, WithdrawalNetwork.L2, 0); + _assertVaultGetters(BASE_FEE_VAULT, FEE_SPLITTER, WithdrawalNetwork.L2, 0); + _assertVaultGetters(L1_FEE_VAULT, FEE_SPLITTER, WithdrawalNetwork.L2, 0); + } + + /// @notice Assert the configuration of a single fee vault + /// @param _vault The address of the fee vault + /// @param _recipient The expected recipient of the fee vault + /// @param _withdrawalNetwork The expected withdrawal network + /// @param _minWithdrawalAmount The expected minimum withdrawal amount + /// @dev Ensures both the legacy and the new getters return the same value + function _assertVaultGetters( + address _vault, + address _recipient, + WithdrawalNetwork _withdrawalNetwork, + uint256 _minWithdrawalAmount + ) internal view { + // Check new getters + assertEq(IFeeVault(_vault).recipient(), _recipient, "Vault recipient mismatch"); + assertEq( + uint256(IFeeVault(_vault).withdrawalNetwork()), + uint256(_withdrawalNetwork), + "Vault withdrawalNetwork mismatch" + ); + assertEq(IFeeVault(_vault).minWithdrawalAmount(), _minWithdrawalAmount, "Vault minWithdrawalAmount mismatch"); + + // Check legacy getters (should return same values) + assertEq(IFeeVault(_vault).RECIPIENT(), _recipient, "Vault RECIPIENT (legacy) mismatch"); + assertEq( + uint256(IFeeVault(_vault).WITHDRAWAL_NETWORK()), + uint256(_withdrawalNetwork), + "Vault WITHDRAWAL_NETWORK (legacy) mismatch" + ); + assertEq( + IFeeVault(_vault).MIN_WITHDRAWAL_AMOUNT(), + _minWithdrawalAmount, + "Vault MIN_WITHDRAWAL_AMOUNT (legacy) mismatch" + ); + } +} From 77965ec24de90f02443c62760ac5c217d3665536 Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Fri, 7 Nov 2025 02:20:58 -0300 Subject: [PATCH 22/69] fix: colission due to default salt --- src/RevShareContractsUpgrader.sol | 32 +++++++++++++------ ...RevShareContractsUpgraderIntegration.t.sol | 7 ++-- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol index e4ed9ae829..4921867e03 100644 --- a/src/RevShareContractsUpgrader.sol +++ b/src/RevShareContractsUpgrader.sol @@ -21,8 +21,8 @@ import {IFeeVault} from "src/interfaces/IFeeVault.sol"; /// 2. upgradeAndSetupRevShare() - Combined upgrade + setup (most efficient) /// All operations use the default calculator (L1Withdrawer + SuperchainRevenueShareCalculator). contract RevShareContractsManager is RevSharePredeploys { - /// @notice Salt used for all CREATE2 deployments - bytes32 private constant SALT = keccak256("RevShare"); + /// @notice Base salt seed for CREATE2 deployments + string private constant SALT_SEED = "RevShare"; /// @notice Thrown when portal address is zero error PortalCannotBeZeroAddress(); @@ -122,14 +122,15 @@ contract RevShareContractsManager is RevSharePredeploys { RevShareCodeRepo.l1WithdrawerCreationCode, abi.encode(_config.minWithdrawalAmount, _config.recipient, _config.gasLimit) ); - address l1Withdrawer = Utils.getCreate2Address(SALT, initCode, CREATE2_DEPLOYER); + bytes32 salt = _getSalt("L1Withdrawer"); + address l1Withdrawer = Utils.getCreate2Address(salt, initCode, CREATE2_DEPLOYER); IOptimismPortal2(payable(_portal)).depositTransaction( address(CREATE2_DEPLOYER), 0, RevShareGasLimits.L1_WITHDRAWER_DEPLOYMENT_GAS_LIMIT, false, - abi.encodeCall(ICreate2Deployer.deploy, (0, SALT, initCode)) + abi.encodeCall(ICreate2Deployer.deploy, (0, salt, initCode)) ); return l1Withdrawer; @@ -147,14 +148,15 @@ contract RevShareContractsManager is RevSharePredeploys { bytes memory initCode = bytes.concat( RevShareCodeRepo.scRevShareCalculatorCreationCode, abi.encode(_l1Withdrawer, _chainFeesRecipient) ); - address calculator = Utils.getCreate2Address(SALT, initCode, CREATE2_DEPLOYER); + bytes32 salt = _getSalt("SCRevShareCalculator"); + address calculator = Utils.getCreate2Address(salt, initCode, CREATE2_DEPLOYER); IOptimismPortal2(payable(_portal)).depositTransaction( address(CREATE2_DEPLOYER), 0, RevShareGasLimits.SC_REV_SHARE_CALCULATOR_DEPLOYMENT_GAS_LIMIT, false, - abi.encodeCall(ICreate2Deployer.deploy, (0, SALT, initCode)) + abi.encodeCall(ICreate2Deployer.deploy, (0, salt, initCode)) ); return calculator; @@ -206,9 +208,11 @@ contract RevShareContractsManager is RevSharePredeploys { RevShareCodeRepo.baseFeeVaultCreationCode, RevShareCodeRepo.l1FeeVaultCreationCode ]; + string[4] memory vaultNames = ["OperatorFeeVault", "SequencerFeeVault", "BaseFeeVault", "L1FeeVault"]; for (uint256 i = 0; i < 4; i++) { - address impl = Utils.getCreate2Address(SALT, creationCodes[i], CREATE2_DEPLOYER); + bytes32 salt = _getSalt(vaultNames[i]); + address impl = Utils.getCreate2Address(salt, creationCodes[i], CREATE2_DEPLOYER); // Deploy implementation IOptimismPortal2(payable(_portal)).depositTransaction( @@ -216,7 +220,7 @@ contract RevShareContractsManager is RevSharePredeploys { 0, RevShareGasLimits.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, false, - abi.encodeCall(ICreate2Deployer.deploy, (0, SALT, creationCodes[i])) + abi.encodeCall(ICreate2Deployer.deploy, (0, salt, creationCodes[i])) ); // Upgrade proxy and initialize with RevShare config @@ -245,7 +249,8 @@ contract RevShareContractsManager is RevSharePredeploys { /// @param _calculator The calculator address to initialize with function _deployAndUpgradeFeeSplitterWithCalculator(address _portal, address _calculator) private { bytes memory creationCode = RevShareCodeRepo.feeSplitterCreationCode; - address impl = Utils.getCreate2Address(SALT, creationCode, CREATE2_DEPLOYER); + bytes32 salt = _getSalt("FeeSplitter"); + address impl = Utils.getCreate2Address(salt, creationCode, CREATE2_DEPLOYER); // Deploy implementation IOptimismPortal2(payable(_portal)).depositTransaction( @@ -253,7 +258,7 @@ contract RevShareContractsManager is RevSharePredeploys { 0, RevShareGasLimits.FEE_SPLITTER_DEPLOYMENT_GAS_LIMIT, false, - abi.encodeCall(ICreate2Deployer.deploy, (0, SALT, creationCode)) + abi.encodeCall(ICreate2Deployer.deploy, (0, salt, creationCode)) ); // Upgrade proxy and initialize with calculator @@ -268,4 +273,11 @@ contract RevShareContractsManager is RevSharePredeploys { ) ); } + + /// @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)); + } } diff --git a/test/integration/RevShareContractsUpgraderIntegration.t.sol b/test/integration/RevShareContractsUpgraderIntegration.t.sol index 739808b05f..9339ec8fb2 100644 --- a/test/integration/RevShareContractsUpgraderIntegration.t.sol +++ b/test/integration/RevShareContractsUpgraderIntegration.t.sol @@ -52,10 +52,9 @@ contract RevShareContractsUpgraderIntegrationTest is IntegrationBase { address internal constant L1_FEE_VAULT = 0x420000000000000000000000000000000000001A; address internal constant FEE_SPLITTER = 0x420000000000000000000000000000000000002B; - // Expected deployed contracts (precalculated with CREATE2 and hardcoded SALT) - // These addresses are deterministic based on the SALT = keccak256("RevShare") - address internal constant L1_WITHDRAWER = 0x524E512Dd372C70E7866a7825481385b7b533af0; - address internal constant REV_SHARE_CALCULATOR = 0x72aa66CaA04C9bd83Ecc43c65cff2Cf837EE4BB3; + // Expected deployed contracts (deterministic CREATE2 addresses) + address internal constant L1_WITHDRAWER = 0x1aF7f9310029851c75843c3E393b0012dCC38260; + address internal constant REV_SHARE_CALCULATOR = 0x1E32f55E539aD75b90bEAD33347B43264755a178; // Test configuration uint256 internal constant MIN_WITHDRAWAL_AMOUNT = 350000; From ee1d78b5dfe861eef13bb1ed840e6204b86fc9c4 Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Fri, 7 Nov 2025 02:39:05 -0300 Subject: [PATCH 23/69] test: add integration test with delegatecall --- ...RevShareContractsUpgraderIntegration.t.sol | 28 +++++++++++++++---- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/test/integration/RevShareContractsUpgraderIntegration.t.sol b/test/integration/RevShareContractsUpgraderIntegration.t.sol index 9339ec8fb2..6251c80a6e 100644 --- a/test/integration/RevShareContractsUpgraderIntegration.t.sol +++ b/test/integration/RevShareContractsUpgraderIntegration.t.sol @@ -34,8 +34,16 @@ interface ISuperchainRevSharesCalculator { function remainderRecipient() external view returns (address payable); } +/// @notice Simple contract to simulate a Safe executing delegatecall +contract SafeSimulator { + function executeDelegatecall(address target, bytes memory data) external returns (bool success, bytes memory returnData) { + return target.delegatecall(data); + } +} + contract RevShareContractsUpgraderIntegrationTest is IntegrationBase { RevShareContractsManager public revShareManager; + SafeSimulator public safeSimulator; // Fork IDs uint256 internal _mainnetForkId; @@ -53,8 +61,8 @@ contract RevShareContractsUpgraderIntegrationTest is IntegrationBase { address internal constant FEE_SPLITTER = 0x420000000000000000000000000000000000002B; // Expected deployed contracts (deterministic CREATE2 addresses) - address internal constant L1_WITHDRAWER = 0x1aF7f9310029851c75843c3E393b0012dCC38260; - address internal constant REV_SHARE_CALCULATOR = 0x1E32f55E539aD75b90bEAD33347B43264755a178; + address internal constant L1_WITHDRAWER = 0xB3AeB34b88D73Fb4832f65BEa5Bd865017fB5daC; + address internal constant REV_SHARE_CALCULATOR = 0x3E806Fd8592366E850197FEC8D80608b5526Bba2; // Test configuration uint256 internal constant MIN_WITHDRAWAL_AMOUNT = 350000; @@ -67,8 +75,16 @@ contract RevShareContractsUpgraderIntegrationTest is IntegrationBase { _mainnetForkId = vm.createFork("http://127.0.0.1:8545"); _opMainnetForkId = vm.createFork("http://127.0.0.1:9545"); - // Deploy RevShareContractsManager on L1 + // Deploy contracts on L1 vm.selectFork(_mainnetForkId); + + // Deploy SafeSimulator at PROXY_ADMIN_OWNER address using vm.etch + // This simulates the Safe that will execute the delegatecall + bytes memory safeSimulatorCode = type(SafeSimulator).runtimeCode; + vm.etch(PROXY_ADMIN_OWNER, safeSimulatorCode); + safeSimulator = SafeSimulator(PROXY_ADMIN_OWNER); + + // Deploy RevShareContractsManager revShareManager = new RevShareContractsManager(); } @@ -92,14 +108,14 @@ contract RevShareContractsUpgraderIntegrationTest is IntegrationBase { address[] memory chainFeesRecipients = new address[](1); chainFeesRecipients[0] = CHAIN_FEES_RECIPIENT; - // Step 3: Execute upgradeAndSetupRevShare via delegatecall as ProxyAdmin Owner + // Step 3: Execute upgradeAndSetupRevShare via delegatecall from SafeSimulator + // This simulates how the Safe will execute this in production bytes memory callData = abi.encodeCall( RevShareContractsManager.upgradeAndSetupRevShare, (portals, l1Configs, chainFeesRecipients) ); - vm.prank(PROXY_ADMIN_OWNER); - (bool success,) = address(revShareManager).delegatecall(callData); + (bool success,) = safeSimulator.executeDelegatecall(address(revShareManager), callData); require(success, "Delegatecall failed"); // Step 4: Relay all deposit transactions from L1 to L2 From 1524459fc3d662ecd257adfb17d2e32883524745 Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Fri, 7 Nov 2025 13:27:08 -0300 Subject: [PATCH 24/69] perf: remove default variable init --- src/RevShareContractsUpgrader.sol | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol index 4921867e03..a46f3e5180 100644 --- a/src/RevShareContractsUpgrader.sol +++ b/src/RevShareContractsUpgrader.sol @@ -60,7 +60,7 @@ contract RevShareContractsManager is RevSharePredeploys { revert ArrayLengthMismatch(); } - for (uint256 i = 0; i < _portals.length; i++) { + for (uint256 i; i < _portals.length; i++) { if (_portals[i] == address(0)) revert PortalCannotBeZeroAddress(); if (_l1Configs[i].recipient == address(0)) revert L1WithdrawerRecipientCannotBeZeroAddress(); if (_chainFeesRecipients[i] == address(0)) revert ChainFeesRecipientCannotBeZeroAddress(); @@ -93,7 +93,7 @@ contract RevShareContractsManager is RevSharePredeploys { revert ArrayLengthMismatch(); } - for (uint256 i = 0; i < _portals.length; i++) { + for (uint256 i; i < _portals.length; i++) { if (_portals[i] == address(0)) revert PortalCannotBeZeroAddress(); if (_l1Configs[i].recipient == address(0)) revert L1WithdrawerRecipientCannotBeZeroAddress(); if (_chainFeesRecipients[i] == address(0)) revert ChainFeesRecipientCannotBeZeroAddress(); @@ -167,7 +167,7 @@ contract RevShareContractsManager is RevSharePredeploys { function _configureVaultsForRevShare(address _portal) private { address[4] memory vaults = [OPERATOR_FEE_VAULT, SEQUENCER_FEE_WALLET, BASE_FEE_VAULT, L1_FEE_VAULT]; - for (uint256 i = 0; i < vaults.length; i++) { + for (uint256 i; i < vaults.length; i++) { // Set recipient to FeeSplitter IOptimismPortal2(payable(_portal)).depositTransaction( vaults[i], 0, RevShareGasLimits.SETTERS_GAS_LIMIT, false, abi.encodeCall(IFeeVault.setRecipient, (FEE_SPLITTER)) @@ -210,7 +210,7 @@ contract RevShareContractsManager is RevSharePredeploys { ]; string[4] memory vaultNames = ["OperatorFeeVault", "SequencerFeeVault", "BaseFeeVault", "L1FeeVault"]; - for (uint256 i = 0; i < 4; i++) { + for (uint256 i; i < 4; i++) { bytes32 salt = _getSalt(vaultNames[i]); address impl = Utils.getCreate2Address(salt, creationCodes[i], CREATE2_DEPLOYER); From 528e60b2939f1539a231ce58f863e5dcfc907d4c Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Fri, 7 Nov 2025 13:28:49 -0300 Subject: [PATCH 25/69] refactor: remove magic number usage --- src/RevShareContractsUpgrader.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol index a46f3e5180..92c3c93ea0 100644 --- a/src/RevShareContractsUpgrader.sol +++ b/src/RevShareContractsUpgrader.sol @@ -210,7 +210,7 @@ contract RevShareContractsManager is RevSharePredeploys { ]; string[4] memory vaultNames = ["OperatorFeeVault", "SequencerFeeVault", "BaseFeeVault", "L1FeeVault"]; - for (uint256 i; i < 4; i++) { + for (uint256 i; i < vaultProxies.length; i++) { bytes32 salt = _getSalt(vaultNames[i]); address impl = Utils.getCreate2Address(salt, creationCodes[i], CREATE2_DEPLOYER); From e8b4b3b40aa31ec3d147d6eb8bb9896fc48eb1f3 Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Fri, 7 Nov 2025 13:47:12 -0300 Subject: [PATCH 26/69] refactor: use helper functions for portal deposits --- src/RevShareContractsUpgrader.sol | 209 ++++++++++++++---------------- 1 file changed, 95 insertions(+), 114 deletions(-) diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol index 92c3c93ea0..5170b990b4 100644 --- a/src/RevShareContractsUpgrader.sol +++ b/src/RevShareContractsUpgrader.sol @@ -66,16 +66,42 @@ contract RevShareContractsManager is RevSharePredeploys { if (_chainFeesRecipients[i] == address(0)) revert ChainFeesRecipientCannotBeZeroAddress(); // Deploy L1Withdrawer - address l1Withdrawer = _deployL1Withdrawer(_portals[i], _l1Configs[i]); + bytes memory l1WithdrawerInitCode = bytes.concat( + RevShareCodeRepo.l1WithdrawerCreationCode, + abi.encode(_l1Configs[i].minWithdrawalAmount, _l1Configs[i].recipient, _l1Configs[i].gasLimit) + ); + bytes32 l1WithdrawerSalt = _getSalt("L1Withdrawer"); + address l1Withdrawer = Utils.getCreate2Address(l1WithdrawerSalt, l1WithdrawerInitCode, CREATE2_DEPLOYER); + _depositCreate2( + _portals[i], + RevShareGasLimits.L1_WITHDRAWER_DEPLOYMENT_GAS_LIMIT, + l1WithdrawerSalt, + l1WithdrawerInitCode + ); // Deploy SuperchainRevenueShareCalculator - address calculator = _deployCalculator(_portals[i], l1Withdrawer, _chainFeesRecipients[i]); + bytes memory calculatorInitCode = bytes.concat( + RevShareCodeRepo.scRevShareCalculatorCreationCode, abi.encode(l1Withdrawer, _chainFeesRecipients[i]) + ); + bytes32 calculatorSalt = _getSalt("SCRevShareCalculator"); + address calculator = Utils.getCreate2Address(calculatorSalt, calculatorInitCode, CREATE2_DEPLOYER); + _depositCreate2( + _portals[i], + RevShareGasLimits.SC_REV_SHARE_CALCULATOR_DEPLOYMENT_GAS_LIMIT, + calculatorSalt, + calculatorInitCode + ); // Configure all 4 vaults for revenue sharing _configureVaultsForRevShare(_portals[i]); // Set calculator on fee splitter - _setFeeSplitterCalculator(_portals[i], calculator); + _depositCall( + _portals[i], + FEE_SPLITTER, + RevShareGasLimits.SETTERS_GAS_LIMIT, + abi.encodeCall(IFeeSplitterSetter.setSharesCalculator, (calculator)) + ); } } @@ -99,105 +125,76 @@ contract RevShareContractsManager is RevSharePredeploys { if (_chainFeesRecipients[i] == address(0)) revert ChainFeesRecipientCannotBeZeroAddress(); // Deploy L1Withdrawer - address l1Withdrawer = _deployL1Withdrawer(_portals[i], _l1Configs[i]); + bytes memory l1WithdrawerInitCode = bytes.concat( + RevShareCodeRepo.l1WithdrawerCreationCode, + abi.encode(_l1Configs[i].minWithdrawalAmount, _l1Configs[i].recipient, _l1Configs[i].gasLimit) + ); + bytes32 l1WithdrawerSalt = _getSalt("L1Withdrawer"); + address l1Withdrawer = Utils.getCreate2Address(l1WithdrawerSalt, l1WithdrawerInitCode, CREATE2_DEPLOYER); + _depositCreate2( + _portals[i], + RevShareGasLimits.L1_WITHDRAWER_DEPLOYMENT_GAS_LIMIT, + l1WithdrawerSalt, + l1WithdrawerInitCode + ); // Deploy SuperchainRevenueShareCalculator - address calculator = _deployCalculator(_portals[i], l1Withdrawer, _chainFeesRecipients[i]); + bytes memory calculatorInitCode = bytes.concat( + RevShareCodeRepo.scRevShareCalculatorCreationCode, abi.encode(l1Withdrawer, _chainFeesRecipients[i]) + ); + bytes32 calculatorSalt = _getSalt("SCRevShareCalculator"); + address calculator = Utils.getCreate2Address(calculatorSalt, calculatorInitCode, CREATE2_DEPLOYER); + _depositCreate2( + _portals[i], + RevShareGasLimits.SC_REV_SHARE_CALCULATOR_DEPLOYMENT_GAS_LIMIT, + calculatorSalt, + calculatorInitCode + ); // Upgrade fee splitter and initialize with calculator FIRST // This prevents the edge case where fees could be sent to an uninitialized FeeSplitter - _deployAndUpgradeFeeSplitterWithCalculator(_portals[i], calculator); + bytes32 feeSplitterSalt = _getSalt("FeeSplitter"); + address feeSplitterImpl = + Utils.getCreate2Address(feeSplitterSalt, RevShareCodeRepo.feeSplitterCreationCode, CREATE2_DEPLOYER); + _depositCreate2( + _portals[i], + RevShareGasLimits.FEE_SPLITTER_DEPLOYMENT_GAS_LIMIT, + feeSplitterSalt, + RevShareCodeRepo.feeSplitterCreationCode + ); + _depositCall( + _portals[i], + address(PROXY_ADMIN), + RevShareGasLimits.UPGRADE_GAS_LIMIT, + abi.encodeCall( + IProxyAdmin.upgradeAndCall, + (payable(FEE_SPLITTER), feeSplitterImpl, abi.encodeCall(IFeeSplitter.initialize, (calculator))) + ) + ); // Upgrade all 4 vaults with RevShare configuration (recipient=FeeSplitter, minWithdrawal=0, network=L2) _upgradeVaultsWithRevShareConfig(_portals[i]); } } - /// @notice Deploys L1Withdrawer to L2. - /// @param _portal The OptimismPortal2 address for the target L2 - /// @param _config L1Withdrawer configuration - /// @return The deployed L1Withdrawer address - function _deployL1Withdrawer(address _portal, L1WithdrawerConfig memory _config) private returns (address) { - bytes memory initCode = bytes.concat( - RevShareCodeRepo.l1WithdrawerCreationCode, - abi.encode(_config.minWithdrawalAmount, _config.recipient, _config.gasLimit) - ); - bytes32 salt = _getSalt("L1Withdrawer"); - address l1Withdrawer = Utils.getCreate2Address(salt, initCode, CREATE2_DEPLOYER); - - IOptimismPortal2(payable(_portal)).depositTransaction( - address(CREATE2_DEPLOYER), - 0, - RevShareGasLimits.L1_WITHDRAWER_DEPLOYMENT_GAS_LIMIT, - false, - abi.encodeCall(ICreate2Deployer.deploy, (0, salt, initCode)) - ); - - return l1Withdrawer; - } - - /// @notice Deploys SuperchainRevenueShareCalculator to L2. - /// @param _portal The OptimismPortal2 address for the target L2 - /// @param _l1Withdrawer The L1Withdrawer address - /// @param _chainFeesRecipient The chain fees recipient address - /// @return The deployed calculator address - function _deployCalculator(address _portal, address _l1Withdrawer, address _chainFeesRecipient) - private - returns (address) - { - bytes memory initCode = bytes.concat( - RevShareCodeRepo.scRevShareCalculatorCreationCode, abi.encode(_l1Withdrawer, _chainFeesRecipient) - ); - bytes32 salt = _getSalt("SCRevShareCalculator"); - address calculator = Utils.getCreate2Address(salt, initCode, CREATE2_DEPLOYER); - - IOptimismPortal2(payable(_portal)).depositTransaction( - address(CREATE2_DEPLOYER), - 0, - RevShareGasLimits.SC_REV_SHARE_CALCULATOR_DEPLOYMENT_GAS_LIMIT, - false, - abi.encodeCall(ICreate2Deployer.deploy, (0, salt, initCode)) - ); - - return calculator; - } - /// @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 = [OPERATOR_FEE_VAULT, SEQUENCER_FEE_WALLET, BASE_FEE_VAULT, L1_FEE_VAULT]; for (uint256 i; i < vaults.length; i++) { - // Set recipient to FeeSplitter - IOptimismPortal2(payable(_portal)).depositTransaction( - vaults[i], 0, RevShareGasLimits.SETTERS_GAS_LIMIT, false, abi.encodeCall(IFeeVault.setRecipient, (FEE_SPLITTER)) + _depositCall( + _portal, vaults[i], RevShareGasLimits.SETTERS_GAS_LIMIT, abi.encodeCall(IFeeVault.setRecipient, (FEE_SPLITTER)) ); - - // Set minWithdrawalAmount to 0 - IOptimismPortal2(payable(_portal)).depositTransaction( - vaults[i], 0, RevShareGasLimits.SETTERS_GAS_LIMIT, false, abi.encodeCall(IFeeVault.setMinWithdrawalAmount, (0)) + _depositCall( + _portal, vaults[i], RevShareGasLimits.SETTERS_GAS_LIMIT, abi.encodeCall(IFeeVault.setMinWithdrawalAmount, (0)) ); - - // Set withdrawalNetwork to L2 (1) - IOptimismPortal2(payable(_portal)).depositTransaction( - vaults[i], 0, RevShareGasLimits.SETTERS_GAS_LIMIT, false, abi.encodeCall(IFeeVault.setWithdrawalNetwork, (1)) + _depositCall( + _portal, vaults[i], RevShareGasLimits.SETTERS_GAS_LIMIT, abi.encodeCall(IFeeVault.setWithdrawalNetwork, (1)) ); } } - /// @notice Sets the calculator on the fee splitter. - /// @param _portal The OptimismPortal2 address for the target L2 - /// @param _calculator The calculator address to set - function _setFeeSplitterCalculator(address _portal, address _calculator) private { - IOptimismPortal2(payable(_portal)).depositTransaction( - FEE_SPLITTER, - 0, - RevShareGasLimits.SETTERS_GAS_LIMIT, - false, - abi.encodeCall(IFeeSplitterSetter.setSharesCalculator, (_calculator)) - ); - } - /// @notice Upgrades all 4 vaults with RevShare configuration (recipient=FeeSplitter, minWithdrawal=0, network=L2). /// @param _portal The OptimismPortal2 address for the target L2 function _upgradeVaultsWithRevShareConfig(address _portal) private { @@ -214,21 +211,11 @@ contract RevShareContractsManager is RevSharePredeploys { bytes32 salt = _getSalt(vaultNames[i]); address impl = Utils.getCreate2Address(salt, creationCodes[i], CREATE2_DEPLOYER); - // Deploy implementation - IOptimismPortal2(payable(_portal)).depositTransaction( - address(CREATE2_DEPLOYER), - 0, - RevShareGasLimits.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, - false, - abi.encodeCall(ICreate2Deployer.deploy, (0, salt, creationCodes[i])) - ); - - // Upgrade proxy and initialize with RevShare config - IOptimismPortal2(payable(_portal)).depositTransaction( + _depositCreate2(_portal, RevShareGasLimits.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, salt, creationCodes[i]); + _depositCall( + _portal, address(PROXY_ADMIN), - 0, RevShareGasLimits.UPGRADE_GAS_LIMIT, - false, abi.encodeCall( IProxyAdmin.upgradeAndCall, ( @@ -244,34 +231,28 @@ contract RevShareContractsManager is RevSharePredeploys { } } - /// @notice Deploys and upgrades the fee splitter with a calculator. - /// @param _portal The OptimismPortal2 address for the target L2 - /// @param _calculator The calculator address to initialize with - function _deployAndUpgradeFeeSplitterWithCalculator(address _portal, address _calculator) private { - bytes memory creationCode = RevShareCodeRepo.feeSplitterCreationCode; - bytes32 salt = _getSalt("FeeSplitter"); - address impl = Utils.getCreate2Address(salt, creationCode, CREATE2_DEPLOYER); - - // Deploy implementation + /// @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(CREATE2_DEPLOYER), 0, - RevShareGasLimits.FEE_SPLITTER_DEPLOYMENT_GAS_LIMIT, + _gasLimit, false, - abi.encodeCall(ICreate2Deployer.deploy, (0, salt, creationCode)) + abi.encodeCall(ICreate2Deployer.deploy, (0, _salt, _initCode)) ); + } - // Upgrade proxy and initialize with calculator - IOptimismPortal2(payable(_portal)).depositTransaction( - address(PROXY_ADMIN), - 0, - RevShareGasLimits.UPGRADE_GAS_LIMIT, - false, - abi.encodeCall( - IProxyAdmin.upgradeAndCall, - (payable(FEE_SPLITTER), impl, abi.encodeCall(IFeeSplitter.initialize, (_calculator))) - ) - ); + /// @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. From 66626366685eb304901056f2dbcd04e027d0283e Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Fri, 7 Nov 2025 14:00:48 -0300 Subject: [PATCH 27/69] refactor: move main case to beginning --- src/RevShareContractsUpgrader.sol | 66 +++++++++++++++---------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol index 5170b990b4..1e68c59d1e 100644 --- a/src/RevShareContractsUpgrader.sol +++ b/src/RevShareContractsUpgrader.sol @@ -46,12 +46,12 @@ contract RevShareContractsManager is RevSharePredeploys { uint32 gasLimit; } - /// @notice Enables revenue sharing after vaults have been upgraded and `FeeSplitter` initialized. - /// Deploys L1Withdrawer and calculator, then configures vaults and splitter for multiple chains. + /// @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 _portals Array of OptimismPortal2 addresses for the target L2s. /// @param _l1Configs Array of L1Withdrawer configurations. /// @param _chainFeesRecipients Array of chain fees recipients for the calculators. - function setupRevShare( + function upgradeAndSetupRevShare( address[] calldata _portals, L1WithdrawerConfig[] calldata _l1Configs, address[] calldata _chainFeesRecipients @@ -92,25 +92,38 @@ contract RevShareContractsManager is RevSharePredeploys { calculatorInitCode ); - // Configure all 4 vaults for revenue sharing - _configureVaultsForRevShare(_portals[i]); - - // Set calculator on fee splitter + // 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, RevShareCodeRepo.feeSplitterCreationCode, CREATE2_DEPLOYER); + _depositCreate2( + _portals[i], + RevShareGasLimits.FEE_SPLITTER_DEPLOYMENT_GAS_LIMIT, + feeSplitterSalt, + RevShareCodeRepo.feeSplitterCreationCode + ); _depositCall( _portals[i], - FEE_SPLITTER, - RevShareGasLimits.SETTERS_GAS_LIMIT, - abi.encodeCall(IFeeSplitterSetter.setSharesCalculator, (calculator)) + address(PROXY_ADMIN), + RevShareGasLimits.UPGRADE_GAS_LIMIT, + abi.encodeCall( + IProxyAdmin.upgradeAndCall, + (payable(FEE_SPLITTER), feeSplitterImpl, abi.encodeCall(IFeeSplitter.initialize, (calculator))) + ) ); + + // Upgrade all 4 vaults with RevShare configuration (recipient=FeeSplitter, minWithdrawal=0, network=L2) + _upgradeVaultsWithRevShareConfig(_portals[i]); } } - /// @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. + /// @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 _portals Array of OptimismPortal2 addresses for the target L2s. /// @param _l1Configs Array of L1Withdrawer configurations. /// @param _chainFeesRecipients Array of chain fees recipients for the calculators. - function upgradeAndSetupRevShare( + function setupRevShare( address[] calldata _portals, L1WithdrawerConfig[] calldata _l1Configs, address[] calldata _chainFeesRecipients @@ -151,29 +164,16 @@ contract RevShareContractsManager is RevSharePredeploys { calculatorInitCode ); - // 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, RevShareCodeRepo.feeSplitterCreationCode, CREATE2_DEPLOYER); - _depositCreate2( - _portals[i], - RevShareGasLimits.FEE_SPLITTER_DEPLOYMENT_GAS_LIMIT, - feeSplitterSalt, - RevShareCodeRepo.feeSplitterCreationCode - ); + // Configure all 4 vaults for revenue sharing + _configureVaultsForRevShare(_portals[i]); + + // Set calculator on fee splitter _depositCall( _portals[i], - address(PROXY_ADMIN), - RevShareGasLimits.UPGRADE_GAS_LIMIT, - abi.encodeCall( - IProxyAdmin.upgradeAndCall, - (payable(FEE_SPLITTER), feeSplitterImpl, abi.encodeCall(IFeeSplitter.initialize, (calculator))) - ) + FEE_SPLITTER, + RevShareGasLimits.SETTERS_GAS_LIMIT, + abi.encodeCall(IFeeSplitterSetter.setSharesCalculator, (calculator)) ); - - // Upgrade all 4 vaults with RevShare configuration (recipient=FeeSplitter, minWithdrawal=0, network=L2) - _upgradeVaultsWithRevShareConfig(_portals[i]); } } From dd341939475e2c17e6ecef6a5c317ca4ba033c40 Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Fri, 7 Nov 2025 14:07:59 -0300 Subject: [PATCH 28/69] refactor: improve var naming --- src/RevShareContractsUpgrader.sol | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol index 1e68c59d1e..5f22b0e937 100644 --- a/src/RevShareContractsUpgrader.sol +++ b/src/RevShareContractsUpgrader.sol @@ -49,26 +49,26 @@ contract RevShareContractsManager is RevSharePredeploys { /// @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 _portals Array of OptimismPortal2 addresses for the target L2s. - /// @param _l1Configs Array of L1Withdrawer configurations. + /// @param _l1WithdrawerConfigs Array of L1Withdrawer configurations. /// @param _chainFeesRecipients Array of chain fees recipients for the calculators. function upgradeAndSetupRevShare( address[] calldata _portals, - L1WithdrawerConfig[] calldata _l1Configs, + L1WithdrawerConfig[] calldata _l1WithdrawerConfigs, address[] calldata _chainFeesRecipients ) external { - if (_portals.length != _l1Configs.length || _portals.length != _chainFeesRecipients.length) { + if (_portals.length != _l1WithdrawerConfigs.length || _portals.length != _chainFeesRecipients.length) { revert ArrayLengthMismatch(); } for (uint256 i; i < _portals.length; i++) { if (_portals[i] == address(0)) revert PortalCannotBeZeroAddress(); - if (_l1Configs[i].recipient == address(0)) revert L1WithdrawerRecipientCannotBeZeroAddress(); + if (_l1WithdrawerConfigs[i].recipient == address(0)) revert L1WithdrawerRecipientCannotBeZeroAddress(); if (_chainFeesRecipients[i] == address(0)) revert ChainFeesRecipientCannotBeZeroAddress(); // Deploy L1Withdrawer bytes memory l1WithdrawerInitCode = bytes.concat( RevShareCodeRepo.l1WithdrawerCreationCode, - abi.encode(_l1Configs[i].minWithdrawalAmount, _l1Configs[i].recipient, _l1Configs[i].gasLimit) + abi.encode(_l1WithdrawerConfigs[i].minWithdrawalAmount, _l1WithdrawerConfigs[i].recipient, _l1WithdrawerConfigs[i].gasLimit) ); bytes32 l1WithdrawerSalt = _getSalt("L1Withdrawer"); address l1Withdrawer = Utils.getCreate2Address(l1WithdrawerSalt, l1WithdrawerInitCode, CREATE2_DEPLOYER); @@ -121,26 +121,26 @@ contract RevShareContractsManager is RevSharePredeploys { /// @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 _portals Array of OptimismPortal2 addresses for the target L2s. - /// @param _l1Configs Array of L1Withdrawer configurations. + /// @param _l1WithdrawerConfigs Array of L1Withdrawer configurations. /// @param _chainFeesRecipients Array of chain fees recipients for the calculators. function setupRevShare( address[] calldata _portals, - L1WithdrawerConfig[] calldata _l1Configs, + L1WithdrawerConfig[] calldata _l1WithdrawerConfigs, address[] calldata _chainFeesRecipients ) external { - if (_portals.length != _l1Configs.length || _portals.length != _chainFeesRecipients.length) { + if (_portals.length != _l1WithdrawerConfigs.length || _portals.length != _chainFeesRecipients.length) { revert ArrayLengthMismatch(); } for (uint256 i; i < _portals.length; i++) { if (_portals[i] == address(0)) revert PortalCannotBeZeroAddress(); - if (_l1Configs[i].recipient == address(0)) revert L1WithdrawerRecipientCannotBeZeroAddress(); + if (_l1WithdrawerConfigs[i].recipient == address(0)) revert L1WithdrawerRecipientCannotBeZeroAddress(); if (_chainFeesRecipients[i] == address(0)) revert ChainFeesRecipientCannotBeZeroAddress(); // Deploy L1Withdrawer bytes memory l1WithdrawerInitCode = bytes.concat( RevShareCodeRepo.l1WithdrawerCreationCode, - abi.encode(_l1Configs[i].minWithdrawalAmount, _l1Configs[i].recipient, _l1Configs[i].gasLimit) + abi.encode(_l1WithdrawerConfigs[i].minWithdrawalAmount, _l1WithdrawerConfigs[i].recipient, _l1WithdrawerConfigs[i].gasLimit) ); bytes32 l1WithdrawerSalt = _getSalt("L1Withdrawer"); address l1Withdrawer = Utils.getCreate2Address(l1WithdrawerSalt, l1WithdrawerInitCode, CREATE2_DEPLOYER); From 5fe8f70404a9f93506de9a655f17c11c2cacf94e Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Fri, 7 Nov 2025 14:13:52 -0300 Subject: [PATCH 29/69] chore: add zero length array check --- src/RevShareContractsUpgrader.sol | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol index 5f22b0e937..de6de0aa38 100644 --- a/src/RevShareContractsUpgrader.sol +++ b/src/RevShareContractsUpgrader.sol @@ -36,6 +36,9 @@ contract RevShareContractsManager is RevSharePredeploys { /// @notice Thrown when array lengths don't match error ArrayLengthMismatch(); + /// @notice Thrown when array is empty + error EmptyArray(); + /// @notice Struct for L1Withdrawer configuration. /// @param minWithdrawalAmount Minimum withdrawal amount /// @param recipient Recipient address for withdrawals @@ -56,6 +59,7 @@ contract RevShareContractsManager is RevSharePredeploys { L1WithdrawerConfig[] calldata _l1WithdrawerConfigs, address[] calldata _chainFeesRecipients ) external { + if (_portals.length == 0) revert EmptyArray(); if (_portals.length != _l1WithdrawerConfigs.length || _portals.length != _chainFeesRecipients.length) { revert ArrayLengthMismatch(); } @@ -128,6 +132,7 @@ contract RevShareContractsManager is RevSharePredeploys { L1WithdrawerConfig[] calldata _l1WithdrawerConfigs, address[] calldata _chainFeesRecipients ) external { + if (_portals.length == 0) revert EmptyArray(); if (_portals.length != _l1WithdrawerConfigs.length || _portals.length != _chainFeesRecipients.length) { revert ArrayLengthMismatch(); } From 4200f5658ae1059f38766983d70e99c1c3333b2d Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Fri, 7 Nov 2025 14:21:51 -0300 Subject: [PATCH 30/69] refactor: add deploy periphery contract --- src/RevShareContractsUpgrader.sol | 87 +++++++++++++------------------ 1 file changed, 35 insertions(+), 52 deletions(-) diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol index de6de0aa38..a01554b3aa 100644 --- a/src/RevShareContractsUpgrader.sol +++ b/src/RevShareContractsUpgrader.sol @@ -69,32 +69,8 @@ contract RevShareContractsManager is RevSharePredeploys { if (_l1WithdrawerConfigs[i].recipient == address(0)) revert L1WithdrawerRecipientCannotBeZeroAddress(); if (_chainFeesRecipients[i] == address(0)) revert ChainFeesRecipientCannotBeZeroAddress(); - // Deploy L1Withdrawer - bytes memory l1WithdrawerInitCode = bytes.concat( - RevShareCodeRepo.l1WithdrawerCreationCode, - abi.encode(_l1WithdrawerConfigs[i].minWithdrawalAmount, _l1WithdrawerConfigs[i].recipient, _l1WithdrawerConfigs[i].gasLimit) - ); - bytes32 l1WithdrawerSalt = _getSalt("L1Withdrawer"); - address l1Withdrawer = Utils.getCreate2Address(l1WithdrawerSalt, l1WithdrawerInitCode, CREATE2_DEPLOYER); - _depositCreate2( - _portals[i], - RevShareGasLimits.L1_WITHDRAWER_DEPLOYMENT_GAS_LIMIT, - l1WithdrawerSalt, - l1WithdrawerInitCode - ); - - // Deploy SuperchainRevenueShareCalculator - bytes memory calculatorInitCode = bytes.concat( - RevShareCodeRepo.scRevShareCalculatorCreationCode, abi.encode(l1Withdrawer, _chainFeesRecipients[i]) - ); - bytes32 calculatorSalt = _getSalt("SCRevShareCalculator"); - address calculator = Utils.getCreate2Address(calculatorSalt, calculatorInitCode, CREATE2_DEPLOYER); - _depositCreate2( - _portals[i], - RevShareGasLimits.SC_REV_SHARE_CALCULATOR_DEPLOYMENT_GAS_LIMIT, - calculatorSalt, - calculatorInitCode - ); + // Deploy L1Withdrawer and SuperchainRevenueShareCalculator + address calculator = _deployRevSharePeriphery(_portals[i], _l1WithdrawerConfigs[i], _chainFeesRecipients[i]); // Upgrade fee splitter and initialize with calculator FIRST // This prevents the edge case where fees could be sent to an uninitialized FeeSplitter @@ -142,32 +118,8 @@ contract RevShareContractsManager is RevSharePredeploys { if (_l1WithdrawerConfigs[i].recipient == address(0)) revert L1WithdrawerRecipientCannotBeZeroAddress(); if (_chainFeesRecipients[i] == address(0)) revert ChainFeesRecipientCannotBeZeroAddress(); - // Deploy L1Withdrawer - bytes memory l1WithdrawerInitCode = bytes.concat( - RevShareCodeRepo.l1WithdrawerCreationCode, - abi.encode(_l1WithdrawerConfigs[i].minWithdrawalAmount, _l1WithdrawerConfigs[i].recipient, _l1WithdrawerConfigs[i].gasLimit) - ); - bytes32 l1WithdrawerSalt = _getSalt("L1Withdrawer"); - address l1Withdrawer = Utils.getCreate2Address(l1WithdrawerSalt, l1WithdrawerInitCode, CREATE2_DEPLOYER); - _depositCreate2( - _portals[i], - RevShareGasLimits.L1_WITHDRAWER_DEPLOYMENT_GAS_LIMIT, - l1WithdrawerSalt, - l1WithdrawerInitCode - ); - - // Deploy SuperchainRevenueShareCalculator - bytes memory calculatorInitCode = bytes.concat( - RevShareCodeRepo.scRevShareCalculatorCreationCode, abi.encode(l1Withdrawer, _chainFeesRecipients[i]) - ); - bytes32 calculatorSalt = _getSalt("SCRevShareCalculator"); - address calculator = Utils.getCreate2Address(calculatorSalt, calculatorInitCode, CREATE2_DEPLOYER); - _depositCreate2( - _portals[i], - RevShareGasLimits.SC_REV_SHARE_CALCULATOR_DEPLOYMENT_GAS_LIMIT, - calculatorSalt, - calculatorInitCode - ); + // Deploy L1Withdrawer and SuperchainRevenueShareCalculator + address calculator = _deployRevSharePeriphery(_portals[i], _l1WithdrawerConfigs[i], _chainFeesRecipients[i]); // Configure all 4 vaults for revenue sharing _configureVaultsForRevShare(_portals[i]); @@ -182,6 +134,37 @@ contract RevShareContractsManager is RevSharePredeploys { } } + /// @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( + RevShareCodeRepo.l1WithdrawerCreationCode, + abi.encode(_l1WithdrawerConfig.minWithdrawalAmount, _l1WithdrawerConfig.recipient, _l1WithdrawerConfig.gasLimit) + ); + bytes32 l1WithdrawerSalt = _getSalt("L1Withdrawer"); + address l1Withdrawer = Utils.getCreate2Address(l1WithdrawerSalt, l1WithdrawerInitCode, CREATE2_DEPLOYER); + _depositCreate2( + _portal, RevShareGasLimits.L1_WITHDRAWER_DEPLOYMENT_GAS_LIMIT, l1WithdrawerSalt, l1WithdrawerInitCode + ); + + // Deploy SuperchainRevenueShareCalculator + bytes memory calculatorInitCode = + bytes.concat(RevShareCodeRepo.scRevShareCalculatorCreationCode, abi.encode(l1Withdrawer, _chainFeesRecipient)); + bytes32 calculatorSalt = _getSalt("SCRevShareCalculator"); + calculator = Utils.getCreate2Address(calculatorSalt, calculatorInitCode, CREATE2_DEPLOYER); + _depositCreate2( + _portal, RevShareGasLimits.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 { From 34855bb55a033ade740e3f815b1902dedbd1578b Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Fri, 7 Nov 2025 14:25:57 -0300 Subject: [PATCH 31/69] refactor: invert calls order --- src/RevShareContractsUpgrader.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol index a01554b3aa..75491543ca 100644 --- a/src/RevShareContractsUpgrader.sol +++ b/src/RevShareContractsUpgrader.sol @@ -121,9 +121,6 @@ contract RevShareContractsManager is RevSharePredeploys { // Deploy L1Withdrawer and SuperchainRevenueShareCalculator address calculator = _deployRevSharePeriphery(_portals[i], _l1WithdrawerConfigs[i], _chainFeesRecipients[i]); - // Configure all 4 vaults for revenue sharing - _configureVaultsForRevShare(_portals[i]); - // Set calculator on fee splitter _depositCall( _portals[i], @@ -131,6 +128,9 @@ contract RevShareContractsManager is RevSharePredeploys { RevShareGasLimits.SETTERS_GAS_LIMIT, abi.encodeCall(IFeeSplitterSetter.setSharesCalculator, (calculator)) ); + + // Configure all 4 vaults for revenue sharing + _configureVaultsForRevShare(_portals[i]); } } From 111c49a0a72ec8c6bdc9a45af7cc0796a949b070 Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Fri, 7 Nov 2025 14:29:14 -0300 Subject: [PATCH 32/69] refactor: reduce interface complexity --- src/RevShareContractsUpgrader.sol | 3 +-- src/interfaces/IFeeSplitter.sol | 1 + src/interfaces/IFeeSplitterSetter.sol | 7 ------- 3 files changed, 2 insertions(+), 9 deletions(-) delete mode 100644 src/interfaces/IFeeSplitterSetter.sol diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol index 75491543ca..d49ee55f9e 100644 --- a/src/RevShareContractsUpgrader.sol +++ b/src/RevShareContractsUpgrader.sol @@ -11,7 +11,6 @@ import {IOptimismPortal2} from "@eth-optimism-bedrock/interfaces/L1/IOptimismPor 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 {IFeeSplitterSetter} from "src/interfaces/IFeeSplitterSetter.sol"; import {IFeeVault} from "src/interfaces/IFeeVault.sol"; /// @title RevShareContractsManager @@ -126,7 +125,7 @@ contract RevShareContractsManager is RevSharePredeploys { _portals[i], FEE_SPLITTER, RevShareGasLimits.SETTERS_GAS_LIMIT, - abi.encodeCall(IFeeSplitterSetter.setSharesCalculator, (calculator)) + abi.encodeCall(IFeeSplitter.setSharesCalculator, (calculator)) ); // Configure all 4 vaults for revenue sharing diff --git a/src/interfaces/IFeeSplitter.sol b/src/interfaces/IFeeSplitter.sol index 50a3de4269..7a85a9f5b0 100644 --- a/src/interfaces/IFeeSplitter.sol +++ b/src/interfaces/IFeeSplitter.sol @@ -4,4 +4,5 @@ pragma solidity 0.8.15; /// @notice Interface for the FeeSplitter in L2. interface IFeeSplitter { function initialize(address _sharesCalculator) external; + function setSharesCalculator(address _calculator) external; } diff --git a/src/interfaces/IFeeSplitterSetter.sol b/src/interfaces/IFeeSplitterSetter.sol deleted file mode 100644 index 1bc20b2046..0000000000 --- a/src/interfaces/IFeeSplitterSetter.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.15; - -/// @notice Interface for FeeSplitter setter. -interface IFeeSplitterSetter { - function setSharesCalculator(address _calculator) external; -} From a76d1f0b6b43ce6e81d0e9ef09523cf4505ed274 Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Mon, 10 Nov 2025 00:21:46 -0300 Subject: [PATCH 33/69] feat: add revshare template and integration tests --- src/template/RevShareSetup.sol | 112 ++++++++++++++++++ test/integration/IntegrationBase.t.sol | 48 ++++++-- ...RevShareContractsUpgraderIntegration.t.sol | 69 +++++------ .../integration/RevenueShareIntegration.t.sol | 19 ++- .../integration/fixtures/revshare-config.toml | 30 +++++ 5 files changed, 226 insertions(+), 52 deletions(-) create mode 100644 src/template/RevShareSetup.sol create mode 100644 test/integration/fixtures/revshare-config.toml diff --git a/src/template/RevShareSetup.sol b/src/template/RevShareSetup.sol new file mode 100644 index 0000000000..b3e2a8e005 --- /dev/null +++ b/src/template/RevShareSetup.sol @@ -0,0 +1,112 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import {VmSafe} from "forge-std/Vm.sol"; +import {stdToml} from "forge-std/StdToml.sol"; +import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; + +import {OPCMTaskBase} from "src/tasks/types/OPCMTaskBase.sol"; +import {Action} from "src/libraries/MultisigTypes.sol"; +import {RevShareContractsManager} from "src/RevShareContractsUpgrader.sol"; + +/// @notice Task for setting up revenue sharing on OP Stack chains. +contract RevShareSetup is OPCMTaskBase { + using stdToml for string; + using EnumerableSet for EnumerableSet.AddressSet; + + /// @notice RevShareContractsManager address + address public REV_SHARE_MANAGER; + + /// @notice Portal addresses for L2 chains. + address[] internal portals; + + /// @notice L1Withdrawer configurations (stored as encoded bytes). + bytes internal l1WithdrawerConfigsEncoded; + + /// @notice Remainder recipients (chain fees recipients). + address[] internal remainderRecipients; + + /// @notice Names in the SimpleAddressRegistry that are expected to be written during this task. + function _taskStorageWrites() internal pure virtual override returns (string[] memory) { + return new string[](0); + } + + /// @notice Returns an array of strings that refer to contract names in the address registry. + function _taskBalanceChanges() internal view virtual override returns (string[] memory) { + return new string[](0); + } + + /// @notice Sets the allowed storage accesses - override to add portal addresses + function _setAllowedStorageAccesses() internal virtual override { + super._setAllowedStorageAccesses(); + // Add portal addresses as they will have storage writes from depositTransaction calls + for (uint256 i = 0; i < portals.length; i++) { + _allowedStorageAccesses.add(portals[i]); + } + } + + /// @notice Sets up the template with configurations from a TOML file. + function _templateSetup(string memory taskConfigFilePath, address) internal override { + string memory tomlContent = vm.readFile(taskConfigFilePath); + + // Load RevShareContractsManager address from TOML + REV_SHARE_MANAGER = tomlContent.readAddress(".revShareManager"); + require(REV_SHARE_MANAGER.code.length > 0, "RevShareContractsManager has no code"); + vm.label(REV_SHARE_MANAGER, "RevShareContractsManager"); + + // Set RevShareContractsManager as the allowed target for delegatecall + OPCM_TARGETS.push(REV_SHARE_MANAGER); + + // Load portal addresses + portals = abi.decode(tomlContent.parseRaw(".portals"), (address[])); + require(portals.length > 0, "No portals configured"); + + // Load L1Withdrawer configs by reading each field individually + // Note: We can't use parseRaw + abi.decode directly because TOML inline tables + // sort keys alphabetically, which doesn't match the struct field order + // So we need to read each field separately and construct the struct manually + RevShareContractsManager.L1WithdrawerConfig[] memory configs = + new RevShareContractsManager.L1WithdrawerConfig[](portals.length); + + for (uint256 i = 0; i < portals.length; i++) { + string memory basePath = string.concat(".l1WithdrawerConfigs[", vm.toString(i), "]"); + configs[i] = RevShareContractsManager.L1WithdrawerConfig({ + minWithdrawalAmount: tomlContent.readUint(string.concat(basePath, ".minWithdrawalAmount")), + recipient: tomlContent.readAddress(string.concat(basePath, ".recipient")), + gasLimit: uint32(tomlContent.readUint(string.concat(basePath, ".gasLimit"))) + }); + } + l1WithdrawerConfigsEncoded = abi.encode(configs); + + // Load remainder recipients + remainderRecipients = abi.decode(tomlContent.parseRaw(".remainderRecipients"), (address[])); + require(remainderRecipients.length == portals.length, "Remainder recipients length mismatch"); + } + + /// @notice Builds the actions for executing the operations. + function _build(address) internal override { + // Decode configs from storage + RevShareContractsManager.L1WithdrawerConfig[] memory l1WithdrawerConfigs = + abi.decode(l1WithdrawerConfigsEncoded, (RevShareContractsManager.L1WithdrawerConfig[])); + + // Delegatecall into RevShareContractsManager + // OPCMTaskBase uses Multicall3Delegatecall, so this delegatecall will be captured as an action + (bool success,) = REV_SHARE_MANAGER.delegatecall( + abi.encodeCall( + RevShareContractsManager.upgradeAndSetupRevShare, (portals, l1WithdrawerConfigs, remainderRecipients) + ) + ); + require(success, "RevShareSetup: Delegatecall failed"); + } + + /// @notice This method performs all validations and assertions that verify the calls executed as expected. + function _validate(VmSafe.AccountAccess[] memory, Action[] memory, address) internal view override { + // Add validation logic here if needed + // For now, we rely on the integration tests to validate the L2 state + } + + /// @notice Override to return a list of addresses that should not be checked for code length. + function _getCodeExceptions() internal view virtual override returns (address[] memory) { + return new address[](0); + } +} diff --git a/test/integration/IntegrationBase.t.sol b/test/integration/IntegrationBase.t.sol index 5a478bfb83..95fb806e74 100644 --- a/test/integration/IntegrationBase.t.sol +++ b/test/integration/IntegrationBase.t.sol @@ -9,25 +9,48 @@ import {AddressAliasHelper} from "@eth-optimism-bedrock/src/vendor/AddressAliasH /// @title IntegrationBase /// @notice Base contract for integration tests with L1->L2 deposit transaction replay functionality abstract contract IntegrationBase is Test { - /// @notice Replay all deposit transactions from L1 to L2 - /// @param _forkId The fork ID to switch to for L2 execution + /// @notice Replay all deposit transactions from L1 to multiple L2s + /// @param _forkIds Array of fork IDs for each L2 chain /// @param _isSimulate If true, only process the second half of logs to avoid duplicates. /// Task simulations emit events twice: once during the initial dry-run /// and once during the actual simulation. Taking the second half ensures /// we only process the final simulation results. - function _relayAllMessages(uint256 _forkId, bool _isSimulate) internal { + /// @param _portals Array of OptimismPortal addresses corresponding to each fork. + /// Only events emitted by each portal will be replayed on its corresponding L2. + function _relayAllMessages(uint256[] memory _forkIds, bool _isSimulate, address[] memory _portals) internal { + require(_forkIds.length == _portals.length, "Fork IDs and portals length mismatch"); + + // Get logs from L1 execution (currently active fork should be L1) + Vm.Log[] memory _allLogs = vm.getRecordedLogs(); + + // Process each L2 chain + for (uint256 _chainIdx = 0; _chainIdx < _forkIds.length; _chainIdx++) { + _relayMessagesForChain(_allLogs, _forkIds[_chainIdx], _isSimulate, _portals[_chainIdx]); + } + } + + /// @notice Replay deposit transactions for a single L2 chain + /// @param _allLogs All recorded logs from L1 execution + /// @param _forkId The fork ID to switch to for L2 execution + /// @param _isSimulate If true, only process the second half of logs + /// @param _portal The OptimismPortal address to filter events by + function _relayMessagesForChain( + Vm.Log[] memory _allLogs, + uint256 _forkId, + bool _isSimulate, + address _portal + ) internal { + // Switch to L2 fork for execution vm.selectFork(_forkId); console2.log("\n"); console2.log("================================================================================"); console2.log("=== Replaying Deposit Transactions on L2 ==="); + console2.log("=== Portal:", _portal); console2.log("=== Each transaction includes Tenderly simulation link ==="); - console2.log("=== Network is set to 10 (OP Mainnet) - adjust if testing on different L2 ==="); + console2.log("=== Network is set to", block.chainid, "- adjust if testing on different L2 ==="); console2.log("================================================================================"); - // Get logs from L1 execution - Vm.Log[] memory _allLogs = vm.getRecordedLogs(); - // If this is a simulation, only take the second half of logs to avoid processing duplicates // Simulations emit events twice, so we skip the first half uint256 _startIndex = _isSimulate ? _allLogs.length / 2 : 0; @@ -44,10 +67,17 @@ abstract contract IntegrationBase is Test { uint256 _transactionCount; uint256 _successCount; uint256 _failureCount; + uint256 _totalDepositEvents; + uint256 _filteredOutEvents; for (uint256 _i = 0; _i < _logs.length; _i++) { - // Check if this is a TransactionDeposited event + // Check if this is a TransactionDeposited event AND it was emitted by the specified portal if (_logs[_i].topics[0] == _transactionDepositedHash) { + _totalDepositEvents++; + if (_logs[_i].emitter != _portal) { + _filteredOutEvents++; + continue; + } // Decode indexed parameters address _from = address(uint160(uint256(_logs[_i].topics[1]))); address _to = address(uint160(uint256(_logs[_i].topics[2]))); @@ -69,7 +99,7 @@ abstract contract IntegrationBase is Test { } console2.log("\n=== Summary ==="); - console2.log("Total transactions:", _transactionCount); + console2.log("Total transactions processed:", _transactionCount); console2.log("Successful transactions:", _successCount); console2.log("Failed transactions:", _failureCount); diff --git a/test/integration/RevShareContractsUpgraderIntegration.t.sol b/test/integration/RevShareContractsUpgraderIntegration.t.sol index 6251c80a6e..4f93b8d5b9 100644 --- a/test/integration/RevShareContractsUpgraderIntegration.t.sol +++ b/test/integration/RevShareContractsUpgraderIntegration.t.sol @@ -2,6 +2,7 @@ pragma solidity 0.8.15; import {RevShareContractsManager} from "src/RevShareContractsUpgrader.sol"; +import {RevShareSetup} from "src/template/RevShareSetup.sol"; import {IntegrationBase} from "./IntegrationBase.t.sol"; import {Test} from "forge-std/Test.sol"; @@ -34,24 +35,20 @@ interface ISuperchainRevSharesCalculator { function remainderRecipient() external view returns (address payable); } -/// @notice Simple contract to simulate a Safe executing delegatecall -contract SafeSimulator { - function executeDelegatecall(address target, bytes memory data) external returns (bool success, bytes memory returnData) { - return target.delegatecall(data); - } -} - contract RevShareContractsUpgraderIntegrationTest is IntegrationBase { RevShareContractsManager public revShareManager; - SafeSimulator public safeSimulator; + RevShareSetup public revShareTask; // Fork IDs uint256 internal _mainnetForkId; uint256 internal _opMainnetForkId; + uint256 internal _inkMainnetForkId; // L1 addresses address internal constant PROXY_ADMIN_OWNER = 0x5a0Aae59D09fccBdDb6C6CcEB07B7279367C3d2A; address internal constant OP_MAINNET_PORTAL = 0xbEb5Fc579115071764c7423A4f12eDde41f106Ed; + address internal constant INK_MAINNET_PORTAL = 0x5d66C1782664115999C47c9fA5cd031f495D3e4F; + address internal constant REV_SHARE_MANAGER_ADDRESS = 0x0000000000000000000000000000000000001337; // L2 predeploys (same across all OP Stack chains) address internal constant SEQUENCER_FEE_VAULT = 0x4200000000000000000000000000000000000011; @@ -74,18 +71,18 @@ contract RevShareContractsUpgraderIntegrationTest is IntegrationBase { // Create forks for L1 (mainnet) and L2 (OP Mainnet) _mainnetForkId = vm.createFork("http://127.0.0.1:8545"); _opMainnetForkId = vm.createFork("http://127.0.0.1:9545"); + _inkMainnetForkId = vm.createFork("http://127.0.0.1:9546"); // Deploy contracts on L1 vm.selectFork(_mainnetForkId); - // Deploy SafeSimulator at PROXY_ADMIN_OWNER address using vm.etch - // This simulates the Safe that will execute the delegatecall - bytes memory safeSimulatorCode = type(SafeSimulator).runtimeCode; - vm.etch(PROXY_ADMIN_OWNER, safeSimulatorCode); - safeSimulator = SafeSimulator(PROXY_ADMIN_OWNER); - - // Deploy RevShareContractsManager + // Deploy RevShareContractsManager and etch at predetermined address revShareManager = new RevShareContractsManager(); + vm.etch(REV_SHARE_MANAGER_ADDRESS, address(revShareManager).code); + revShareManager = RevShareContractsManager(REV_SHARE_MANAGER_ADDRESS); + + // Deploy RevShareSetup task + revShareTask = new RevShareSetup(); } /// @notice Test the integration of upgradeAndSetupRevShare @@ -93,36 +90,26 @@ contract RevShareContractsUpgraderIntegrationTest is IntegrationBase { // Step 1: Record logs for L1→L2 message replay vm.recordLogs(); - // Step 2: Prepare call parameters - address[] memory portals = new address[](1); - portals[0] = OP_MAINNET_PORTAL; + // Step 2: Execute task simulation + revShareTask.simulate("test/integration/fixtures/revshare-config.toml"); - RevShareContractsManager.L1WithdrawerConfig[] memory l1Configs = - new RevShareContractsManager.L1WithdrawerConfig[](1); - l1Configs[0] = RevShareContractsManager.L1WithdrawerConfig({ - minWithdrawalAmount: MIN_WITHDRAWAL_AMOUNT, - recipient: L1_WITHDRAWAL_RECIPIENT, - gasLimit: WITHDRAWAL_GAS_LIMIT - }); - - address[] memory chainFeesRecipients = new address[](1); - chainFeesRecipients[0] = CHAIN_FEES_RECIPIENT; - - // Step 3: Execute upgradeAndSetupRevShare via delegatecall from SafeSimulator - // This simulates how the Safe will execute this in production - bytes memory callData = abi.encodeCall( - RevShareContractsManager.upgradeAndSetupRevShare, - (portals, l1Configs, chainFeesRecipients) - ); + // Step 3: Relay deposit transactions from L1 to all L2s + uint256[] memory forkIds = new uint256[](2); + forkIds[0] = _opMainnetForkId; + forkIds[1] = _inkMainnetForkId; - (bool success,) = safeSimulator.executeDelegatecall(address(revShareManager), callData); - require(success, "Delegatecall failed"); + address[] memory portals = new address[](2); + portals[0] = OP_MAINNET_PORTAL; + portals[1] = INK_MAINNET_PORTAL; - // Step 4: Relay all deposit transactions from L1 to L2 - // Pass false for _isSimulate since we're not using simulate() - _relayAllMessages(_opMainnetForkId, false); + _relayAllMessages(forkIds, true, portals); + + // Step 4: Assert the state of the OP Mainnet contracts + vm.selectFork(_opMainnetForkId); + _assertL2State(); - // Step 5: Assert the state of the L2 contracts + // Step 5: Assert the state of the Ink Mainnet contracts + vm.selectFork(_inkMainnetForkId); _assertL2State(); } diff --git a/test/integration/RevenueShareIntegration.t.sol b/test/integration/RevenueShareIntegration.t.sol index 02081aed89..c0cf4a723c 100644 --- a/test/integration/RevenueShareIntegration.t.sol +++ b/test/integration/RevenueShareIntegration.t.sol @@ -42,6 +42,9 @@ contract RevenueShareIntegrationTest is IntegrationBase { uint256 internal _mainnetForkId; uint256 internal _l2ForkId; + // L1 addresses + address internal constant OP_MAINNET_PORTAL = 0xbEb5Fc579115071764c7423A4f12eDde41f106Ed; + // L2 predeploys /// @notice Address of the Sequencer Fee Vault Predeploy on L2. address internal constant SEQUENCER_FEE_VAULT = 0x4200000000000000000000000000000000000011; @@ -77,7 +80,13 @@ contract RevenueShareIntegrationTest is IntegrationBase { // Step 2: Relay messages from L1 to L2 // Pass true for _isSimulate since simulate() emits events twice - _relayAllMessages(_l2ForkId, true); + uint256[] memory forkIds = new uint256[](1); + forkIds[0] = _l2ForkId; + + address[] memory portals = new address[](1); + portals[0] = OP_MAINNET_PORTAL; + + _relayAllMessages(forkIds, true, portals); // Step 3: Assert the state of the L2 contracts string memory _config = vm.readFile(_configPath); @@ -115,7 +124,13 @@ contract RevenueShareIntegrationTest is IntegrationBase { // Step 2: Relay messages from L1 to L2 // Pass true for _isSimulate since simulate() emits events twice - _relayAllMessages(_l2ForkId, true); + uint256[] memory forkIds = new uint256[](1); + forkIds[0] = _l2ForkId; + + address[] memory portals = new address[](1); + portals[0] = OP_MAINNET_PORTAL; + + _relayAllMessages(forkIds, true, portals); // Step 3: Assert the state of the L2 contracts string memory _config = vm.readFile(_configPath); diff --git a/test/integration/fixtures/revshare-config.toml b/test/integration/fixtures/revshare-config.toml new file mode 100644 index 0000000000..7fb2d06785 --- /dev/null +++ b/test/integration/fixtures/revshare-config.toml @@ -0,0 +1,30 @@ +# RevShare Setup Configuration + +# L2 chains to target +l2chains = [{name = "OP Mainnet", chainId = 10}, {name = "Ink", chainId = 57073}] + +safeAddress = "ProxyAdminOwner" + +# RevShareContractsManager address +revShareManager = "0x0000000000000000000000000000000000001337" + +# Portal addresses for each chain +portals = [ + "0xbEb5Fc579115071764c7423A4f12eDde41f106Ed", # OP Mainnet Portal + "0x5d66C1782664115999C47c9fA5cd031f495D3e4F" # Ink Mainnet Portal +] + +# Chain fees recipients +remainderRecipients = [ + "0x0000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000001" +] + +# L1Withdrawer configurations +l1WithdrawerConfigs = [ + {minWithdrawalAmount = 350000, recipient = "0x0000000000000000000000000000000000000001", gasLimit = 800000}, + {minWithdrawalAmount = 350000, recipient = "0x0000000000000000000000000000000000000001", gasLimit = 800000} +] + +[addresses] +ProxyAdminOwner = "0x5a0Aae59D09fccBdDb6C6CcEB07B7279367C3d2A" From 88a9d39556a4885e96cad6fb328753fe1c91415d Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Mon, 10 Nov 2025 00:41:17 -0300 Subject: [PATCH 34/69] refactor: remove fixture file --- ...RevShareContractsUpgraderIntegration.t.sol | 2 +- .../integration/fixtures/revshare-config.toml | 30 ----------- .../config.toml | 52 ++++++++----------- 3 files changed, 22 insertions(+), 62 deletions(-) delete mode 100644 test/integration/fixtures/revshare-config.toml diff --git a/test/integration/RevShareContractsUpgraderIntegration.t.sol b/test/integration/RevShareContractsUpgraderIntegration.t.sol index 4f93b8d5b9..8e59f45ecd 100644 --- a/test/integration/RevShareContractsUpgraderIntegration.t.sol +++ b/test/integration/RevShareContractsUpgraderIntegration.t.sol @@ -91,7 +91,7 @@ contract RevShareContractsUpgraderIntegrationTest is IntegrationBase { vm.recordLogs(); // Step 2: Execute task simulation - revShareTask.simulate("test/integration/fixtures/revshare-config.toml"); + revShareTask.simulate("test/tasks/example/eth/018-revshare-upgrade-and-setup/config.toml"); // Step 3: Relay deposit transactions from L1 to all L2s uint256[] memory forkIds = new uint256[](2); diff --git a/test/integration/fixtures/revshare-config.toml b/test/integration/fixtures/revshare-config.toml deleted file mode 100644 index 7fb2d06785..0000000000 --- a/test/integration/fixtures/revshare-config.toml +++ /dev/null @@ -1,30 +0,0 @@ -# RevShare Setup Configuration - -# L2 chains to target -l2chains = [{name = "OP Mainnet", chainId = 10}, {name = "Ink", chainId = 57073}] - -safeAddress = "ProxyAdminOwner" - -# RevShareContractsManager address -revShareManager = "0x0000000000000000000000000000000000001337" - -# Portal addresses for each chain -portals = [ - "0xbEb5Fc579115071764c7423A4f12eDde41f106Ed", # OP Mainnet Portal - "0x5d66C1782664115999C47c9fA5cd031f495D3e4F" # Ink Mainnet Portal -] - -# Chain fees recipients -remainderRecipients = [ - "0x0000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000001" -] - -# L1Withdrawer configurations -l1WithdrawerConfigs = [ - {minWithdrawalAmount = 350000, recipient = "0x0000000000000000000000000000000000000001", gasLimit = 800000}, - {minWithdrawalAmount = 350000, recipient = "0x0000000000000000000000000000000000000001", gasLimit = 800000} -] - -[addresses] -ProxyAdminOwner = "0x5a0Aae59D09fccBdDb6C6CcEB07B7279367C3d2A" diff --git a/test/tasks/example/eth/018-revshare-upgrade-and-setup/config.toml b/test/tasks/example/eth/018-revshare-upgrade-and-setup/config.toml index 4ea1b3b4b4..7fb2d06785 100644 --- a/test/tasks/example/eth/018-revshare-upgrade-and-setup/config.toml +++ b/test/tasks/example/eth/018-revshare-upgrade-and-setup/config.toml @@ -1,40 +1,30 @@ -# L2 chains to upgrade and enable revenue sharing -l2chains = [ - {name = "OP Mainnet", chainId = 10}, - {name = "Base", chainId = 8453} -] - -templateName = "RevShareUpgradeAndSetup" +# RevShare Setup Configuration -# OP Mainnet configuration -[[revShareSetups]] -chainId = 10 -saltSeed = "DeploymentSaltV1-OP" +# L2 chains to target +l2chains = [{name = "OP Mainnet", chainId = 10}, {name = "Ink", chainId = 57073}] -# L1 Withdrawer configuration -l1WithdrawerMinWithdrawalAmount = 350000 -l1WithdrawerRecipient = "0x742d35Cc6634C0532925a3b8D0C0C8b8B0c0C8b8" # L1 recipient (e.g., FeesDepositor) -l1WithdrawerGasLimit = 800000 +safeAddress = "ProxyAdminOwner" -# Superchain Revenue Share Calculator configuration -chainFeesRecipient = "0x8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b" # Chain fees recipient +# RevShareContractsManager address +revShareManager = "0x0000000000000000000000000000000000001337" -# Base Mainnet configuration -[[revShareSetups]] -chainId = 8453 -saltSeed = "DeploymentSaltV1-Base" +# Portal addresses for each chain +portals = [ + "0xbEb5Fc579115071764c7423A4f12eDde41f106Ed", # OP Mainnet Portal + "0x5d66C1782664115999C47c9fA5cd031f495D3e4F" # Ink Mainnet Portal +] -# L1 Withdrawer configuration -l1WithdrawerMinWithdrawalAmount = 350000 -l1WithdrawerRecipient = "0x742d35Cc6634C0532925a3b8D0C0C8b8B0c0C8b8" # L1 recipient (e.g., FeesDepositor) -l1WithdrawerGasLimit = 800000 +# Chain fees recipients +remainderRecipients = [ + "0x0000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000001" +] -# Superchain Revenue Share Calculator configuration -chainFeesRecipient = "0x9B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C9B" # Chain fees recipient +# L1Withdrawer configurations +l1WithdrawerConfigs = [ + {minWithdrawalAmount = 350000, recipient = "0x0000000000000000000000000000000000000001", gasLimit = 800000}, + {minWithdrawalAmount = 350000, recipient = "0x0000000000000000000000000000000000000001", gasLimit = 800000} +] [addresses] ProxyAdminOwner = "0x5a0Aae59D09fccBdDb6C6CcEB07B7279367C3d2A" -RevShareContractsManager = "0x0000000000000000000000000000000000000000" # TODO: Set actual deployed address - -# Per-chain addresses (discovered automatically by SuperchainAddressRegistry) -# OptimismPortal addresses will be looked up automatically for each chain From 8c3599bb5bc8512a158817a19b2a597ea11fa6e6 Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Mon, 10 Nov 2025 00:43:40 -0300 Subject: [PATCH 35/69] refactor: cleanup --- test/integration/IntegrationBase.t.sol | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/test/integration/IntegrationBase.t.sol b/test/integration/IntegrationBase.t.sol index 95fb806e74..362101d8f8 100644 --- a/test/integration/IntegrationBase.t.sol +++ b/test/integration/IntegrationBase.t.sol @@ -24,7 +24,7 @@ abstract contract IntegrationBase is Test { Vm.Log[] memory _allLogs = vm.getRecordedLogs(); // Process each L2 chain - for (uint256 _chainIdx = 0; _chainIdx < _forkIds.length; _chainIdx++) { + for (uint256 _chainIdx; _chainIdx < _forkIds.length; _chainIdx++) { _relayMessagesForChain(_allLogs, _forkIds[_chainIdx], _isSimulate, _portals[_chainIdx]); } } @@ -57,7 +57,7 @@ abstract contract IntegrationBase is Test { uint256 _logsCount = _isSimulate ? _allLogs.length - _startIndex : _allLogs.length; Vm.Log[] memory _logs = new Vm.Log[](_logsCount); - for (uint256 _i = 0; _i < _logsCount; _i++) { + for (uint256 _i; _i < _logsCount; _i++) { _logs[_i] = _allLogs[_startIndex + _i]; } @@ -67,17 +67,10 @@ abstract contract IntegrationBase is Test { uint256 _transactionCount; uint256 _successCount; uint256 _failureCount; - uint256 _totalDepositEvents; - uint256 _filteredOutEvents; - for (uint256 _i = 0; _i < _logs.length; _i++) { + for (uint256 _i; _i < _logs.length; _i++) { // Check if this is a TransactionDeposited event AND it was emitted by the specified portal if (_logs[_i].topics[0] == _transactionDepositedHash) { - _totalDepositEvents++; - if (_logs[_i].emitter != _portal) { - _filteredOutEvents++; - continue; - } // Decode indexed parameters address _from = address(uint160(uint256(_logs[_i].topics[1]))); address _to = address(uint160(uint256(_logs[_i].topics[2]))); @@ -157,7 +150,7 @@ abstract contract IntegrationBase is Test { /// @notice Helper function to slice bytes function _slice(bytes memory _data, uint256 _start, uint256 _length) internal pure returns (bytes memory) { bytes memory _result = new bytes(_length); - for (uint256 _i = 0; _i < _length; _i++) { + for (uint256 _i; _i < _length; _i++) { _result[_i] = _data[_start + _i]; } return _result; @@ -195,7 +188,7 @@ abstract contract IntegrationBase is Test { /// @notice Convert address to lowercase hex string without 0x prefix function _toAsciiString(address _addr) internal pure returns (string memory) { bytes memory _s = new bytes(40); - for (uint256 _i = 0; _i < 20; _i++) { + for (uint256 _i; _i < 20; _i++) { bytes1 _b = bytes1(uint8(uint256(uint160(_addr)) / (2 ** (8 * (19 - _i))))); bytes1 _hi = bytes1(uint8(_b) / 16); bytes1 _lo = bytes1(uint8(_b) - 16 * uint8(_hi)); @@ -209,7 +202,7 @@ abstract contract IntegrationBase is Test { function _bytesToHexString(bytes memory _data) internal pure returns (string memory) { bytes memory _hexChars = "0123456789abcdef"; bytes memory _result = new bytes(_data.length * 2); - for (uint256 _i = 0; _i < _data.length; _i++) { + for (uint256 _i; _i < _data.length; _i++) { _result[_i * 2] = _hexChars[uint8(_data[_i] >> 4)]; _result[_i * 2 + 1] = _hexChars[uint8(_data[_i] & 0x0f)]; } From 93542adda6763a9c854c63cbe3d3d6dd6cded663 Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Mon, 10 Nov 2025 00:44:33 -0300 Subject: [PATCH 36/69] chore: improve naming --- test/integration/IntegrationBase.t.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/integration/IntegrationBase.t.sol b/test/integration/IntegrationBase.t.sol index 362101d8f8..8aba9d8767 100644 --- a/test/integration/IntegrationBase.t.sol +++ b/test/integration/IntegrationBase.t.sol @@ -15,7 +15,7 @@ abstract contract IntegrationBase is Test { /// Task simulations emit events twice: once during the initial dry-run /// and once during the actual simulation. Taking the second half ensures /// we only process the final simulation results. - /// @param _portals Array of OptimismPortal addresses corresponding to each fork. + /// @param _portals Array of Portal addresses corresponding to each fork. /// Only events emitted by each portal will be replayed on its corresponding L2. function _relayAllMessages(uint256[] memory _forkIds, bool _isSimulate, address[] memory _portals) internal { require(_forkIds.length == _portals.length, "Fork IDs and portals length mismatch"); @@ -33,7 +33,7 @@ abstract contract IntegrationBase is Test { /// @param _allLogs All recorded logs from L1 execution /// @param _forkId The fork ID to switch to for L2 execution /// @param _isSimulate If true, only process the second half of logs - /// @param _portal The OptimismPortal address to filter events by + /// @param _portal The Portal address to filter events by function _relayMessagesForChain( Vm.Log[] memory _allLogs, uint256 _forkId, From 03d4cfa904ed86e2a4d887f4d553a664653337df Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Mon, 10 Nov 2025 00:51:01 -0300 Subject: [PATCH 37/69] feat: add portal check --- test/integration/IntegrationBase.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/IntegrationBase.t.sol b/test/integration/IntegrationBase.t.sol index 8aba9d8767..1fed75da1b 100644 --- a/test/integration/IntegrationBase.t.sol +++ b/test/integration/IntegrationBase.t.sol @@ -70,7 +70,7 @@ abstract contract IntegrationBase is Test { for (uint256 _i; _i < _logs.length; _i++) { // Check if this is a TransactionDeposited event AND it was emitted by the specified portal - if (_logs[_i].topics[0] == _transactionDepositedHash) { + if (_logs[_i].topics[0] == _transactionDepositedHash && _logs[_i].emitter == _portal) { // Decode indexed parameters address _from = address(uint160(uint256(_logs[_i].topics[1]))); address _to = address(uint160(uint256(_logs[_i].topics[2]))); From d61043c8f7e23c04cac8a59ad5ba641e85703ecc Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Mon, 10 Nov 2025 00:53:10 -0300 Subject: [PATCH 38/69] chore: remove unused task --- src/template/RevShareSetup.sol | 112 ---------- src/template/RevShareUpgradeAndSetup.sol | 210 +++++++----------- ...RevShareContractsUpgraderIntegration.t.sol | 8 +- 3 files changed, 86 insertions(+), 244 deletions(-) delete mode 100644 src/template/RevShareSetup.sol diff --git a/src/template/RevShareSetup.sol b/src/template/RevShareSetup.sol deleted file mode 100644 index b3e2a8e005..0000000000 --- a/src/template/RevShareSetup.sol +++ /dev/null @@ -1,112 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.15; - -import {VmSafe} from "forge-std/Vm.sol"; -import {stdToml} from "forge-std/StdToml.sol"; -import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; - -import {OPCMTaskBase} from "src/tasks/types/OPCMTaskBase.sol"; -import {Action} from "src/libraries/MultisigTypes.sol"; -import {RevShareContractsManager} from "src/RevShareContractsUpgrader.sol"; - -/// @notice Task for setting up revenue sharing on OP Stack chains. -contract RevShareSetup is OPCMTaskBase { - using stdToml for string; - using EnumerableSet for EnumerableSet.AddressSet; - - /// @notice RevShareContractsManager address - address public REV_SHARE_MANAGER; - - /// @notice Portal addresses for L2 chains. - address[] internal portals; - - /// @notice L1Withdrawer configurations (stored as encoded bytes). - bytes internal l1WithdrawerConfigsEncoded; - - /// @notice Remainder recipients (chain fees recipients). - address[] internal remainderRecipients; - - /// @notice Names in the SimpleAddressRegistry that are expected to be written during this task. - function _taskStorageWrites() internal pure virtual override returns (string[] memory) { - return new string[](0); - } - - /// @notice Returns an array of strings that refer to contract names in the address registry. - function _taskBalanceChanges() internal view virtual override returns (string[] memory) { - return new string[](0); - } - - /// @notice Sets the allowed storage accesses - override to add portal addresses - function _setAllowedStorageAccesses() internal virtual override { - super._setAllowedStorageAccesses(); - // Add portal addresses as they will have storage writes from depositTransaction calls - for (uint256 i = 0; i < portals.length; i++) { - _allowedStorageAccesses.add(portals[i]); - } - } - - /// @notice Sets up the template with configurations from a TOML file. - function _templateSetup(string memory taskConfigFilePath, address) internal override { - string memory tomlContent = vm.readFile(taskConfigFilePath); - - // Load RevShareContractsManager address from TOML - REV_SHARE_MANAGER = tomlContent.readAddress(".revShareManager"); - require(REV_SHARE_MANAGER.code.length > 0, "RevShareContractsManager has no code"); - vm.label(REV_SHARE_MANAGER, "RevShareContractsManager"); - - // Set RevShareContractsManager as the allowed target for delegatecall - OPCM_TARGETS.push(REV_SHARE_MANAGER); - - // Load portal addresses - portals = abi.decode(tomlContent.parseRaw(".portals"), (address[])); - require(portals.length > 0, "No portals configured"); - - // Load L1Withdrawer configs by reading each field individually - // Note: We can't use parseRaw + abi.decode directly because TOML inline tables - // sort keys alphabetically, which doesn't match the struct field order - // So we need to read each field separately and construct the struct manually - RevShareContractsManager.L1WithdrawerConfig[] memory configs = - new RevShareContractsManager.L1WithdrawerConfig[](portals.length); - - for (uint256 i = 0; i < portals.length; i++) { - string memory basePath = string.concat(".l1WithdrawerConfigs[", vm.toString(i), "]"); - configs[i] = RevShareContractsManager.L1WithdrawerConfig({ - minWithdrawalAmount: tomlContent.readUint(string.concat(basePath, ".minWithdrawalAmount")), - recipient: tomlContent.readAddress(string.concat(basePath, ".recipient")), - gasLimit: uint32(tomlContent.readUint(string.concat(basePath, ".gasLimit"))) - }); - } - l1WithdrawerConfigsEncoded = abi.encode(configs); - - // Load remainder recipients - remainderRecipients = abi.decode(tomlContent.parseRaw(".remainderRecipients"), (address[])); - require(remainderRecipients.length == portals.length, "Remainder recipients length mismatch"); - } - - /// @notice Builds the actions for executing the operations. - function _build(address) internal override { - // Decode configs from storage - RevShareContractsManager.L1WithdrawerConfig[] memory l1WithdrawerConfigs = - abi.decode(l1WithdrawerConfigsEncoded, (RevShareContractsManager.L1WithdrawerConfig[])); - - // Delegatecall into RevShareContractsManager - // OPCMTaskBase uses Multicall3Delegatecall, so this delegatecall will be captured as an action - (bool success,) = REV_SHARE_MANAGER.delegatecall( - abi.encodeCall( - RevShareContractsManager.upgradeAndSetupRevShare, (portals, l1WithdrawerConfigs, remainderRecipients) - ) - ); - require(success, "RevShareSetup: Delegatecall failed"); - } - - /// @notice This method performs all validations and assertions that verify the calls executed as expected. - function _validate(VmSafe.AccountAccess[] memory, Action[] memory, address) internal view override { - // Add validation logic here if needed - // For now, we rely on the integration tests to validate the L2 state - } - - /// @notice Override to return a list of addresses that should not be checked for code length. - function _getCodeExceptions() internal view virtual override returns (address[] memory) { - return new address[](0); - } -} diff --git a/src/template/RevShareUpgradeAndSetup.sol b/src/template/RevShareUpgradeAndSetup.sol index 4d0f98bd8f..57ea0df301 100644 --- a/src/template/RevShareUpgradeAndSetup.sol +++ b/src/template/RevShareUpgradeAndSetup.sol @@ -3,156 +3,110 @@ pragma solidity 0.8.15; import {VmSafe} from "forge-std/Vm.sol"; import {stdToml} from "forge-std/StdToml.sol"; -import {L2TaskBase} from "src/tasks/types/L2TaskBase.sol"; -import {SuperchainAddressRegistry} from "src/SuperchainAddressRegistry.sol"; -import {Action} from "src/libraries/MultisigTypes.sol"; -import {RevSharePredeploys} from "src/libraries/RevSharePredeploys.sol"; - -/// @notice Interface for the RevShareContractsManager. -interface IRevShareContractsManager { - struct L1WithdrawerConfig { - uint256 minWithdrawalAmount; - address recipient; - uint32 gasLimit; - } +import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; - function upgradeAndSetupRevShare( - address _portal, - string memory _saltSeed, - L1WithdrawerConfig memory _l1Config, - address _chainFeesRecipient - ) external; -} +import {OPCMTaskBase} from "src/tasks/types/OPCMTaskBase.sol"; +import {Action} from "src/libraries/MultisigTypes.sol"; +import {RevShareContractsManager} from "src/RevShareContractsUpgrader.sol"; -/// @notice Template for upgrading vault and fee splitter contracts AND enabling revenue sharing. -/// @dev This template performs the complete upgrade and setup with default calculator. Supports multiple L2 chains. -contract RevShareUpgradeAndSetup is L2TaskBase, RevSharePredeploys { +/// @notice Task for setting up revenue sharing on OP Stack chains. +contract RevShareUpgradeAndSetup is OPCMTaskBase { using stdToml for string; + using EnumerableSet for EnumerableSet.AddressSet; - /// @notice Struct representing configuration for a single chain. - struct ChainConfig { - uint256 chainId; - string saltSeed; - uint256 l1WithdrawerMinWithdrawalAmount; - address l1WithdrawerRecipient; - uint32 l1WithdrawerGasLimit; - address chainFeesRecipient; - } + /// @notice RevShareContractsManager address + address public REV_SHARE_MANAGER; - /// @notice The RevShareContractsManager contract to delegatecall. - address public REVSHARE_MANAGER; + /// @notice Portal addresses for L2 chains. + address[] internal portals; - /// @notice Mapping of chain ID to configuration. - mapping(uint256 => ChainConfig) public cfg; + /// @notice L1Withdrawer configurations (stored as encoded bytes). + bytes internal l1WithdrawerConfigsEncoded; - /// @notice Returns the safe address string identifier. - function safeAddressString() public pure override returns (string memory) { - return "ProxyAdminOwner"; - } + /// @notice Remainder recipients (chain fees recipients). + address[] internal remainderRecipients; - /// @notice Returns the storage write permissions required for this task. + /// @notice Names in the SimpleAddressRegistry that are expected to be written during this task. function _taskStorageWrites() internal pure virtual override returns (string[] memory) { - string[] memory _storageWrites = new string[](1); - _storageWrites[0] = "OptimismPortal"; - return _storageWrites; + return new string[](0); } - /// @notice Returns an array of contract names expected to have balance changes. + /// @notice Returns an array of strings that refer to contract names in the address registry. function _taskBalanceChanges() internal view virtual override returns (string[] memory) { - string[] memory _balanceChanges = new string[](1); - _balanceChanges[0] = "OptimismPortal"; - return _balanceChanges; + return new string[](0); } - /// @notice Sets up the template with configurations from a TOML file. - function _templateSetup(string memory _taskConfigFilePath, address _rootSafe) internal override { - super._templateSetup(_taskConfigFilePath, _rootSafe); - - string memory _toml = vm.readFile(_taskConfigFilePath); - SuperchainAddressRegistry.ChainInfo[] memory _chains = superchainAddrRegistry.getChains(); - - // Load RevShareContractsManager address - REVSHARE_MANAGER = _toml.readAddress(".addresses.RevShareContractsManager"); - require(REVSHARE_MANAGER != address(0), "RevShareContractsManager must be set"); - vm.label(REVSHARE_MANAGER, "RevShareContractsManager"); - - // Load per-chain configurations - // Expected TOML structure: - // [[revShareSetups]] - // chainId = 10 - // saltSeed = "..." - // l1WithdrawerMinWithdrawalAmount = 350000 - // l1WithdrawerRecipient = "0x..." - // l1WithdrawerGasLimit = 800000 - // chainFeesRecipient = "0x..." - ChainConfig[] memory _configs = abi.decode(_toml.parseRaw(".revShareSetups"), (ChainConfig[])); - - for (uint256 i = 0; i < _configs.length; i++) { - ChainConfig memory _config = _configs[i]; - require(bytes(_config.saltSeed).length != 0, "saltSeed must be set for each chain"); - require(_config.l1WithdrawerRecipient != address(0), "l1WithdrawerRecipient must be set"); - require(_config.chainFeesRecipient != address(0), "chainFeesRecipient must be set"); - require(_config.l1WithdrawerGasLimit > 0, "l1WithdrawerGasLimit must be greater than 0"); - - // Verify chainId is in the l2chains list - bool chainFound = false; - for (uint256 j = 0; j < _chains.length; j++) { - if (_chains[j].chainId == _config.chainId) { - chainFound = true; - break; - } - } - require(chainFound, "Chain ID not found in l2chains list"); - - // Store configuration - cfg[_config.chainId] = _config; + /// @notice Sets the allowed storage accesses - override to add portal addresses + function _setAllowedStorageAccesses() internal virtual override { + super._setAllowedStorageAccesses(); + // Add portal addresses as they will have storage writes from depositTransaction calls + for (uint256 i = 0; i < portals.length; i++) { + _allowedStorageAccesses.add(portals[i]); } } - /// @notice Executes the vault/splitter upgrade and revenue sharing setup via delegatecall for each chain. - function _build(address) internal override { - SuperchainAddressRegistry.ChainInfo[] memory chains = superchainAddrRegistry.getChains(); - - for (uint256 i = 0; i < chains.length; i++) { - uint256 chainId = chains[i].chainId; - ChainConfig memory chainCfg = cfg[chainId]; - - // Get portal address for this chain - address portal = superchainAddrRegistry.getAddress("OptimismPortal", chainId); - require(portal != address(0), "OptimismPortal not found for chain"); - - // Prepare L1Withdrawer config - IRevShareContractsManager.L1WithdrawerConfig memory l1Config = IRevShareContractsManager - .L1WithdrawerConfig({ - minWithdrawalAmount: chainCfg.l1WithdrawerMinWithdrawalAmount, - recipient: chainCfg.l1WithdrawerRecipient, - gasLimit: chainCfg.l1WithdrawerGasLimit + /// @notice Sets up the template with configurations from a TOML file. + function _templateSetup(string memory taskConfigFilePath, address) internal override { + string memory tomlContent = vm.readFile(taskConfigFilePath); + + // Load RevShareContractsManager address from TOML + REV_SHARE_MANAGER = tomlContent.readAddress(".revShareManager"); + require(REV_SHARE_MANAGER.code.length > 0, "RevShareContractsManager has no code"); + vm.label(REV_SHARE_MANAGER, "RevShareContractsManager"); + + // Set RevShareContractsManager as the allowed target for delegatecall + OPCM_TARGETS.push(REV_SHARE_MANAGER); + + // Load portal addresses + portals = abi.decode(tomlContent.parseRaw(".portals"), (address[])); + require(portals.length > 0, "No portals configured"); + + // Load L1Withdrawer configs by reading each field individually + // Note: We can't use parseRaw + abi.decode directly because TOML inline tables + // sort keys alphabetically, which doesn't match the struct field order + // So we need to read each field separately and construct the struct manually + RevShareContractsManager.L1WithdrawerConfig[] memory configs = + new RevShareContractsManager.L1WithdrawerConfig[](portals.length); + + for (uint256 i = 0; i < portals.length; i++) { + string memory basePath = string.concat(".l1WithdrawerConfigs[", vm.toString(i), "]"); + configs[i] = RevShareContractsManager.L1WithdrawerConfig({ + minWithdrawalAmount: tomlContent.readUint(string.concat(basePath, ".minWithdrawalAmount")), + recipient: tomlContent.readAddress(string.concat(basePath, ".recipient")), + gasLimit: uint32(tomlContent.readUint(string.concat(basePath, ".gasLimit"))) }); - - // Delegatecall to RevShareContractsManager for this chain - (bool success,) = REVSHARE_MANAGER.delegatecall( - abi.encodeCall( - IRevShareContractsManager.upgradeAndSetupRevShare, - (portal, chainCfg.saltSeed, l1Config, chainCfg.chainFeesRecipient) - ) - ); - require(success, "RevShareUpgradeAndSetup: Delegatecall to upgradeAndSetupRevShare failed"); } + l1WithdrawerConfigsEncoded = abi.encode(configs); + + // Load remainder recipients + remainderRecipients = abi.decode(tomlContent.parseRaw(".remainderRecipients"), (address[])); + require(remainderRecipients.length == portals.length, "Remainder recipients length mismatch"); + } + + /// @notice Builds the actions for executing the operations. + function _build(address) internal override { + // Decode configs from storage + RevShareContractsManager.L1WithdrawerConfig[] memory l1WithdrawerConfigs = + abi.decode(l1WithdrawerConfigsEncoded, (RevShareContractsManager.L1WithdrawerConfig[])); + + // Delegatecall into RevShareContractsManager + // OPCMTaskBase uses Multicall3Delegatecall, so this delegatecall will be captured as an action + (bool success,) = REV_SHARE_MANAGER.delegatecall( + abi.encodeCall( + RevShareContractsManager.upgradeAndSetupRevShare, (portals, l1WithdrawerConfigs, remainderRecipients) + ) + ); + require(success, "RevShareUpgradeAndSetup: Delegatecall failed"); } - /// @notice Validates the operations executed as expected. + /// @notice This method performs all validations and assertions that verify the calls executed as expected. function _validate(VmSafe.AccountAccess[] memory, Action[] memory, address) internal view override { - // Basic validation - state changes are validated by the framework - SuperchainAddressRegistry.ChainInfo[] memory chains = superchainAddrRegistry.getChains(); - for (uint256 i = 0; i < chains.length; i++) { - uint256 chainId = chains[i].chainId; - ChainConfig memory chainCfg = cfg[chainId]; - - // Verify configuration was loaded - require(bytes(chainCfg.saltSeed).length != 0, "Configuration not loaded for chain"); - } + // Add validation logic here if needed + // For now, we rely on the integration tests to validate the L2 state } - /// @notice Returns list of addresses that should not be checked for code length. - function _getCodeExceptions() internal view virtual override returns (address[] memory) {} + /// @notice Override to return a list of addresses that should not be checked for code length. + function _getCodeExceptions() internal view virtual override returns (address[] memory) { + return new address[](0); + } } diff --git a/test/integration/RevShareContractsUpgraderIntegration.t.sol b/test/integration/RevShareContractsUpgraderIntegration.t.sol index 8e59f45ecd..255c60e5ed 100644 --- a/test/integration/RevShareContractsUpgraderIntegration.t.sol +++ b/test/integration/RevShareContractsUpgraderIntegration.t.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.15; import {RevShareContractsManager} from "src/RevShareContractsUpgrader.sol"; -import {RevShareSetup} from "src/template/RevShareSetup.sol"; +import {RevShareUpgradeAndSetup} from "src/template/RevShareUpgradeAndSetup.sol"; import {IntegrationBase} from "./IntegrationBase.t.sol"; import {Test} from "forge-std/Test.sol"; @@ -37,7 +37,7 @@ interface ISuperchainRevSharesCalculator { contract RevShareContractsUpgraderIntegrationTest is IntegrationBase { RevShareContractsManager public revShareManager; - RevShareSetup public revShareTask; + RevShareUpgradeAndSetup public revShareTask; // Fork IDs uint256 internal _mainnetForkId; @@ -81,8 +81,8 @@ contract RevShareContractsUpgraderIntegrationTest is IntegrationBase { vm.etch(REV_SHARE_MANAGER_ADDRESS, address(revShareManager).code); revShareManager = RevShareContractsManager(REV_SHARE_MANAGER_ADDRESS); - // Deploy RevShareSetup task - revShareTask = new RevShareSetup(); + // Deploy RevShareUpgradeAndSetup task + revShareTask = new RevShareUpgradeAndSetup(); } /// @notice Test the integration of upgradeAndSetupRevShare From 582d73bbe8634218c6894c24b559cd2a231d2124 Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Mon, 10 Nov 2025 00:58:47 -0300 Subject: [PATCH 39/69] refactor: use interfaces --- src/RevShareContractsUpgrader.sol | 4 +- src/interfaces/IFeeSplitter.sol | 1 + src/interfaces/IFeeVault.sol | 17 ++++++- src/interfaces/IL1Withdrawer.sol | 8 ++++ .../ISuperchainRevSharesCalculator.sol | 7 +++ ...RevShareContractsUpgraderIntegration.t.sol | 46 ++++++------------- 6 files changed, 46 insertions(+), 37 deletions(-) create mode 100644 src/interfaces/IL1Withdrawer.sol create mode 100644 src/interfaces/ISuperchainRevSharesCalculator.sol diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol index d49ee55f9e..562da20e90 100644 --- a/src/RevShareContractsUpgrader.sol +++ b/src/RevShareContractsUpgrader.sol @@ -177,7 +177,7 @@ contract RevShareContractsManager is RevSharePredeploys { _portal, vaults[i], RevShareGasLimits.SETTERS_GAS_LIMIT, abi.encodeCall(IFeeVault.setMinWithdrawalAmount, (0)) ); _depositCall( - _portal, vaults[i], RevShareGasLimits.SETTERS_GAS_LIMIT, abi.encodeCall(IFeeVault.setWithdrawalNetwork, (1)) + _portal, vaults[i], RevShareGasLimits.SETTERS_GAS_LIMIT, abi.encodeCall(IFeeVault.setWithdrawalNetwork, (IFeeVault.WithdrawalNetwork.L2)) ); } } @@ -210,7 +210,7 @@ contract RevShareContractsManager is RevSharePredeploys { impl, abi.encodeCall( IFeeVault.initialize, - (FEE_SPLITTER, 0, 1) // recipient=FeeSplitter, minWithdrawal=0, network=L2 + (FEE_SPLITTER, 0, IFeeVault.WithdrawalNetwork.L2) // recipient=FeeSplitter, minWithdrawal=0, network=L2 ) ) ) diff --git a/src/interfaces/IFeeSplitter.sol b/src/interfaces/IFeeSplitter.sol index 7a85a9f5b0..680ad671b1 100644 --- a/src/interfaces/IFeeSplitter.sol +++ b/src/interfaces/IFeeSplitter.sol @@ -4,5 +4,6 @@ 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; } diff --git a/src/interfaces/IFeeVault.sol b/src/interfaces/IFeeVault.sol index b28111628e..c0a7206547 100644 --- a/src/interfaces/IFeeVault.sol +++ b/src/interfaces/IFeeVault.sol @@ -2,8 +2,21 @@ pragma solidity 0.8.15; interface IFeeVault { - function initialize(address _recipient, uint256 _minWithdrawalAmount, uint8 _withdrawalNetwork) external; + 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(uint8 _withdrawalNetwork) external; + function setWithdrawalNetwork(WithdrawalNetwork _withdrawalNetwork) external; } diff --git a/src/interfaces/IL1Withdrawer.sol b/src/interfaces/IL1Withdrawer.sol new file mode 100644 index 0000000000..3a0e3b0490 --- /dev/null +++ b/src/interfaces/IL1Withdrawer.sol @@ -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); +} \ No newline at end of file diff --git a/src/interfaces/ISuperchainRevSharesCalculator.sol b/src/interfaces/ISuperchainRevSharesCalculator.sol new file mode 100644 index 0000000000..37f855091c --- /dev/null +++ b/src/interfaces/ISuperchainRevSharesCalculator.sol @@ -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); +} \ No newline at end of file diff --git a/test/integration/RevShareContractsUpgraderIntegration.t.sol b/test/integration/RevShareContractsUpgraderIntegration.t.sol index 255c60e5ed..2d6bbf6c75 100644 --- a/test/integration/RevShareContractsUpgraderIntegration.t.sol +++ b/test/integration/RevShareContractsUpgraderIntegration.t.sol @@ -6,34 +6,14 @@ import {RevShareUpgradeAndSetup} from "src/template/RevShareUpgradeAndSetup.sol" import {IntegrationBase} from "./IntegrationBase.t.sol"; import {Test} from "forge-std/Test.sol"; -enum WithdrawalNetwork { - L1, - L2 -} - -interface IFeeVault { - function MIN_WITHDRAWAL_AMOUNT() external view returns (uint256); - function RECIPIENT() external view returns (address); - 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); -} - -interface IFeeSplitter { - function sharesCalculator() external view returns (address); -} - -interface IL1Withdrawer { - function minWithdrawalAmount() external view returns (uint256); - function recipient() external view returns (address); - function withdrawalGasLimit() external view returns (uint32); -} - -interface ISuperchainRevSharesCalculator { - function shareRecipient() external view returns (address payable); - function remainderRecipient() external view returns (address payable); -} +// 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"; +import {IL1Withdrawer} from "src/interfaces/IL1Withdrawer.sol"; +import {ISuperchainRevSharesCalculator} from "src/interfaces/ISuperchainRevSharesCalculator.sol"; contract RevShareContractsUpgraderIntegrationTest is IntegrationBase { RevShareContractsManager public revShareManager; @@ -145,10 +125,10 @@ contract RevShareContractsUpgraderIntegrationTest is IntegrationBase { /// @notice Assert the configuration of all fee vaults function _assertFeeVaultsState() internal view { - _assertVaultGetters(SEQUENCER_FEE_VAULT, FEE_SPLITTER, WithdrawalNetwork.L2, 0); - _assertVaultGetters(OPERATOR_FEE_VAULT, FEE_SPLITTER, WithdrawalNetwork.L2, 0); - _assertVaultGetters(BASE_FEE_VAULT, FEE_SPLITTER, WithdrawalNetwork.L2, 0); - _assertVaultGetters(L1_FEE_VAULT, FEE_SPLITTER, WithdrawalNetwork.L2, 0); + _assertVaultGetters(SEQUENCER_FEE_VAULT, FEE_SPLITTER, IFeeVault.WithdrawalNetwork.L2, 0); + _assertVaultGetters(OPERATOR_FEE_VAULT, FEE_SPLITTER, IFeeVault.WithdrawalNetwork.L2, 0); + _assertVaultGetters(BASE_FEE_VAULT, FEE_SPLITTER, IFeeVault.WithdrawalNetwork.L2, 0); + _assertVaultGetters(L1_FEE_VAULT, FEE_SPLITTER, IFeeVault.WithdrawalNetwork.L2, 0); } /// @notice Assert the configuration of a single fee vault @@ -160,7 +140,7 @@ contract RevShareContractsUpgraderIntegrationTest is IntegrationBase { function _assertVaultGetters( address _vault, address _recipient, - WithdrawalNetwork _withdrawalNetwork, + IFeeVault.WithdrawalNetwork _withdrawalNetwork, uint256 _minWithdrawalAmount ) internal view { // Check new getters From acaaf16410bded9f9257c6b787a6c277f642350c Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Mon, 10 Nov 2025 01:00:10 -0300 Subject: [PATCH 40/69] chore: improve readability --- test/integration/RevShareContractsUpgraderIntegration.t.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/integration/RevShareContractsUpgraderIntegration.t.sol b/test/integration/RevShareContractsUpgraderIntegration.t.sol index 2d6bbf6c75..8ebc079902 100644 --- a/test/integration/RevShareContractsUpgraderIntegration.t.sol +++ b/test/integration/RevShareContractsUpgraderIntegration.t.sol @@ -46,6 +46,7 @@ contract RevShareContractsUpgraderIntegrationTest is IntegrationBase { address internal constant L1_WITHDRAWAL_RECIPIENT = address(1); // Placeholder uint32 internal constant WITHDRAWAL_GAS_LIMIT = 800000; address internal constant CHAIN_FEES_RECIPIENT = address(1); // Placeholder + bool internal constant IS_SIMULATE = true; function setUp() public { // Create forks for L1 (mainnet) and L2 (OP Mainnet) @@ -82,7 +83,7 @@ contract RevShareContractsUpgraderIntegrationTest is IntegrationBase { portals[0] = OP_MAINNET_PORTAL; portals[1] = INK_MAINNET_PORTAL; - _relayAllMessages(forkIds, true, portals); + _relayAllMessages(forkIds, IS_SIMULATE, portals); // Step 4: Assert the state of the OP Mainnet contracts vm.selectFork(_opMainnetForkId); From d69bf104ae70e84b36cc14bafb99b402a17cb1c8 Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Mon, 10 Nov 2025 01:02:15 -0300 Subject: [PATCH 41/69] chore: fix contract name --- src/RevShareContractsUpgrader.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol index 562da20e90..e70b916fba 100644 --- a/src/RevShareContractsUpgrader.sol +++ b/src/RevShareContractsUpgrader.sol @@ -13,7 +13,7 @@ import {ICreate2Deployer} from "src/interfaces/ICreate2Deployer.sol"; import {IFeeSplitter} from "src/interfaces/IFeeSplitter.sol"; import {IFeeVault} from "src/interfaces/IFeeVault.sol"; -/// @title RevShareContractsManager +/// @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 From a5f713f5434f02196d8ea428e42927bac871bc02 Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Mon, 10 Nov 2025 01:31:53 -0300 Subject: [PATCH 42/69] feat: fix contract naming, add regression tests --- .../example/eth/018-revshare-upgrade-and-setup/config.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/tasks/example/eth/018-revshare-upgrade-and-setup/config.toml b/test/tasks/example/eth/018-revshare-upgrade-and-setup/config.toml index 7fb2d06785..25aa8c669e 100644 --- a/test/tasks/example/eth/018-revshare-upgrade-and-setup/config.toml +++ b/test/tasks/example/eth/018-revshare-upgrade-and-setup/config.toml @@ -1,5 +1,7 @@ # RevShare Setup Configuration +templateName = "RevShareUpgradeAndSetup" + # L2 chains to target l2chains = [{name = "OP Mainnet", chainId = 10}, {name = "Ink", chainId = 57073}] From 1e674a411067406f275915993495b99a3f2597c3 Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Mon, 10 Nov 2025 11:32:57 -0300 Subject: [PATCH 43/69] test: add todo regression --- src/RevShareContractsUpgrader.sol | 2 +- src/template/RevShareUpgradeAndSetup.sol | 55 +++++++++++++------ ...RevShareContractsUpgraderIntegration.t.sol | 10 ++-- test/tasks/Regression.t.sol | 25 +++++++++ 4 files changed, 70 insertions(+), 22 deletions(-) diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol index e70b916fba..6c9fa78b22 100644 --- a/src/RevShareContractsUpgrader.sol +++ b/src/RevShareContractsUpgrader.sol @@ -19,7 +19,7 @@ import {IFeeVault} from "src/interfaces/IFeeVault.sol"; /// 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 RevShareContractsManager is RevSharePredeploys { +contract RevShareContractsUpgrader is RevSharePredeploys { /// @notice Base salt seed for CREATE2 deployments string private constant SALT_SEED = "RevShare"; diff --git a/src/template/RevShareUpgradeAndSetup.sol b/src/template/RevShareUpgradeAndSetup.sol index 57ea0df301..e1e279cc31 100644 --- a/src/template/RevShareUpgradeAndSetup.sol +++ b/src/template/RevShareUpgradeAndSetup.sol @@ -7,14 +7,15 @@ import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet import {OPCMTaskBase} from "src/tasks/types/OPCMTaskBase.sol"; import {Action} from "src/libraries/MultisigTypes.sol"; -import {RevShareContractsManager} from "src/RevShareContractsUpgrader.sol"; +import {MultisigTaskPrinter} from "src/libraries/MultisigTaskPrinter.sol"; +import {RevShareContractsUpgrader} from "src/RevShareContractsUpgrader.sol"; /// @notice Task for setting up revenue sharing on OP Stack chains. contract RevShareUpgradeAndSetup is OPCMTaskBase { using stdToml for string; using EnumerableSet for EnumerableSet.AddressSet; - /// @notice RevShareContractsManager address + /// @notice RevShareContractsUpgrader address address public REV_SHARE_MANAGER; /// @notice Portal addresses for L2 chains. @@ -49,12 +50,12 @@ contract RevShareUpgradeAndSetup is OPCMTaskBase { function _templateSetup(string memory taskConfigFilePath, address) internal override { string memory tomlContent = vm.readFile(taskConfigFilePath); - // Load RevShareContractsManager address from TOML + // Load RevShareContractsUpgrader address from TOML REV_SHARE_MANAGER = tomlContent.readAddress(".revShareManager"); - require(REV_SHARE_MANAGER.code.length > 0, "RevShareContractsManager has no code"); - vm.label(REV_SHARE_MANAGER, "RevShareContractsManager"); + require(REV_SHARE_MANAGER.code.length > 0, "RevShareContractsUpgrader has no code"); + vm.label(REV_SHARE_MANAGER, "RevShareContractsUpgrader"); - // Set RevShareContractsManager as the allowed target for delegatecall + // Set RevShareContractsUpgrader as the allowed target for delegatecall OPCM_TARGETS.push(REV_SHARE_MANAGER); // Load portal addresses @@ -65,12 +66,12 @@ contract RevShareUpgradeAndSetup is OPCMTaskBase { // Note: We can't use parseRaw + abi.decode directly because TOML inline tables // sort keys alphabetically, which doesn't match the struct field order // So we need to read each field separately and construct the struct manually - RevShareContractsManager.L1WithdrawerConfig[] memory configs = - new RevShareContractsManager.L1WithdrawerConfig[](portals.length); + RevShareContractsUpgrader.L1WithdrawerConfig[] memory configs = + new RevShareContractsUpgrader.L1WithdrawerConfig[](portals.length); for (uint256 i = 0; i < portals.length; i++) { string memory basePath = string.concat(".l1WithdrawerConfigs[", vm.toString(i), "]"); - configs[i] = RevShareContractsManager.L1WithdrawerConfig({ + configs[i] = RevShareContractsUpgrader.L1WithdrawerConfig({ minWithdrawalAmount: tomlContent.readUint(string.concat(basePath, ".minWithdrawalAmount")), recipient: tomlContent.readAddress(string.concat(basePath, ".recipient")), gasLimit: uint32(tomlContent.readUint(string.concat(basePath, ".gasLimit"))) @@ -86,23 +87,45 @@ contract RevShareUpgradeAndSetup is OPCMTaskBase { /// @notice Builds the actions for executing the operations. function _build(address) internal override { // Decode configs from storage - RevShareContractsManager.L1WithdrawerConfig[] memory l1WithdrawerConfigs = - abi.decode(l1WithdrawerConfigsEncoded, (RevShareContractsManager.L1WithdrawerConfig[])); + RevShareContractsUpgrader.L1WithdrawerConfig[] memory l1WithdrawerConfigs = + abi.decode(l1WithdrawerConfigsEncoded, (RevShareContractsUpgrader.L1WithdrawerConfig[])); - // Delegatecall into RevShareContractsManager + // Delegatecall into RevShareContractsUpgrader // OPCMTaskBase uses Multicall3Delegatecall, so this delegatecall will be captured as an action (bool success,) = REV_SHARE_MANAGER.delegatecall( abi.encodeCall( - RevShareContractsManager.upgradeAndSetupRevShare, (portals, l1WithdrawerConfigs, remainderRecipients) + RevShareContractsUpgrader.upgradeAndSetupRevShare, (portals, l1WithdrawerConfigs, remainderRecipients) ) ); require(success, "RevShareUpgradeAndSetup: Delegatecall failed"); } /// @notice This method performs all validations and assertions that verify the calls executed as expected. - function _validate(VmSafe.AccountAccess[] memory, Action[] memory, address) internal view override { - // Add validation logic here if needed - // For now, we rely on the integration tests to validate the L2 state + function _validate(VmSafe.AccountAccess[] memory, Action[] memory _actions, address) internal view override { + MultisigTaskPrinter.printTitle("Validating delegatecall to RevShareContractsUpgrader"); + + // For OPCM tasks using delegatecall, we validate that the delegatecall was made correctly. + // The actual portal calls happen inside the delegatecall and are validated by integration tests. + + require(_actions.length == 1, "Expected exactly one action"); + + bool foundDelegatecall = false; + + for (uint256 i = 0; i < _actions.length; i++) { + Action memory action = _actions[i]; + // Check if this is a delegatecall to RevShareContractsUpgrader + if (action.target == REV_SHARE_MANAGER) { + foundDelegatecall = true; + // Verify it's calling upgradeAndSetupRevShare + bytes4 selector = bytes4(action.arguments); + require( + selector == RevShareContractsUpgrader.upgradeAndSetupRevShare.selector, + "Wrong function selector for delegatecall" + ); + } + } + + require(foundDelegatecall, "Delegatecall to RevShareContractsUpgrader not found"); } /// @notice Override to return a list of addresses that should not be checked for code length. diff --git a/test/integration/RevShareContractsUpgraderIntegration.t.sol b/test/integration/RevShareContractsUpgraderIntegration.t.sol index 8ebc079902..04fc30b1d1 100644 --- a/test/integration/RevShareContractsUpgraderIntegration.t.sol +++ b/test/integration/RevShareContractsUpgraderIntegration.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import {RevShareContractsManager} from "src/RevShareContractsUpgrader.sol"; +import {RevShareContractsUpgrader} from "src/RevShareContractsUpgrader.sol"; import {RevShareUpgradeAndSetup} from "src/template/RevShareUpgradeAndSetup.sol"; import {IntegrationBase} from "./IntegrationBase.t.sol"; import {Test} from "forge-std/Test.sol"; @@ -16,7 +16,7 @@ import {IL1Withdrawer} from "src/interfaces/IL1Withdrawer.sol"; import {ISuperchainRevSharesCalculator} from "src/interfaces/ISuperchainRevSharesCalculator.sol"; contract RevShareContractsUpgraderIntegrationTest is IntegrationBase { - RevShareContractsManager public revShareManager; + RevShareContractsUpgrader public revShareManager; RevShareUpgradeAndSetup public revShareTask; // Fork IDs @@ -57,10 +57,10 @@ contract RevShareContractsUpgraderIntegrationTest is IntegrationBase { // Deploy contracts on L1 vm.selectFork(_mainnetForkId); - // Deploy RevShareContractsManager and etch at predetermined address - revShareManager = new RevShareContractsManager(); + // Deploy RevShareContractsUpgrader and etch at predetermined address + revShareManager = new RevShareContractsUpgrader(); vm.etch(REV_SHARE_MANAGER_ADDRESS, address(revShareManager).code); - revShareManager = RevShareContractsManager(REV_SHARE_MANAGER_ADDRESS); + revShareManager = RevShareContractsUpgrader(REV_SHARE_MANAGER_ADDRESS); // Deploy RevShareUpgradeAndSetup task revShareTask = new RevShareUpgradeAndSetup(); diff --git a/test/tasks/Regression.t.sol b/test/tasks/Regression.t.sol index 139457f049..8de74a8721 100644 --- a/test/tasks/Regression.t.sol +++ b/test/tasks/Regression.t.sol @@ -41,6 +41,7 @@ import {OPCMUpgradeV410} from "src/template/OPCMUpgradeV410.sol"; import {OPCMUpgradeSuperchainConfigV410} from "src/template/OPCMUpgradeSuperchainConfigV410.sol"; import {RevenueShareV100UpgradePath} from "src/template/RevenueShareUpgradePath.sol"; import {DeployFeesDepositor} from "src/template/DeployFeesDepositor.sol"; +import {RevShareUpgradeAndSetup} from "src/template/RevShareUpgradeAndSetup.sol"; import {L1PortalExecuteL2Call} from "src/template/L1PortalExecuteL2Call.sol"; import {AddGameTypeTemplate} from "src/template/AddGameTypeTemplate.sol"; @@ -1002,6 +1003,30 @@ contract RegressionTest is Test { _assertDataToSignNestedMultisig(multisigTask, actions, expectedDataToSign, MULTICALL3_ADDRESS, rootSafe); } + /// @notice Expected call data and data to sign generated by manually running the RevShareUpgradeAndSetup template at block TBD on mainnet. + /// Simulate from task directory (test/tasks/example/eth/018-revshare-upgrade-and-setup/config.toml) with: + /// just --dotenv-path $(pwd)/.env --justfile ../../../../../src/improvements/justfile simulate (foundation|council) + function testRegressionCallDataMatches_RevShareUpgradeAndSetup() public { + vm.skip(true); // TODO: deploy upgrader + string memory taskConfigFilePath = "test/tasks/example/eth/018-revshare-upgrade-and-setup/config.toml"; + string memory expectedCallData = ""; + MultisigTask multisigTask = new RevShareUpgradeAndSetup(); + address rootSafe = address(0x5a0Aae59D09fccBdDb6C6CcEB07B7279367C3d2A); // L1PAO + address securityCouncilChildMultisig = address(0xc2819DC788505Aac350142A7A707BF9D03E3Bd03); + address[] memory allSafes = MultisigTaskTestHelper.getAllSafes(rootSafe, securityCouncilChildMultisig); + + (Action[] memory actions, uint256[] memory allOriginalNonces) = + _setupAndSimulate(taskConfigFilePath, 23434662, "mainnet", multisigTask, allSafes); + _assertCallDataMatches(multisigTask, actions, allSafes, allOriginalNonces, expectedCallData); + + string[] memory expectedDataToSign = new string[](2); + // Foundation + expectedDataToSign[0] = ""; + // Security Council + expectedDataToSign[1] = ""; + _assertDataToSignNestedMultisig(multisigTask, actions, expectedDataToSign, MULTICALL3_ADDRESS, rootSafe); + } + /// @notice Expected call data and data to sign generated by manually running the GnosisSafeRotateSigner at block 9264006 on sepolia using script: /// forge script GnosisSafeRotateSigner --sig "simulate(string)" test/tasks/example/sep/016-gnosis-safe-remove-owner/config.toml --rpc-url sepolia --fork-block-number 9264006 -vv function testRegressionCallDataMatches_GnosisSafeRotateSigner() public { From 4c3e55e6b5df7352f6d2ccab3248b0ebe6f8636d Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Mon, 10 Nov 2025 16:29:39 -0300 Subject: [PATCH 44/69] test: make integration tests with different configs for both chains --- ...RevShareContractsUpgraderIntegration.t.sol | 59 +++++++++++++------ .../config.toml | 12 ++-- 2 files changed, 46 insertions(+), 25 deletions(-) diff --git a/test/integration/RevShareContractsUpgraderIntegration.t.sol b/test/integration/RevShareContractsUpgraderIntegration.t.sol index 04fc30b1d1..939c100c12 100644 --- a/test/integration/RevShareContractsUpgraderIntegration.t.sol +++ b/test/integration/RevShareContractsUpgraderIntegration.t.sol @@ -38,14 +38,24 @@ contract RevShareContractsUpgraderIntegrationTest is IntegrationBase { address internal constant FEE_SPLITTER = 0x420000000000000000000000000000000000002B; // Expected deployed contracts (deterministic CREATE2 addresses) - address internal constant L1_WITHDRAWER = 0xB3AeB34b88D73Fb4832f65BEa5Bd865017fB5daC; - address internal constant REV_SHARE_CALCULATOR = 0x3E806Fd8592366E850197FEC8D80608b5526Bba2; - - // Test configuration - uint256 internal constant MIN_WITHDRAWAL_AMOUNT = 350000; - address internal constant L1_WITHDRAWAL_RECIPIENT = address(1); // Placeholder - uint32 internal constant WITHDRAWAL_GAS_LIMIT = 800000; - address internal constant CHAIN_FEES_RECIPIENT = address(1); // Placeholder + address internal constant OP_L1_WITHDRAWER = 0xB3AeB34b88D73Fb4832f65BEa5Bd865017fB5daC; + address internal constant OP_REV_SHARE_CALCULATOR = 0x3E806Fd8592366E850197FEC8D80608b5526Bba2; + + address internal constant INK_L1_WITHDRAWER = 0x70e26B12a578176BccCD3b7e7f58f605871c5eF7; + address internal constant INK_REV_SHARE_CALCULATOR = 0xd7a5307B4Ce92B0269903191007b95dF42552Dfa; + + // Test configuration - OP Mainnet + uint256 internal constant OP_MIN_WITHDRAWAL_AMOUNT = 350000; + address internal constant OP_L1_WITHDRAWAL_RECIPIENT = 0x0000000000000000000000000000000000000001; + uint32 internal constant OP_WITHDRAWAL_GAS_LIMIT = 800000; + address internal constant OP_CHAIN_FEES_RECIPIENT = 0x0000000000000000000000000000000000000001; + + // Test configuration - Ink Mainnet + uint256 internal constant INK_MIN_WITHDRAWAL_AMOUNT = 500000; + address internal constant INK_L1_WITHDRAWAL_RECIPIENT = 0x0000000000000000000000000000000000000002; + uint32 internal constant INK_WITHDRAWAL_GAS_LIMIT = 1000000; + address internal constant INK_CHAIN_FEES_RECIPIENT = 0x0000000000000000000000000000000000000002; + bool internal constant IS_SIMULATE = true; function setUp() public { @@ -87,36 +97,47 @@ contract RevShareContractsUpgraderIntegrationTest is IntegrationBase { // Step 4: Assert the state of the OP Mainnet contracts vm.selectFork(_opMainnetForkId); - _assertL2State(); + _assertL2State(OP_L1_WITHDRAWER, OP_REV_SHARE_CALCULATOR, OP_MIN_WITHDRAWAL_AMOUNT, OP_L1_WITHDRAWAL_RECIPIENT, OP_WITHDRAWAL_GAS_LIMIT, OP_CHAIN_FEES_RECIPIENT); // Step 5: Assert the state of the Ink Mainnet contracts vm.selectFork(_inkMainnetForkId); - _assertL2State(); + _assertL2State(INK_L1_WITHDRAWER, INK_REV_SHARE_CALCULATOR, INK_MIN_WITHDRAWAL_AMOUNT, INK_L1_WITHDRAWAL_RECIPIENT, INK_WITHDRAWAL_GAS_LIMIT, INK_CHAIN_FEES_RECIPIENT); } /// @notice Assert the state of all L2 contracts after upgrade - function _assertL2State() internal view { + /// @param _minWithdrawalAmount Expected minimum withdrawal amount for L1Withdrawer + /// @param _l1Recipient Expected recipient address for L1Withdrawer + /// @param _gasLimit Expected gas limit for L1Withdrawer + /// @param _chainFeesRecipient Expected chain fees recipient (remainder recipient) + function _assertL2State( + address _l1Withdrawer, + address _revShareCalculator, + uint256 _minWithdrawalAmount, + address _l1Recipient, + uint32 _gasLimit, + address _chainFeesRecipient + ) internal view { // L1Withdrawer: check configuration - assertEq(IL1Withdrawer(L1_WITHDRAWER).minWithdrawalAmount(), MIN_WITHDRAWAL_AMOUNT, "L1Withdrawer minWithdrawalAmount mismatch"); - assertEq(IL1Withdrawer(L1_WITHDRAWER).recipient(), L1_WITHDRAWAL_RECIPIENT, "L1Withdrawer recipient mismatch"); - assertEq(IL1Withdrawer(L1_WITHDRAWER).withdrawalGasLimit(), WITHDRAWAL_GAS_LIMIT, "L1Withdrawer gasLimit mismatch"); + assertEq(IL1Withdrawer(_l1Withdrawer).minWithdrawalAmount(), _minWithdrawalAmount, "L1Withdrawer minWithdrawalAmount mismatch"); + assertEq(IL1Withdrawer(_l1Withdrawer).recipient(), _l1Recipient, "L1Withdrawer recipient mismatch"); + assertEq(IL1Withdrawer(_l1Withdrawer).withdrawalGasLimit(), _gasLimit, "L1Withdrawer gasLimit mismatch"); // Rev Share Calculator: check it's linked correctly assertEq( - ISuperchainRevSharesCalculator(REV_SHARE_CALCULATOR).shareRecipient(), - L1_WITHDRAWER, + ISuperchainRevSharesCalculator(_revShareCalculator).shareRecipient(), + _l1Withdrawer, "Calculator shareRecipient should be L1Withdrawer" ); assertEq( - ISuperchainRevSharesCalculator(REV_SHARE_CALCULATOR).remainderRecipient(), - CHAIN_FEES_RECIPIENT, + ISuperchainRevSharesCalculator(_revShareCalculator).remainderRecipient(), + _chainFeesRecipient, "Calculator remainderRecipient mismatch" ); // Fee Splitter: check calculator is set assertEq( IFeeSplitter(FEE_SPLITTER).sharesCalculator(), - REV_SHARE_CALCULATOR, + _revShareCalculator, "FeeSplitter calculator should be set to RevShareCalculator" ); diff --git a/test/tasks/example/eth/018-revshare-upgrade-and-setup/config.toml b/test/tasks/example/eth/018-revshare-upgrade-and-setup/config.toml index 25aa8c669e..5d704f302f 100644 --- a/test/tasks/example/eth/018-revshare-upgrade-and-setup/config.toml +++ b/test/tasks/example/eth/018-revshare-upgrade-and-setup/config.toml @@ -16,16 +16,16 @@ portals = [ "0x5d66C1782664115999C47c9fA5cd031f495D3e4F" # Ink Mainnet Portal ] -# Chain fees recipients +# Chain fees recipients (remainder recipients for each chain) remainderRecipients = [ - "0x0000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000001" + "0x0000000000000000000000000000000000000001", # OP Mainnet chain fees recipient + "0x0000000000000000000000000000000000000002" # Ink Mainnet chain fees recipient ] -# L1Withdrawer configurations +# L1Withdrawer configurations (different for each chain) l1WithdrawerConfigs = [ - {minWithdrawalAmount = 350000, recipient = "0x0000000000000000000000000000000000000001", gasLimit = 800000}, - {minWithdrawalAmount = 350000, recipient = "0x0000000000000000000000000000000000000001", gasLimit = 800000} + {minWithdrawalAmount = 350000, recipient = "0x0000000000000000000000000000000000000001", gasLimit = 800000}, # OP Mainnet L1Withdrawer + {minWithdrawalAmount = 500000, recipient = "0x0000000000000000000000000000000000000002", gasLimit = 1000000} # Ink Mainnet L1Withdrawer ] [addresses] From 30795431cf3fa424cb0ca1c87ce7aa883219496b Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Mon, 10 Nov 2025 16:30:15 -0300 Subject: [PATCH 45/69] chore: remove regression tests until upgrader is deployed --- test/tasks/Regression.t.sol | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/test/tasks/Regression.t.sol b/test/tasks/Regression.t.sol index 8de74a8721..c27acf80c1 100644 --- a/test/tasks/Regression.t.sol +++ b/test/tasks/Regression.t.sol @@ -1003,30 +1003,6 @@ contract RegressionTest is Test { _assertDataToSignNestedMultisig(multisigTask, actions, expectedDataToSign, MULTICALL3_ADDRESS, rootSafe); } - /// @notice Expected call data and data to sign generated by manually running the RevShareUpgradeAndSetup template at block TBD on mainnet. - /// Simulate from task directory (test/tasks/example/eth/018-revshare-upgrade-and-setup/config.toml) with: - /// just --dotenv-path $(pwd)/.env --justfile ../../../../../src/improvements/justfile simulate (foundation|council) - function testRegressionCallDataMatches_RevShareUpgradeAndSetup() public { - vm.skip(true); // TODO: deploy upgrader - string memory taskConfigFilePath = "test/tasks/example/eth/018-revshare-upgrade-and-setup/config.toml"; - string memory expectedCallData = ""; - MultisigTask multisigTask = new RevShareUpgradeAndSetup(); - address rootSafe = address(0x5a0Aae59D09fccBdDb6C6CcEB07B7279367C3d2A); // L1PAO - address securityCouncilChildMultisig = address(0xc2819DC788505Aac350142A7A707BF9D03E3Bd03); - address[] memory allSafes = MultisigTaskTestHelper.getAllSafes(rootSafe, securityCouncilChildMultisig); - - (Action[] memory actions, uint256[] memory allOriginalNonces) = - _setupAndSimulate(taskConfigFilePath, 23434662, "mainnet", multisigTask, allSafes); - _assertCallDataMatches(multisigTask, actions, allSafes, allOriginalNonces, expectedCallData); - - string[] memory expectedDataToSign = new string[](2); - // Foundation - expectedDataToSign[0] = ""; - // Security Council - expectedDataToSign[1] = ""; - _assertDataToSignNestedMultisig(multisigTask, actions, expectedDataToSign, MULTICALL3_ADDRESS, rootSafe); - } - /// @notice Expected call data and data to sign generated by manually running the GnosisSafeRotateSigner at block 9264006 on sepolia using script: /// forge script GnosisSafeRotateSigner --sig "simulate(string)" test/tasks/example/sep/016-gnosis-safe-remove-owner/config.toml --rpc-url sepolia --fork-block-number 9264006 -vv function testRegressionCallDataMatches_GnosisSafeRotateSigner() public { From 616fb008b150f05a97b99ae2f5a89ddbab1dd31d Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Mon, 10 Nov 2025 16:39:51 -0300 Subject: [PATCH 46/69] chore: remove deprecated tasks and tests --- src/template/DeployFeesDepositor.sol | 149 ------------ ...RevShareContractsUpgraderIntegration.t.sol | 2 +- test/tasks/Regression.t.sol | 82 ------- .../eth/015-revenue-share-upgrade/.env | 3 - .../eth/015-revenue-share-upgrade/config.toml | 23 -- .../eth/016-deploy-fees-depositor/.env | 3 - .../eth/016-deploy-fees-depositor/config.toml | 11 - .../config.toml | 0 .../.env | 3 - .../config.toml | 16 -- .../DeployFeesDepositor.t.sol | 223 ------------------ 11 files changed, 1 insertion(+), 514 deletions(-) delete mode 100644 src/template/DeployFeesDepositor.sol delete mode 100644 test/tasks/example/eth/015-revenue-share-upgrade/.env delete mode 100644 test/tasks/example/eth/015-revenue-share-upgrade/config.toml delete mode 100644 test/tasks/example/eth/016-deploy-fees-depositor/.env delete mode 100644 test/tasks/example/eth/016-deploy-fees-depositor/config.toml rename test/tasks/example/eth/{018-revshare-upgrade-and-setup => 016-revshare-upgrade-and-setup}/config.toml (100%) delete mode 100644 test/tasks/example/eth/017-revenue-share-upgrade-custom-calc/.env delete mode 100644 test/tasks/example/eth/017-revenue-share-upgrade-custom-calc/config.toml delete mode 100644 test/template/deploy-fees-depositor/DeployFeesDepositor.t.sol diff --git a/src/template/DeployFeesDepositor.sol b/src/template/DeployFeesDepositor.sol deleted file mode 100644 index b69fbe5330..0000000000 --- a/src/template/DeployFeesDepositor.sol +++ /dev/null @@ -1,149 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.15; - -import {VmSafe} from "forge-std/Vm.sol"; -import {LibString} from "@solady/utils/LibString.sol"; -import {stdToml} from "lib/forge-std/src/StdToml.sol"; -import {SimpleTaskBase} from "src/tasks/types/SimpleTaskBase.sol"; -import {Action} from "src/libraries/MultisigTypes.sol"; -import {RevShareCodeRepo} from "src/libraries/RevShareCodeRepo.sol"; -import {Proxy} from "optimism/packages/contracts-bedrock/src/universal/Proxy.sol"; -import {Create2} from "@openzeppelin/contracts/utils/Create2.sol"; - -/// @notice Interface for the FeesDepositor contract on L1. -/// This is used to deposit fees into L2. -interface IFeesDepositor { - function initialize(uint96 _minDepositAmount, address _l2Recipient, address _messenger, uint32 _gasLimit) - external; - function minDepositAmount() external view returns (uint96); - function l2Recipient() external view returns (address); - function gasLimit() external view returns (uint32); -} - -/// @notice Interface for the CREATE2 deployer contract. -interface ICreate2Deployer { - function deploy(uint256 value, bytes32 salt, bytes memory code) external; -} - -/// @notice Interface for the ProxyAdmin contract. -interface IProxyAdmin { - function upgradeAndCall(address payable _proxy, address _implementation, bytes memory _data) external; -} - -/// @notice A template contract for deploying and initializing the FeesDepositor contract. -contract DeployFeesDepositor is SimpleTaskBase { - using LibString for string; - using stdToml for string; - - /// @notice The address of the CREATE2 deployer contract. - /// @notice This is present in OP Stack chains as a Preinstall and on L1. - address internal constant CREATE2_DEPLOYER = address(0x13b0D85CcB8bf860b6b79AF3029fCA081AE9beF2); - - /// @notice The salt for the deployment of the FeesDepositor contract. - string public salt; - /// @notice The address of the L2 recipient of the fees. - address public l2Recipient; - /// @notice The minimum amount of fees the depositor needs before initiating a deposit. - uint96 public minDepositAmount; - /// @notice The address of the portal contract. - address public portal; - /// @notice The gas limit for the deposit. - uint32 public gasLimit; - /// @notice The address of the proxy admin. - address public proxyAdmin; - - /// @notice The initialization code for the proxy contract. Sent to the CREATE2 deployer. - bytes internal _proxyInitCode; - /// @notice The calculated address of the proxy contract. - address internal _proxyCalculatedAddress; - /// @notice The calculated address of the FeesDepositor implementation contract. - address internal _implCalculatedAddress; - - /// @notice Returns the safe address string identifier. - function safeAddressString() public pure override returns (string memory) { - return "ProxyAdminOwner"; - } - - /// @notice Returns the storage write permissions required for this task. This is an array of - /// contract names that are expected to be written to during the execution of the task. - function _taskStorageWrites() internal pure virtual override returns (string[] memory) {} - - /// @notice Returns an array of strings that refer to contract names in the address registry. - /// Contracts with these names are expected to have their balance changes during the task. - /// By default returns an empty array. Override this function if your task expects balance changes. - function _taskBalanceChanges() internal view virtual override returns (string[] memory) {} - - /// @notice Sets up the template with implementation configurations from a TOML file. - /// State overrides are not applied yet. Keep this in mind when performing various pre-simulation assertions in this function. - function _templateSetup(string memory _taskConfigFilePath, address) internal override { - string memory tomlContent = vm.readFile(_taskConfigFilePath); - salt = tomlContent.readString(".salt"); - require(bytes(salt).length > 0, "salt must be set"); - - // Default to 0 if not set - minDepositAmount = uint96(tomlContent.readUint(".minDepositAmount")); - - l2Recipient = tomlContent.readAddress(".l2Recipient"); - require(l2Recipient != address(0), "l2Recipient must be set"); - - portal = tomlContent.readAddress(".portal"); - require(portal != address(0), "portal must be set"); - - uint256 _gasLimitRaw = tomlContent.readUint(".gasLimit"); - require(_gasLimitRaw > 0, "gasLimit must be set"); - require(_gasLimitRaw <= type(uint32).max, "gasLimit must be less than uint32.max"); - gasLimit = uint32(_gasLimitRaw); - - proxyAdmin = tomlContent.readAddress(".proxyAdmin"); - require(proxyAdmin != address(0), "proxyAdmin must be set"); - - _proxyInitCode = bytes.concat(type(Proxy).creationCode, abi.encode(proxyAdmin)); - - _proxyCalculatedAddress = - Create2.computeAddress(bytes32(bytes(salt)), keccak256(_proxyInitCode), CREATE2_DEPLOYER); - vm.label(_proxyCalculatedAddress, "Proxy"); - - _implCalculatedAddress = Create2.computeAddress( - bytes32(bytes(salt)), keccak256(RevShareCodeRepo.feesDepositorCreationCode), CREATE2_DEPLOYER - ); - vm.label(_implCalculatedAddress, "FeesDepositorV100"); - } - - /// @notice Builds the deployment transactions for the FeesDepositor implementation and proxy. - /// @dev This function deploys both the implementation contract and the proxy contract using CREATE2, - /// then initializes the proxy with the implementation. The calculated addresses are validated - /// implicitly because if the calculated address of the Proxy would differ from the one we - /// calculated, the task would fail on the check for code to be present, since the changes - /// in build function revert and the parent contract validates that accessed accounts have code. - function _build(address) internal override { - // Deploy the FeesDepositor implementation contract using CREATE2 - ICreate2Deployer(CREATE2_DEPLOYER).deploy(0, bytes32(bytes(salt)), RevShareCodeRepo.feesDepositorCreationCode); - - // Deploy the proxy contract using CREATE2 with the calculated initialization code - ICreate2Deployer(CREATE2_DEPLOYER).deploy(0, bytes32(bytes(salt)), _proxyInitCode); - - // Initialize the proxy by upgrading to the implementation and calling initialize via ProxyAdmin - IProxyAdmin(proxyAdmin).upgradeAndCall( - payable(_proxyCalculatedAddress), - _implCalculatedAddress, - abi.encodeCall(IFeesDepositor.initialize, (minDepositAmount, l2Recipient, portal, gasLimit)) - ); - } - - /// @notice This method performs all validations and assertions that verify the calls executed as expected. - function _validate(VmSafe.AccountAccess[] memory, Action[] memory, address) internal view override { - require( - IFeesDepositor(payable(_proxyCalculatedAddress)).minDepositAmount() == minDepositAmount, - "minDepositAmount mismatch" - ); - require(IFeesDepositor(payable(_proxyCalculatedAddress)).l2Recipient() == l2Recipient, "l2Recipient mismatch"); - require(IFeesDepositor(payable(_proxyCalculatedAddress)).gasLimit() == gasLimit, "gasLimit mismatch"); - } - - /// @notice Override to return a list of addresses that should not be checked for code length. - function _getCodeExceptions() internal view virtual override returns (address[] memory) { - address[] memory codeExceptions = new address[](1); - codeExceptions[0] = _proxyCalculatedAddress; - return codeExceptions; - } -} diff --git a/test/integration/RevShareContractsUpgraderIntegration.t.sol b/test/integration/RevShareContractsUpgraderIntegration.t.sol index 939c100c12..f12712d706 100644 --- a/test/integration/RevShareContractsUpgraderIntegration.t.sol +++ b/test/integration/RevShareContractsUpgraderIntegration.t.sol @@ -82,7 +82,7 @@ contract RevShareContractsUpgraderIntegrationTest is IntegrationBase { vm.recordLogs(); // Step 2: Execute task simulation - revShareTask.simulate("test/tasks/example/eth/018-revshare-upgrade-and-setup/config.toml"); + revShareTask.simulate("test/tasks/example/eth/016-revshare-upgrade-and-setup/config.toml"); // Step 3: Relay deposit transactions from L1 to all L2s uint256[] memory forkIds = new uint256[](2); diff --git a/test/tasks/Regression.t.sol b/test/tasks/Regression.t.sol index c27acf80c1..293da94ce4 100644 --- a/test/tasks/Regression.t.sol +++ b/test/tasks/Regression.t.sol @@ -39,9 +39,6 @@ import {BlacklistGamesV400} from "src/template/BlacklistGamesV400.sol"; import {OPCMUpgradeV220toV410} from "src/template/OPCMUpgradeV220toV410.sol"; import {OPCMUpgradeV410} from "src/template/OPCMUpgradeV410.sol"; import {OPCMUpgradeSuperchainConfigV410} from "src/template/OPCMUpgradeSuperchainConfigV410.sol"; -import {RevenueShareV100UpgradePath} from "src/template/RevenueShareUpgradePath.sol"; -import {DeployFeesDepositor} from "src/template/DeployFeesDepositor.sol"; -import {RevShareUpgradeAndSetup} from "src/template/RevShareUpgradeAndSetup.sol"; import {L1PortalExecuteL2Call} from "src/template/L1PortalExecuteL2Call.sol"; import {AddGameTypeTemplate} from "src/template/AddGameTypeTemplate.sol"; @@ -924,85 +921,6 @@ contract RegressionTest is Test { _assertDataToSignNestedMultisig(multisigTask, actions, expectedDataToSign, MULTICALL3_ADDRESS, rootSafe); } - /// @notice Expected call data and data to sign generated by manually running the RevenueShareV100UpgradePath template at block 23434662 on mainnet. - /// Simulate from task directory (test/tasks/example/eth/015-revenue-share-upgrade/config.toml) with: - /// just --dotenv-path $(pwd)/.env --justfile ../../../../../src/improvements/justfile simulate (foundation|council) - function testRegressionCallDataMatches_RevenueShareV100UpgradePath() public { - string memory taskConfigFilePath = "test/tasks/example/eth/015-revenue-share-upgrade/config.toml"; - string memory expectedCallData = - "0x174dea710000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000d2000000000000000000000000000000000000000000000000000000000000018e00000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000000000000000003140000000000000000000000000000000000000000000000000000000000000430000000000000000000000000000000000000000000000000000000000000045a000000000000000000000000000000000000000000000000000000000000057600000000000000000000000000000000000000000000000000000000000005a000000000000000000000000000000000000000000000000000000000000006bc00000000000000000000000000000000000000000000000000000000000006e600000000000000000000000000000000000000000000000000000000000008020000000000000000000000000beb5fc579115071764c7423a4f12edde41f106ed0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000ae4e9e05c4200000000000000000000000013b0d85ccb8bf860b6b79af3029fca081ae9bef2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0498000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000a0466cfa0570000000000000000000000000000000000000000000000000000000000000000fa8e542d08c461382d17d78973c846bafcf01f0c60f78f77abd977884fd393ff000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000009686080604052348015600e575f80fd5b50604051610908380380610908833981016040819052602b916067565b5f929092556001805463ffffffff909316600160a01b026001600160c01b03199093166001600160a01b039092169190911791909117905560b8565b5f805f606084860312156078575f80fd5b835160208501519093506001600160a01b03811681146095575f80fd5b604085015190925063ffffffff8116811460ad575f80fd5b809150509250925092565b610843806100c55f395ff3fe608060405260043610610071575f3560e01c806366d003ac1161004c57806366d003ac146102995780638312f149146102ea57806385b5b14d1461030c5780639d7955b41461032b575f80fd5b80633bbed4a0146101d7578063500bf72f146101f657806354fd4d5014610244575f80fd5b366101d3576040805134815247602082018190529133917f363f315f930a17d1266b86a20d6dd34b1cfbc5a9db9f13a65d06a689c3a2af8a910160405180910390a25f5481106101d1576001546040517f3dbb202b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152606060248201525f60648201527401000000000000000000000000000000000000000090910463ffffffff16604482015273420000000000000000000000000000000000000790633dbb202b9083906084015f604051808303818588803b158015610169575f80fd5b505af115801561017b573d5f803e3d5ffd5b505060015460405185815273ffffffffffffffffffffffffffffffffffffffff90911693507f6d92f7d3303f995bf21956bb0c51b388bae348eaf45c23debd2cfa3fcd9ec6469250602001905060405180910390a25b005b5f80fd5b3480156101e2575f80fd5b506101d16101f136600461076c565b61034a565b348015610201575f80fd5b5060015461022a9074010000000000000000000000000000000000000000900463ffffffff1681565b60405163ffffffff90911681526020015b60405180910390f35b34801561024f575f80fd5b5061028c6040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b60405161023b919061078e565b3480156102a4575f80fd5b506001546102c59073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161023b565b3480156102f5575f80fd5b506102fe5f5481565b60405190815260200161023b565b348015610317575f80fd5b506101d16103263660046107e1565b6104b6565b348015610336575f80fd5b506101d16103453660046107f8565b6105d8565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103a7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103cb919061081b565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461042f576040517f807b982000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f62e69886a5df0ba8ffcacbfc1388754e7abd9bde24b036354c561f1acd4e459391015b60405180910390a15050565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610513573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610537919061081b565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461059b576040517f807b982000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80549082905560408051828152602081018490527f895a067c78583e800418fabf3da26a9496aab2ff3429cebdf7fefa642b2e420391016104aa565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610635573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610659919061081b565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106bd576040517f807b982000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001805463ffffffff838116740100000000000000000000000000000000000000008181027fffffffffffffffff00000000ffffffffffffffffffffffffffffffffffffffff85161790945560408051949093049091168084526020840191909152917fd00b9b2acb0059a20066ca19b541618141c03305a0a6644d43277758c539b5de91016104aa565b73ffffffffffffffffffffffffffffffffffffffff81168114610769575f80fd5b50565b5f6020828403121561077c575f80fd5b813561078781610748565b9392505050565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b5f602082840312156107f1575f80fd5b5035919050565b5f60208284031215610808575f80fd5b813563ffffffff81168114610787575f80fd5b5f6020828403121561082b575f80fd5b81516107878161074856fea164736f6c6343000819000a0000000000000000000000000000000000000000000000000000000000055730000000000000000000000000742d35cc6634c0532925a3b8d0c0c8b8b0c0c8b800000000000000000000000000000000000000000000000000000000000c35000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000beb5fc579115071764c7423a4f12edde41f106ed0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000b04e9e05c4200000000000000000000000013b0d85ccb8bf860b6b79af3029fca081ae9bef2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a6802000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000a2466cfa0570000000000000000000000000000000000000000000000000000000000000000d07fd81b3e1bcfbf3c91e5b2f6b54443cff180a787261d425462132920599561000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000009956080604052348015600e575f80fd5b50604051610955380380610955833981016040819052602b916074565b5f80546001600160a01b039384166001600160a01b0319918216179091556001805492909316911617905560a0565b80516001600160a01b0381168114606f575f80fd5b919050565b5f80604083850312156084575f80fd5b608b83605a565b9150609760208401605a565b90509250929050565b6108a8806100ad5f395ff3fe608060405234801561000f575f80fd5b506004361061009f575f3560e01c80635b201d83116100725780637b42d6c2116100585780637b42d6c21461019157806396d842be1461019a5780639c662fdd146101b9575f80fd5b80635b201d831461016b578063712d7bb814610189575f80fd5b806329f33ec8146100a35780634b012e9a146100ed57806354e7f42d1461010257806354fd4d5014610122575b5f80fd5b6001546100c39073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6101006100fb3660046106a3565b6101cc565b005b6101156101103660046106c5565b610325565b6040516100e491906106f4565b61015e6040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516100e49190610758565b61017461271081565b60405163ffffffff90911681526020016100e4565b61017460fa81565b6101746105dc81565b5f546100c39073ffffffffffffffffffffffffffffffffffffffff1681565b6101006101c73660046106a3565b610524565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610229573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061024d91906107ab565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146102b1576040517f67102c4c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917fc7b7459ad1ab31862524bf0c4a5e6a8518c60f27607a5c483a58ea27e30c214c9190a35050565b6040805160028082526060828101909352816020015b604080518082019091525f808252602082015281526020019060019003908161033b575050604080518082019091525f805473ffffffffffffffffffffffffffffffffffffffff16825260208201819052825192935090918391906103a2576103a26107c6565b6020026020010181905250604051806040016040528060015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020015f8152508160018151811061040c5761040c6107c6565b60209081029190910101525f82846104248789610820565b61042e9190610820565b6104389190610820565b90505f61271061044960fa84610839565b6104539190610850565b9050805f0361048e576040517f0174e42600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6104998584610888565b90505f6127106104ab6105dc84610839565b6104b59190610850565b90505f8184116104c557816104c7565b835b905080865f815181106104dc576104dc6107c6565b60209081029190910181015101526104f48186610888565b86600181518110610507576105076107c6565b602002602001015160200181815250505050505050949350505050565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610581573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105a591906107ab565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610609576040517f67102c4c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f28c1e0a919cd3b91d6d516417dedc06a2bd7954ad8960315347250b1aee2a4f1905f90a35050565b73ffffffffffffffffffffffffffffffffffffffff811681146106a0575f80fd5b50565b5f602082840312156106b3575f80fd5b81356106be8161067f565b9392505050565b5f805f80608085870312156106d8575f80fd5b5050823594602084013594506040840135936060013592509050565b602080825282518282018190525f919060409081850190868401855b8281101561074b578151805173ffffffffffffffffffffffffffffffffffffffff168552860151868501529284019290850190600101610710565b5091979650505050505050565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b5f602082840312156107bb575f80fd5b81516106be8161067f565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b80820180821115610833576108336107f3565b92915050565b8082028115828204841417610833576108336107f3565b5f82610883577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b81810381811115610833576108336107f356fea164736f6c6343000819000a000000000000000000000000524e512dd372c70e7866a7825481385b7b533af00000000000000000000000008b0c0c8b8b0c0c8b8b0c0c8b8b0c0c8b8b0c0c8b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000beb5fc579115071764c7423a4f12edde41f106ed0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000001544e9e05c4200000000000000000000000013b0d85ccb8bf860b6b79af3029fca081ae9bef200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000142316000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000146466cfa0570000000000000000000000000000000000000000000000000000000000000000d7c04619bfc311a92d20723f9d08baaba18c3c8c7dcd85736bf66b85f59c37f6000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000013d26080604052348015600e575f80fd5b5060156019565b60d4565b5f54610100900460ff161560835760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b5f5460ff908116101560d2575f805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b6112f1806100e15f395ff3fe608060405260043610610096575f3560e01c80637dfbd04911610066578063b87ea8d41161004c578063b87ea8d414610313578063c4d66de814610327578063d61a398b14610346575f80fd5b80637dfbd049146102dd5780637fc81bb7146102f4575f80fd5b80630a7617b3146101dd5780630c0544a3146101fe578063394d27311461026057806354fd4d5014610288575f80fd5b366101d9577fe3007e9730850b5618eacb0537bef0cf0f1600267ae8549e472449d77b731e455c6100f3576040517f17617f6100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b337342000000000000000000000000000000000000111480159061012b57503373420000000000000000000000000000000000001914155b801561014b57503373420000000000000000000000000000000000001a14155b801561016b57503373420000000000000000000000000000000000001b14155b156101a2576040517f9dcde10900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405134815233907f2ccfc58c2cef4ee590b5f16be0548cc54afc12e1c66a67b362b7d640fd16bb2d9060200160405180910390a2005b5f80fd5b3480156101e8575f80fd5b506101fc6101f7366004610f4b565b61039c565b005b348015610209575f80fd5b5060015461023a9070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1681565b6040516fffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561026b575f80fd5b5060015461023a906fffffffffffffffffffffffffffffffff1681565b348015610293575f80fd5b506102d06040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516102579190610f66565b3480156102e8575f80fd5b5061023a6301e1338081565b3480156102ff575f80fd5b506101fc61030e366004610fb9565b61055e565b34801561031e575f80fd5b506101fc610706565b348015610332575f80fd5b506101fc610341366004610f4b565b610aea565b348015610351575f80fd5b505f546103779062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610257565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103f9573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061041d9190610fe8565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610481576040517f38bac74200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166104ce576040517f99c6ec0800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f805473ffffffffffffffffffffffffffffffffffffffff838116620100008181027fffffffffffffffffffff0000000000000000000000000000000000000000ffff85161790945560408051949093049091168084526020840191909152917f16417cc372deec0caee5f52e2ad77a5f07b4591fd56b4ff31b6e20f817d4daeb91015b60405180910390a15050565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105bb573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105df9190610fe8565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610643576040517f38bac74200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6301e133806fffffffffffffffffffffffffffffffff82161115610693576040517f30b9f35e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180546fffffffffffffffffffffffffffffffff8381167001000000000000000000000000000000008181028385161790945560408051949093049091168084526020840191909152917f4492086b630ed3846eec0979dd87a71c814ceb1c6dab80ab81e3450b21e4de289101610552565b60015461073b906fffffffffffffffffffffffffffffffff700100000000000000000000000000000000820481169116611030565b6fffffffffffffffffffffffffffffffff16421015610786576040517f1e4a9f3a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffffffffffff0000000000000000000000000000000016426fffffffffffffffffffffffffffffffff161781556107cb90610ce0565b5f6107e9734200000000000000000000000000000000000011610d06565b90505f610809734200000000000000000000000000000000000019610d06565b90505f61082973420000000000000000000000000000000000001a610d06565b90505f61084973420000000000000000000000000000000000001b610d06565b90506108545f610ce0565b5f82826108618688611060565b61086b9190611060565b6108759190611060565b9050805f036108b0576040517fc8972e5200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80546040517f54e7f42d000000000000000000000000000000000000000000000000000000008152600481018890526024810187905260448101859052606481018690526201000090910473ffffffffffffffffffffffffffffffffffffffff16906354e7f42d906084015f60405180830381865afa158015610936573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261097b9190810190611118565b905080515f036109b7576040517f763970d600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f805b8251811015610a6e575f8382815181106109d6576109d66111e7565b60200260200101515f015190505f8483815181106109f6576109f66111e7565b6020026020010151602001519050805f03610a12575050610a66565b5f610a1d8383610f03565b905080610a56576040517fd68d1b1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a608286611060565b94505050505b6001016109ba565b50828114610aa8576040517f9c01eac000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f73f9a13241a1848ec157967f3a85601709353e616f1f2605d818c0f2d21774df8284604051610ad9929190611214565b60405180910390a150505050505050565b5f54610100900460ff1615808015610b0857505f54600160ff909116105b80610b215750303b158015610b2157505f5460ff166001145b610bb1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840160405180910390fd5b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610c0d575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b5f80547fffffffffffffffffffff0000000000000000000000000000000000000000ffff166201000073ffffffffffffffffffffffffffffffffffffffff851602179055600180546fffffffffffffffffffffffffffffffff1672015180000000000000000000000000000000001790558015610cdc575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249890602001610552565b5050565b807fe3007e9730850b5618eacb0537bef0cf0f1600267ae8549e472449d77b731e455d50565b5f60018273ffffffffffffffffffffffffffffffffffffffff166382356d8a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d52573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d7691906112af565b6001811115610d8757610d87611282565b14610dbe576040517fb4726cbe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff166366d003ac6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e1e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e429190610fe8565b73ffffffffffffffffffffffffffffffffffffffff1614610e8f576040517fc3380cef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff16633ccfd60b6040518163ffffffff1660e01b81526004016020604051808303815f875af1158015610ed9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610efd91906112cd565b92915050565b5f610f0f835a84610f16565b9392505050565b5f805f805f858888f1949350505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f48575f80fd5b50565b5f60208284031215610f5b575f80fd5b8135610f0f81610f27565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b5f60208284031215610fc9575f80fd5b81356fffffffffffffffffffffffffffffffff81168114610f0f575f80fd5b5f60208284031215610ff8575f80fd5b8151610f0f81610f27565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b6fffffffffffffffffffffffffffffffff81811683821601908082111561105957611059611003565b5092915050565b80820180821115610efd57610efd611003565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6040805190810167ffffffffffffffff811182821017156110c3576110c3611073565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561111057611110611073565b604052919050565b5f6020808385031215611129575f80fd5b825167ffffffffffffffff80821115611140575f80fd5b818501915085601f830112611153575f80fd5b81518181111561116557611165611073565b611173848260051b016110c9565b818152848101925060069190911b830184019087821115611192575f80fd5b928401925b818410156111dc57604084890312156111ae575f80fd5b6111b66110a0565b84516111c181610f27565b81528486015186820152835260409093019291840191611197565b979650505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b604080825283518282018190525f91906020906060850190828801855b8281101561126c578151805173ffffffffffffffffffffffffffffffffffffffff168552850151858501529285019290840190600101611231565b5050508093505050508260208301529392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b5f602082840312156112bf575f80fd5b815160028110610f0f575f80fd5b5f602082840312156112dd575f80fd5b505191905056fea164736f6c6343000819000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000beb5fc579115071764c7423a4f12edde41f106ed00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001a4e9e05c420000000000000000000000004200000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000249f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c49623609d000000000000000000000000420000000000000000000000000000000000002b0000000000000000000000006b0d0b5d65c13ed9ec80617772aee4d6c594a66e00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000024c4d66de800000000000000000000000072aa66caa04c9bd83ecc43c65cff2cf837ee4bb3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000beb5fc579115071764c7423a4f12edde41f106ed0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000001104e9e05c4200000000000000000000000013b0d85ccb8bf860b6b79af3029fca081ae9bef200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000124f80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000102466cfa0570000000000000000000000000000000000000000000000000000000000000000783aa8b3e401c8404e3eff9401ba29702719ddc0c0f69ec9ac77188bacea107300000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000f8f6080604052348015600e575f80fd5b5060156019565b60c9565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff161560685760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b039081161460c65780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b610eb9806100d65f395ff3fe6080604052600436106100d1575f3560e01c806382356d8a1161007c57806385b5b14d1161005757806385b5b14d14610276578063b49dc74114610295578063d0e12f90146102b4578063d3e5792b146102e3575f80fd5b806382356d8a1461020f5780638312f1491461024d57806384411d6514610262575f80fd5b80633ccfd60b116100ac5780633ccfd60b1461016c57806354fd4d501461018e57806366d003ac146101e3575f80fd5b80630d9019e1146100dc578063307f29621461012c5780633bbed4a01461014d575f80fd5b366100d857005b5f80fd5b3480156100e7575f80fd5b5060025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b348015610137575f80fd5b5061014b610146366004610c86565b6102f7565b005b348015610158575f80fd5b5061014b610167366004610cc3565b61047a565b348015610177575f80fd5b506101806105de565b604051908152602001610123565b348015610199575f80fd5b506101d66040518060400160405280600581526020017f312e312e3000000000000000000000000000000000000000000000000000000081525081565b6040516101239190610cde565b3480156101ee575f80fd5b506002546101029073ffffffffffffffffffffffffffffffffffffffff1681565b34801561021a575f80fd5b506002546102409074010000000000000000000000000000000000000000900460ff1681565b6040516101239190610d97565b348015610258575f80fd5b5061018060015481565b34801561026d575f80fd5b506101805f5481565b348015610281575f80fd5b5061014b610290366004610dab565b610918565b3480156102a0575f80fd5b5061014b6102af366004610dc2565b610a3b565b3480156102bf575f80fd5b5060025474010000000000000000000000000000000000000000900460ff16610240565b3480156102ee575f80fd5b50600154610180565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610354573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103789190610dfd565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146103dc576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547401000000000000000000000000000000000000000080820460ff1692849290917fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff9091169083600181111561043857610438610d31565b02179055507ff2ec44eb1c3b3acd547b76333eb2c4b27eee311860c57a9fdb04c95f62398fc8818360405161046e929190610e18565b60405180910390a15050565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104fb9190610dfd565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461055f576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f62e69886a5df0ba8ffcacbfc1388754e7abd9bde24b036354c561f1acd4e4593910161046e565b5f60015447101561069c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f4665655661756c743a207769746864726177616c20616d6f756e74206d75737460448201527f2062652067726561746572207468616e206d696e696d756d207769746864726160648201527f77616c20616d6f756e7400000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b479050805f808282546106af9190610e33565b90915550506002546040805183815273ffffffffffffffffffffffffffffffffffffffff90921660208301523382820152517fc8a211cc64b6ed1b50595a9fcb1932b6d1e5a6e8ef15b60e5b1f988ea9086bba9181900360600190a16002546040517f38e04cbeb8c10f8f568618aa75be0f10b6729b8b4237743b4de20cbcde2839ee9161077491849173ffffffffffffffffffffffffffffffffffffffff811691339174010000000000000000000000000000000000000000900460ff1690610e6b565b60405180910390a1600160025474010000000000000000000000000000000000000000900460ff1660018111156107ad576107ad610d31565b0361086a576002545f906107d79073ffffffffffffffffffffffffffffffffffffffff1683610c4f565b905080610866576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4665655661756c743a206661696c656420746f2073656e642045544820746f2060448201527f4c322066656520726563697069656e74000000000000000000000000000000006064820152608401610693565b5090565b6002546040517fc2b3e5ac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015262061a806024820152606060448201525f60648201527342000000000000000000000000000000000000169063c2b3e5ac9083906084015f604051808303818588803b1580156108fe575f80fd5b505af1158015610910573d5f803e3d5ffd5b505050505090565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610975573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109999190610dfd565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109fd576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180549082905560408051828152602081018490527f895a067c78583e800418fabf3da26a9496aab2ff3429cebdf7fefa642b2e4203910161046e565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f81158015610a855750825b90505f8267ffffffffffffffff166001148015610aa15750303b155b905081158015610aaf575080155b15610ae6576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001660011785558315610b475784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b6002805473ffffffffffffffffffffffffffffffffffffffff8a167fffffffffffffffffffffffff000000000000000000000000000000000000000082168117835560018a81558993927fffffffffffffffffffffff000000000000000000000000000000000000000000169091179074010000000000000000000000000000000000000000908490811115610bdf57610bdf610d31565b02179055508315610c455784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050565b5f610c5b835a84610c62565b9392505050565b5f805f805f858888f1949350505050565b803560028110610c81575f80fd5b919050565b5f60208284031215610c96575f80fd5b610c5b82610c73565b73ffffffffffffffffffffffffffffffffffffffff81168114610cc0575f80fd5b50565b5f60208284031215610cd3575f80fd5b8135610c5b81610c9f565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60028110610d93577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b9052565b60208101610da58284610d5e565b92915050565b5f60208284031215610dbb575f80fd5b5035919050565b5f805f60608486031215610dd4575f80fd5b8335610ddf81610c9f565b925060208401359150610df460408501610c73565b90509250925092565b5f60208284031215610e0d575f80fd5b8151610c5b81610c9f565b60408101610e268285610d5e565b610c5b6020830184610d5e565b80820180821115610da5577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b84815273ffffffffffffffffffffffffffffffffffffffff84811660208301528316604082015260808101610ea36060830184610d5e565b9594505050505056fea164736f6c6343000819000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000beb5fc579115071764c7423a4f12edde41f106ed00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001e4e9e05c420000000000000000000000004200000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000249f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001049623609d000000000000000000000000420000000000000000000000000000000000001b000000000000000000000000bb8accad49adb30084bdf22d01a109883fd13dce00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064b49dc741000000000000000000000000420000000000000000000000000000000000002b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000beb5fc579115071764c7423a4f12edde41f106ed0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000001104e9e05c4200000000000000000000000013b0d85ccb8bf860b6b79af3029fca081ae9bef200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000124f80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000102466cfa0570000000000000000000000000000000000000000000000000000000000000000204cb368f75f2d6cade61b62cb318bffd2bd31a57a3f86dff75f5bfd9d2dd14900000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000f9a6080604052348015600e575f80fd5b5060156019565b60c9565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff161560685760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b039081161460c65780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b610ec4806100d65f395ff3fe6080604052600436106100dc575f3560e01c80638312f1491161007c578063b49dc74111610057578063b49dc741146102a0578063d0e12f90146102bf578063d3e5792b146102ee578063d4ff9218146100e7575f80fd5b80638312f1491461025857806384411d651461026d57806385b5b14d14610281575f80fd5b80633ccfd60b116100b75780633ccfd60b1461017757806354fd4d501461019957806366d003ac146101ee57806382356d8a1461021a575f80fd5b80630d9019e1146100e7578063307f2962146101375780633bbed4a014610158575f80fd5b366100e357005b5f80fd5b3480156100f2575f80fd5b5060025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b348015610142575f80fd5b50610156610151366004610c91565b610302565b005b348015610163575f80fd5b50610156610172366004610cce565b610485565b348015610182575f80fd5b5061018b6105e9565b60405190815260200161012e565b3480156101a4575f80fd5b506101e16040518060400160405280600581526020017f312e362e3000000000000000000000000000000000000000000000000000000081525081565b60405161012e9190610ce9565b3480156101f9575f80fd5b5060025461010d9073ffffffffffffffffffffffffffffffffffffffff1681565b348015610225575f80fd5b5060025461024b9074010000000000000000000000000000000000000000900460ff1681565b60405161012e9190610da2565b348015610263575f80fd5b5061018b60015481565b348015610278575f80fd5b5061018b5f5481565b34801561028c575f80fd5b5061015661029b366004610db6565b610923565b3480156102ab575f80fd5b506101566102ba366004610dcd565b610a46565b3480156102ca575f80fd5b5060025474010000000000000000000000000000000000000000900460ff1661024b565b3480156102f9575f80fd5b5060015461018b565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561035f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103839190610e08565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146103e7576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547401000000000000000000000000000000000000000080820460ff1692849290917fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff9091169083600181111561044357610443610d3c565b02179055507ff2ec44eb1c3b3acd547b76333eb2c4b27eee311860c57a9fdb04c95f62398fc88183604051610479929190610e23565b60405180910390a15050565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104e2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105069190610e08565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461056a576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f62e69886a5df0ba8ffcacbfc1388754e7abd9bde24b036354c561f1acd4e45939101610479565b5f6001544710156106a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f4665655661756c743a207769746864726177616c20616d6f756e74206d75737460448201527f2062652067726561746572207468616e206d696e696d756d207769746864726160648201527f77616c20616d6f756e7400000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b479050805f808282546106ba9190610e3e565b90915550506002546040805183815273ffffffffffffffffffffffffffffffffffffffff90921660208301523382820152517fc8a211cc64b6ed1b50595a9fcb1932b6d1e5a6e8ef15b60e5b1f988ea9086bba9181900360600190a16002546040517f38e04cbeb8c10f8f568618aa75be0f10b6729b8b4237743b4de20cbcde2839ee9161077f91849173ffffffffffffffffffffffffffffffffffffffff811691339174010000000000000000000000000000000000000000900460ff1690610e76565b60405180910390a1600160025474010000000000000000000000000000000000000000900460ff1660018111156107b8576107b8610d3c565b03610875576002545f906107e29073ffffffffffffffffffffffffffffffffffffffff1683610c5a565b905080610871576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4665655661756c743a206661696c656420746f2073656e642045544820746f2060448201527f4c322066656520726563697069656e7400000000000000000000000000000000606482015260840161069e565b5090565b6002546040517fc2b3e5ac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015262061a806024820152606060448201525f60648201527342000000000000000000000000000000000000169063c2b3e5ac9083906084015f604051808303818588803b158015610909575f80fd5b505af115801561091b573d5f803e3d5ffd5b505050505090565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610980573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109a49190610e08565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610a08576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180549082905560408051828152602081018490527f895a067c78583e800418fabf3da26a9496aab2ff3429cebdf7fefa642b2e42039101610479565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f81158015610a905750825b90505f8267ffffffffffffffff166001148015610aac5750303b155b905081158015610aba575080155b15610af1576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001660011785558315610b525784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b6002805473ffffffffffffffffffffffffffffffffffffffff8a167fffffffffffffffffffffffff000000000000000000000000000000000000000082168117835560018a81558993927fffffffffffffffffffffff000000000000000000000000000000000000000000169091179074010000000000000000000000000000000000000000908490811115610bea57610bea610d3c565b02179055508315610c505784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050565b5f610c66835a84610c6d565b9392505050565b5f805f805f858888f1949350505050565b803560028110610c8c575f80fd5b919050565b5f60208284031215610ca1575f80fd5b610c6682610c7e565b73ffffffffffffffffffffffffffffffffffffffff81168114610ccb575f80fd5b50565b5f60208284031215610cde575f80fd5b8135610c6681610caa565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60028110610d9e577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b9052565b60208101610db08284610d69565b92915050565b5f60208284031215610dc6575f80fd5b5035919050565b5f805f60608486031215610ddf575f80fd5b8335610dea81610caa565b925060208401359150610dff60408501610c7e565b90509250925092565b5f60208284031215610e18575f80fd5b8151610c6681610caa565b60408101610e318285610d69565b610c666020830184610d69565b80820180821115610db0577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b84815273ffffffffffffffffffffffffffffffffffffffff84811660208301528316604082015260808101610eae6060830184610d69565b9594505050505056fea164736f6c6343000819000a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000beb5fc579115071764c7423a4f12edde41f106ed00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001e4e9e05c420000000000000000000000004200000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000249f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001049623609d00000000000000000000000042000000000000000000000000000000000000110000000000000000000000006ca5002ca794cfeebc0ec0d04ef89a382bb3942500000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064b49dc741000000000000000000000000420000000000000000000000000000000000002b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000beb5fc579115071764c7423a4f12edde41f106ed0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000001104e9e05c4200000000000000000000000013b0d85ccb8bf860b6b79af3029fca081ae9bef200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000124f80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000102466cfa05700000000000000000000000000000000000000000000000000000000000000007a2bde9cfb7f80a4198677bdf885a43dc36c598688294f694cf64429164f140000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000f8f6080604052348015600e575f80fd5b5060156019565b60c9565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff161560685760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b039081161460c65780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b610eb9806100d65f395ff3fe6080604052600436106100d1575f3560e01c806382356d8a1161007c57806385b5b14d1161005757806385b5b14d14610276578063b49dc74114610295578063d0e12f90146102b4578063d3e5792b146102e3575f80fd5b806382356d8a1461020f5780638312f1491461024d57806384411d6514610262575f80fd5b80633ccfd60b116100ac5780633ccfd60b1461016c57806354fd4d501461018e57806366d003ac146101e3575f80fd5b80630d9019e1146100dc578063307f29621461012c5780633bbed4a01461014d575f80fd5b366100d857005b5f80fd5b3480156100e7575f80fd5b5060025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b348015610137575f80fd5b5061014b610146366004610c86565b6102f7565b005b348015610158575f80fd5b5061014b610167366004610cc3565b61047a565b348015610177575f80fd5b506101806105de565b604051908152602001610123565b348015610199575f80fd5b506101d66040518060400160405280600581526020017f312e362e3000000000000000000000000000000000000000000000000000000081525081565b6040516101239190610cde565b3480156101ee575f80fd5b506002546101029073ffffffffffffffffffffffffffffffffffffffff1681565b34801561021a575f80fd5b506002546102409074010000000000000000000000000000000000000000900460ff1681565b6040516101239190610d97565b348015610258575f80fd5b5061018060015481565b34801561026d575f80fd5b506101805f5481565b348015610281575f80fd5b5061014b610290366004610dab565b610918565b3480156102a0575f80fd5b5061014b6102af366004610dc2565b610a3b565b3480156102bf575f80fd5b5060025474010000000000000000000000000000000000000000900460ff16610240565b3480156102ee575f80fd5b50600154610180565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610354573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103789190610dfd565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146103dc576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547401000000000000000000000000000000000000000080820460ff1692849290917fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff9091169083600181111561043857610438610d31565b02179055507ff2ec44eb1c3b3acd547b76333eb2c4b27eee311860c57a9fdb04c95f62398fc8818360405161046e929190610e18565b60405180910390a15050565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104fb9190610dfd565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461055f576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f62e69886a5df0ba8ffcacbfc1388754e7abd9bde24b036354c561f1acd4e4593910161046e565b5f60015447101561069c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f4665655661756c743a207769746864726177616c20616d6f756e74206d75737460448201527f2062652067726561746572207468616e206d696e696d756d207769746864726160648201527f77616c20616d6f756e7400000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b479050805f808282546106af9190610e33565b90915550506002546040805183815273ffffffffffffffffffffffffffffffffffffffff90921660208301523382820152517fc8a211cc64b6ed1b50595a9fcb1932b6d1e5a6e8ef15b60e5b1f988ea9086bba9181900360600190a16002546040517f38e04cbeb8c10f8f568618aa75be0f10b6729b8b4237743b4de20cbcde2839ee9161077491849173ffffffffffffffffffffffffffffffffffffffff811691339174010000000000000000000000000000000000000000900460ff1690610e6b565b60405180910390a1600160025474010000000000000000000000000000000000000000900460ff1660018111156107ad576107ad610d31565b0361086a576002545f906107d79073ffffffffffffffffffffffffffffffffffffffff1683610c4f565b905080610866576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4665655661756c743a206661696c656420746f2073656e642045544820746f2060448201527f4c322066656520726563697069656e74000000000000000000000000000000006064820152608401610693565b5090565b6002546040517fc2b3e5ac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015262061a806024820152606060448201525f60648201527342000000000000000000000000000000000000169063c2b3e5ac9083906084015f604051808303818588803b1580156108fe575f80fd5b505af1158015610910573d5f803e3d5ffd5b505050505090565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610975573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109999190610dfd565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109fd576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180549082905560408051828152602081018490527f895a067c78583e800418fabf3da26a9496aab2ff3429cebdf7fefa642b2e4203910161046e565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f81158015610a855750825b90505f8267ffffffffffffffff166001148015610aa15750303b155b905081158015610aaf575080155b15610ae6576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001660011785558315610b475784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b6002805473ffffffffffffffffffffffffffffffffffffffff8a167fffffffffffffffffffffffff000000000000000000000000000000000000000082168117835560018a81558993927fffffffffffffffffffffff000000000000000000000000000000000000000000169091179074010000000000000000000000000000000000000000908490811115610bdf57610bdf610d31565b02179055508315610c455784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050565b5f610c5b835a84610c62565b9392505050565b5f805f805f858888f1949350505050565b803560028110610c81575f80fd5b919050565b5f60208284031215610c96575f80fd5b610c5b82610c73565b73ffffffffffffffffffffffffffffffffffffffff81168114610cc0575f80fd5b50565b5f60208284031215610cd3575f80fd5b8135610c5b81610c9f565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60028110610d93577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b9052565b60208101610da58284610d5e565b92915050565b5f60208284031215610dbb575f80fd5b5035919050565b5f805f60608486031215610dd4575f80fd5b8335610ddf81610c9f565b925060208401359150610df460408501610c73565b90509250925092565b5f60208284031215610e0d575f80fd5b8151610c5b81610c9f565b60408101610e268285610d5e565b610c5b6020830184610d5e565b80820180821115610da5577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b84815273ffffffffffffffffffffffffffffffffffffffff84811660208301528316604082015260808101610ea36060830184610d5e565b9594505050505056fea164736f6c6343000819000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000beb5fc579115071764c7423a4f12edde41f106ed00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001e4e9e05c420000000000000000000000004200000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000249f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001049623609d00000000000000000000000042000000000000000000000000000000000000190000000000000000000000003240dd3b3ba917563f63ea129cddff7fb696070500000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064b49dc741000000000000000000000000420000000000000000000000000000000000002b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000beb5fc579115071764c7423a4f12edde41f106ed0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000001104e9e05c4200000000000000000000000013b0d85ccb8bf860b6b79af3029fca081ae9bef200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000124f80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000102466cfa05700000000000000000000000000000000000000000000000000000000000000004ac8e160bee0acc95b22d1744fa9cc7068869945397f78a77ed68ef8ae1d87a900000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000f8f6080604052348015600e575f80fd5b5060156019565b60c9565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff161560685760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b039081161460c65780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b610eb9806100d65f395ff3fe6080604052600436106100d1575f3560e01c806382356d8a1161007c57806385b5b14d1161005757806385b5b14d14610276578063b49dc74114610295578063d0e12f90146102b4578063d3e5792b146102e3575f80fd5b806382356d8a1461020f5780638312f1491461024d57806384411d6514610262575f80fd5b80633ccfd60b116100ac5780633ccfd60b1461016c57806354fd4d501461018e57806366d003ac146101e3575f80fd5b80630d9019e1146100dc578063307f29621461012c5780633bbed4a01461014d575f80fd5b366100d857005b5f80fd5b3480156100e7575f80fd5b5060025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b348015610137575f80fd5b5061014b610146366004610c86565b6102f7565b005b348015610158575f80fd5b5061014b610167366004610cc3565b61047a565b348015610177575f80fd5b506101806105de565b604051908152602001610123565b348015610199575f80fd5b506101d66040518060400160405280600581526020017f312e362e3000000000000000000000000000000000000000000000000000000081525081565b6040516101239190610cde565b3480156101ee575f80fd5b506002546101029073ffffffffffffffffffffffffffffffffffffffff1681565b34801561021a575f80fd5b506002546102409074010000000000000000000000000000000000000000900460ff1681565b6040516101239190610d97565b348015610258575f80fd5b5061018060015481565b34801561026d575f80fd5b506101805f5481565b348015610281575f80fd5b5061014b610290366004610dab565b610918565b3480156102a0575f80fd5b5061014b6102af366004610dc2565b610a3b565b3480156102bf575f80fd5b5060025474010000000000000000000000000000000000000000900460ff16610240565b3480156102ee575f80fd5b50600154610180565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610354573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103789190610dfd565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146103dc576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547401000000000000000000000000000000000000000080820460ff1692849290917fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff9091169083600181111561043857610438610d31565b02179055507ff2ec44eb1c3b3acd547b76333eb2c4b27eee311860c57a9fdb04c95f62398fc8818360405161046e929190610e18565b60405180910390a15050565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104fb9190610dfd565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461055f576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f62e69886a5df0ba8ffcacbfc1388754e7abd9bde24b036354c561f1acd4e4593910161046e565b5f60015447101561069c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f4665655661756c743a207769746864726177616c20616d6f756e74206d75737460448201527f2062652067726561746572207468616e206d696e696d756d207769746864726160648201527f77616c20616d6f756e7400000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b479050805f808282546106af9190610e33565b90915550506002546040805183815273ffffffffffffffffffffffffffffffffffffffff90921660208301523382820152517fc8a211cc64b6ed1b50595a9fcb1932b6d1e5a6e8ef15b60e5b1f988ea9086bba9181900360600190a16002546040517f38e04cbeb8c10f8f568618aa75be0f10b6729b8b4237743b4de20cbcde2839ee9161077491849173ffffffffffffffffffffffffffffffffffffffff811691339174010000000000000000000000000000000000000000900460ff1690610e6b565b60405180910390a1600160025474010000000000000000000000000000000000000000900460ff1660018111156107ad576107ad610d31565b0361086a576002545f906107d79073ffffffffffffffffffffffffffffffffffffffff1683610c4f565b905080610866576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4665655661756c743a206661696c656420746f2073656e642045544820746f2060448201527f4c322066656520726563697069656e74000000000000000000000000000000006064820152608401610693565b5090565b6002546040517fc2b3e5ac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015262061a806024820152606060448201525f60648201527342000000000000000000000000000000000000169063c2b3e5ac9083906084015f604051808303818588803b1580156108fe575f80fd5b505af1158015610910573d5f803e3d5ffd5b505050505090565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610975573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109999190610dfd565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109fd576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180549082905560408051828152602081018490527f895a067c78583e800418fabf3da26a9496aab2ff3429cebdf7fefa642b2e4203910161046e565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f81158015610a855750825b90505f8267ffffffffffffffff166001148015610aa15750303b155b905081158015610aaf575080155b15610ae6576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001660011785558315610b475784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b6002805473ffffffffffffffffffffffffffffffffffffffff8a167fffffffffffffffffffffffff000000000000000000000000000000000000000082168117835560018a81558993927fffffffffffffffffffffff000000000000000000000000000000000000000000169091179074010000000000000000000000000000000000000000908490811115610bdf57610bdf610d31565b02179055508315610c455784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050565b5f610c5b835a84610c62565b9392505050565b5f805f805f858888f1949350505050565b803560028110610c81575f80fd5b919050565b5f60208284031215610c96575f80fd5b610c5b82610c73565b73ffffffffffffffffffffffffffffffffffffffff81168114610cc0575f80fd5b50565b5f60208284031215610cd3575f80fd5b8135610c5b81610c9f565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60028110610d93577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b9052565b60208101610da58284610d5e565b92915050565b5f60208284031215610dbb575f80fd5b5035919050565b5f805f60608486031215610dd4575f80fd5b8335610ddf81610c9f565b925060208401359150610df460408501610c73565b90509250925092565b5f60208284031215610e0d575f80fd5b8151610c5b81610c9f565b60408101610e268285610d5e565b610c5b6020830184610d5e565b80820180821115610da5577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b84815273ffffffffffffffffffffffffffffffffffffffff84811660208301528316604082015260808101610ea36060830184610d5e565b9594505050505056fea164736f6c6343000819000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000beb5fc579115071764c7423a4f12edde41f106ed00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001e4e9e05c420000000000000000000000004200000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000249f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001049623609d000000000000000000000000420000000000000000000000000000000000001a0000000000000000000000006b692240ef7a6b18aaf63a56a94d423c1b5cec0a00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064b49dc741000000000000000000000000420000000000000000000000000000000000002b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; - MultisigTask multisigTask = new RevenueShareV100UpgradePath(); - address rootSafe = address(0x5a0Aae59D09fccBdDb6C6CcEB07B7279367C3d2A); // L1PAO - address securityCouncilChildMultisig = address(0xc2819DC788505Aac350142A7A707BF9D03E3Bd03); - address[] memory allSafes = MultisigTaskTestHelper.getAllSafes(rootSafe, securityCouncilChildMultisig); - - (Action[] memory actions, uint256[] memory allOriginalNonces) = - _setupAndSimulate(taskConfigFilePath, 23434662, "mainnet", multisigTask, allSafes); - _assertCallDataMatches(multisigTask, actions, allSafes, allOriginalNonces, expectedCallData); - - string[] memory expectedDataToSign = new string[](2); - // Foundation - expectedDataToSign[0] = - "0x1901a4a9c312badf3fcaa05eafe5dc9bee8bd9316c78ee8b0bebe3115bb21b732672eaf1963e1b8fce113ea7218a1f023ca5475fb3f07f7f0cc8e31a8909ea48c2b5"; - // Security Council - expectedDataToSign[1] = - "0x1901df53d510b56e539b90b369ef08fce3631020fbf921e3136ea5f8747c20bce9676b689c001fc27e79bcb565c7c5c376c301fb5ec47176b205c5b216fa5da4193c"; - _assertDataToSignNestedMultisig(multisigTask, actions, expectedDataToSign, MULTICALL3_ADDRESS, rootSafe); - } - - - /// @notice Expected call data and data to sign generated by manually running the RevenueShareV100UpgradePath template at block 23434662 on mainnet. - /// Simulate from task directory (test/tasks/example/eth/017-revenue-share-upgrade-custom-calc/config.toml) with: - /// just --dotenv-path $(pwd)/.env --justfile ../../../../../src/improvements/justfile simulate (foundation|council) - function testRegressionCallDataMatches_RevenueShareV100UpgradePath_CustomCalculator() public { - string memory taskConfigFilePath = "test/tasks/example/eth/017-revenue-share-upgrade-custom-calc/config.toml"; - string memory expectedCallData = - "0x174dea710000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000174000000000000000000000000000000000000000000000000000000000000019a00000000000000000000000000000000000000000000000000000000000002b600000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000003fc00000000000000000000000000000000000000000000000000000000000004260000000000000000000000000000000000000000000000000000000000000542000000000000000000000000000000000000000000000000000000000000056c00000000000000000000000000000000000000000000000000000000000006880000000000000000000000000beb5fc579115071764c7423a4f12edde41f106ed0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000001544e9e05c4200000000000000000000000013b0d85ccb8bf860b6b79af3029fca081ae9bef200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000142316000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000146466cfa0570000000000000000000000000000000000000000000000000000000000000000d7c04619bfc311a92d20723f9d08baaba18c3c8c7dcd85736bf66b85f59c37f6000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000013d26080604052348015600e575f80fd5b5060156019565b60d4565b5f54610100900460ff161560835760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b5f5460ff908116101560d2575f805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b6112f1806100e15f395ff3fe608060405260043610610096575f3560e01c80637dfbd04911610066578063b87ea8d41161004c578063b87ea8d414610313578063c4d66de814610327578063d61a398b14610346575f80fd5b80637dfbd049146102dd5780637fc81bb7146102f4575f80fd5b80630a7617b3146101dd5780630c0544a3146101fe578063394d27311461026057806354fd4d5014610288575f80fd5b366101d9577fe3007e9730850b5618eacb0537bef0cf0f1600267ae8549e472449d77b731e455c6100f3576040517f17617f6100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b337342000000000000000000000000000000000000111480159061012b57503373420000000000000000000000000000000000001914155b801561014b57503373420000000000000000000000000000000000001a14155b801561016b57503373420000000000000000000000000000000000001b14155b156101a2576040517f9dcde10900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405134815233907f2ccfc58c2cef4ee590b5f16be0548cc54afc12e1c66a67b362b7d640fd16bb2d9060200160405180910390a2005b5f80fd5b3480156101e8575f80fd5b506101fc6101f7366004610f4b565b61039c565b005b348015610209575f80fd5b5060015461023a9070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1681565b6040516fffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561026b575f80fd5b5060015461023a906fffffffffffffffffffffffffffffffff1681565b348015610293575f80fd5b506102d06040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516102579190610f66565b3480156102e8575f80fd5b5061023a6301e1338081565b3480156102ff575f80fd5b506101fc61030e366004610fb9565b61055e565b34801561031e575f80fd5b506101fc610706565b348015610332575f80fd5b506101fc610341366004610f4b565b610aea565b348015610351575f80fd5b505f546103779062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610257565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103f9573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061041d9190610fe8565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610481576040517f38bac74200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166104ce576040517f99c6ec0800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f805473ffffffffffffffffffffffffffffffffffffffff838116620100008181027fffffffffffffffffffff0000000000000000000000000000000000000000ffff85161790945560408051949093049091168084526020840191909152917f16417cc372deec0caee5f52e2ad77a5f07b4591fd56b4ff31b6e20f817d4daeb91015b60405180910390a15050565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105bb573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105df9190610fe8565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610643576040517f38bac74200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6301e133806fffffffffffffffffffffffffffffffff82161115610693576040517f30b9f35e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180546fffffffffffffffffffffffffffffffff8381167001000000000000000000000000000000008181028385161790945560408051949093049091168084526020840191909152917f4492086b630ed3846eec0979dd87a71c814ceb1c6dab80ab81e3450b21e4de289101610552565b60015461073b906fffffffffffffffffffffffffffffffff700100000000000000000000000000000000820481169116611030565b6fffffffffffffffffffffffffffffffff16421015610786576040517f1e4a9f3a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffffffffffff0000000000000000000000000000000016426fffffffffffffffffffffffffffffffff161781556107cb90610ce0565b5f6107e9734200000000000000000000000000000000000011610d06565b90505f610809734200000000000000000000000000000000000019610d06565b90505f61082973420000000000000000000000000000000000001a610d06565b90505f61084973420000000000000000000000000000000000001b610d06565b90506108545f610ce0565b5f82826108618688611060565b61086b9190611060565b6108759190611060565b9050805f036108b0576040517fc8972e5200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80546040517f54e7f42d000000000000000000000000000000000000000000000000000000008152600481018890526024810187905260448101859052606481018690526201000090910473ffffffffffffffffffffffffffffffffffffffff16906354e7f42d906084015f60405180830381865afa158015610936573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261097b9190810190611118565b905080515f036109b7576040517f763970d600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f805b8251811015610a6e575f8382815181106109d6576109d66111e7565b60200260200101515f015190505f8483815181106109f6576109f66111e7565b6020026020010151602001519050805f03610a12575050610a66565b5f610a1d8383610f03565b905080610a56576040517fd68d1b1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a608286611060565b94505050505b6001016109ba565b50828114610aa8576040517f9c01eac000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f73f9a13241a1848ec157967f3a85601709353e616f1f2605d818c0f2d21774df8284604051610ad9929190611214565b60405180910390a150505050505050565b5f54610100900460ff1615808015610b0857505f54600160ff909116105b80610b215750303b158015610b2157505f5460ff166001145b610bb1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840160405180910390fd5b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610c0d575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b5f80547fffffffffffffffffffff0000000000000000000000000000000000000000ffff166201000073ffffffffffffffffffffffffffffffffffffffff851602179055600180546fffffffffffffffffffffffffffffffff1672015180000000000000000000000000000000001790558015610cdc575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249890602001610552565b5050565b807fe3007e9730850b5618eacb0537bef0cf0f1600267ae8549e472449d77b731e455d50565b5f60018273ffffffffffffffffffffffffffffffffffffffff166382356d8a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d52573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d7691906112af565b6001811115610d8757610d87611282565b14610dbe576040517fb4726cbe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff166366d003ac6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e1e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e429190610fe8565b73ffffffffffffffffffffffffffffffffffffffff1614610e8f576040517fc3380cef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff16633ccfd60b6040518163ffffffff1660e01b81526004016020604051808303815f875af1158015610ed9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610efd91906112cd565b92915050565b5f610f0f835a84610f16565b9392505050565b5f805f805f858888f1949350505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f48575f80fd5b50565b5f60208284031215610f5b575f80fd5b8135610f0f81610f27565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b5f60208284031215610fc9575f80fd5b81356fffffffffffffffffffffffffffffffff81168114610f0f575f80fd5b5f60208284031215610ff8575f80fd5b8151610f0f81610f27565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b6fffffffffffffffffffffffffffffffff81811683821601908082111561105957611059611003565b5092915050565b80820180821115610efd57610efd611003565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6040805190810167ffffffffffffffff811182821017156110c3576110c3611073565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561111057611110611073565b604052919050565b5f6020808385031215611129575f80fd5b825167ffffffffffffffff80821115611140575f80fd5b818501915085601f830112611153575f80fd5b81518181111561116557611165611073565b611173848260051b016110c9565b818152848101925060069190911b830184019087821115611192575f80fd5b928401925b818410156111dc57604084890312156111ae575f80fd5b6111b66110a0565b84516111c181610f27565b81528486015186820152835260409093019291840191611197565b979650505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b604080825283518282018190525f91906020906060850190828801855b8281101561126c578151805173ffffffffffffffffffffffffffffffffffffffff168552850151858501529285019290840190600101611231565b5050508093505050508260208301529392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b5f602082840312156112bf575f80fd5b815160028110610f0f575f80fd5b5f602082840312156112dd575f80fd5b505191905056fea164736f6c6343000819000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000beb5fc579115071764c7423a4f12edde41f106ed00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001a4e9e05c420000000000000000000000004200000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000249f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c49623609d000000000000000000000000420000000000000000000000000000000000002b0000000000000000000000006b0d0b5d65c13ed9ec80617772aee4d6c594a66e00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000024c4d66de80000000000000000000000008b0c0c8b8b0c0c8b8b0c0c8b8b0c0c8b8b0c0c8b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000beb5fc579115071764c7423a4f12edde41f106ed0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000001104e9e05c4200000000000000000000000013b0d85ccb8bf860b6b79af3029fca081ae9bef200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000124f80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000102466cfa0570000000000000000000000000000000000000000000000000000000000000000783aa8b3e401c8404e3eff9401ba29702719ddc0c0f69ec9ac77188bacea107300000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000f8f6080604052348015600e575f80fd5b5060156019565b60c9565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff161560685760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b039081161460c65780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b610eb9806100d65f395ff3fe6080604052600436106100d1575f3560e01c806382356d8a1161007c57806385b5b14d1161005757806385b5b14d14610276578063b49dc74114610295578063d0e12f90146102b4578063d3e5792b146102e3575f80fd5b806382356d8a1461020f5780638312f1491461024d57806384411d6514610262575f80fd5b80633ccfd60b116100ac5780633ccfd60b1461016c57806354fd4d501461018e57806366d003ac146101e3575f80fd5b80630d9019e1146100dc578063307f29621461012c5780633bbed4a01461014d575f80fd5b366100d857005b5f80fd5b3480156100e7575f80fd5b5060025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b348015610137575f80fd5b5061014b610146366004610c86565b6102f7565b005b348015610158575f80fd5b5061014b610167366004610cc3565b61047a565b348015610177575f80fd5b506101806105de565b604051908152602001610123565b348015610199575f80fd5b506101d66040518060400160405280600581526020017f312e312e3000000000000000000000000000000000000000000000000000000081525081565b6040516101239190610cde565b3480156101ee575f80fd5b506002546101029073ffffffffffffffffffffffffffffffffffffffff1681565b34801561021a575f80fd5b506002546102409074010000000000000000000000000000000000000000900460ff1681565b6040516101239190610d97565b348015610258575f80fd5b5061018060015481565b34801561026d575f80fd5b506101805f5481565b348015610281575f80fd5b5061014b610290366004610dab565b610918565b3480156102a0575f80fd5b5061014b6102af366004610dc2565b610a3b565b3480156102bf575f80fd5b5060025474010000000000000000000000000000000000000000900460ff16610240565b3480156102ee575f80fd5b50600154610180565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610354573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103789190610dfd565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146103dc576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547401000000000000000000000000000000000000000080820460ff1692849290917fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff9091169083600181111561043857610438610d31565b02179055507ff2ec44eb1c3b3acd547b76333eb2c4b27eee311860c57a9fdb04c95f62398fc8818360405161046e929190610e18565b60405180910390a15050565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104fb9190610dfd565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461055f576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f62e69886a5df0ba8ffcacbfc1388754e7abd9bde24b036354c561f1acd4e4593910161046e565b5f60015447101561069c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f4665655661756c743a207769746864726177616c20616d6f756e74206d75737460448201527f2062652067726561746572207468616e206d696e696d756d207769746864726160648201527f77616c20616d6f756e7400000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b479050805f808282546106af9190610e33565b90915550506002546040805183815273ffffffffffffffffffffffffffffffffffffffff90921660208301523382820152517fc8a211cc64b6ed1b50595a9fcb1932b6d1e5a6e8ef15b60e5b1f988ea9086bba9181900360600190a16002546040517f38e04cbeb8c10f8f568618aa75be0f10b6729b8b4237743b4de20cbcde2839ee9161077491849173ffffffffffffffffffffffffffffffffffffffff811691339174010000000000000000000000000000000000000000900460ff1690610e6b565b60405180910390a1600160025474010000000000000000000000000000000000000000900460ff1660018111156107ad576107ad610d31565b0361086a576002545f906107d79073ffffffffffffffffffffffffffffffffffffffff1683610c4f565b905080610866576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4665655661756c743a206661696c656420746f2073656e642045544820746f2060448201527f4c322066656520726563697069656e74000000000000000000000000000000006064820152608401610693565b5090565b6002546040517fc2b3e5ac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015262061a806024820152606060448201525f60648201527342000000000000000000000000000000000000169063c2b3e5ac9083906084015f604051808303818588803b1580156108fe575f80fd5b505af1158015610910573d5f803e3d5ffd5b505050505090565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610975573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109999190610dfd565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109fd576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180549082905560408051828152602081018490527f895a067c78583e800418fabf3da26a9496aab2ff3429cebdf7fefa642b2e4203910161046e565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f81158015610a855750825b90505f8267ffffffffffffffff166001148015610aa15750303b155b905081158015610aaf575080155b15610ae6576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001660011785558315610b475784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b6002805473ffffffffffffffffffffffffffffffffffffffff8a167fffffffffffffffffffffffff000000000000000000000000000000000000000082168117835560018a81558993927fffffffffffffffffffffff000000000000000000000000000000000000000000169091179074010000000000000000000000000000000000000000908490811115610bdf57610bdf610d31565b02179055508315610c455784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050565b5f610c5b835a84610c62565b9392505050565b5f805f805f858888f1949350505050565b803560028110610c81575f80fd5b919050565b5f60208284031215610c96575f80fd5b610c5b82610c73565b73ffffffffffffffffffffffffffffffffffffffff81168114610cc0575f80fd5b50565b5f60208284031215610cd3575f80fd5b8135610c5b81610c9f565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60028110610d93577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b9052565b60208101610da58284610d5e565b92915050565b5f60208284031215610dbb575f80fd5b5035919050565b5f805f60608486031215610dd4575f80fd5b8335610ddf81610c9f565b925060208401359150610df460408501610c73565b90509250925092565b5f60208284031215610e0d575f80fd5b8151610c5b81610c9f565b60408101610e268285610d5e565b610c5b6020830184610d5e565b80820180821115610da5577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b84815273ffffffffffffffffffffffffffffffffffffffff84811660208301528316604082015260808101610ea36060830184610d5e565b9594505050505056fea164736f6c6343000819000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000beb5fc579115071764c7423a4f12edde41f106ed00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001e4e9e05c420000000000000000000000004200000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000249f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001049623609d000000000000000000000000420000000000000000000000000000000000001b000000000000000000000000bb8accad49adb30084bdf22d01a109883fd13dce00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064b49dc741000000000000000000000000420000000000000000000000000000000000002b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000beb5fc579115071764c7423a4f12edde41f106ed0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000001104e9e05c4200000000000000000000000013b0d85ccb8bf860b6b79af3029fca081ae9bef200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000124f80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000102466cfa0570000000000000000000000000000000000000000000000000000000000000000204cb368f75f2d6cade61b62cb318bffd2bd31a57a3f86dff75f5bfd9d2dd14900000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000f9a6080604052348015600e575f80fd5b5060156019565b60c9565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff161560685760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b039081161460c65780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b610ec4806100d65f395ff3fe6080604052600436106100dc575f3560e01c80638312f1491161007c578063b49dc74111610057578063b49dc741146102a0578063d0e12f90146102bf578063d3e5792b146102ee578063d4ff9218146100e7575f80fd5b80638312f1491461025857806384411d651461026d57806385b5b14d14610281575f80fd5b80633ccfd60b116100b75780633ccfd60b1461017757806354fd4d501461019957806366d003ac146101ee57806382356d8a1461021a575f80fd5b80630d9019e1146100e7578063307f2962146101375780633bbed4a014610158575f80fd5b366100e357005b5f80fd5b3480156100f2575f80fd5b5060025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b348015610142575f80fd5b50610156610151366004610c91565b610302565b005b348015610163575f80fd5b50610156610172366004610cce565b610485565b348015610182575f80fd5b5061018b6105e9565b60405190815260200161012e565b3480156101a4575f80fd5b506101e16040518060400160405280600581526020017f312e362e3000000000000000000000000000000000000000000000000000000081525081565b60405161012e9190610ce9565b3480156101f9575f80fd5b5060025461010d9073ffffffffffffffffffffffffffffffffffffffff1681565b348015610225575f80fd5b5060025461024b9074010000000000000000000000000000000000000000900460ff1681565b60405161012e9190610da2565b348015610263575f80fd5b5061018b60015481565b348015610278575f80fd5b5061018b5f5481565b34801561028c575f80fd5b5061015661029b366004610db6565b610923565b3480156102ab575f80fd5b506101566102ba366004610dcd565b610a46565b3480156102ca575f80fd5b5060025474010000000000000000000000000000000000000000900460ff1661024b565b3480156102f9575f80fd5b5060015461018b565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561035f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103839190610e08565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146103e7576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547401000000000000000000000000000000000000000080820460ff1692849290917fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff9091169083600181111561044357610443610d3c565b02179055507ff2ec44eb1c3b3acd547b76333eb2c4b27eee311860c57a9fdb04c95f62398fc88183604051610479929190610e23565b60405180910390a15050565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104e2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105069190610e08565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461056a576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f62e69886a5df0ba8ffcacbfc1388754e7abd9bde24b036354c561f1acd4e45939101610479565b5f6001544710156106a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f4665655661756c743a207769746864726177616c20616d6f756e74206d75737460448201527f2062652067726561746572207468616e206d696e696d756d207769746864726160648201527f77616c20616d6f756e7400000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b479050805f808282546106ba9190610e3e565b90915550506002546040805183815273ffffffffffffffffffffffffffffffffffffffff90921660208301523382820152517fc8a211cc64b6ed1b50595a9fcb1932b6d1e5a6e8ef15b60e5b1f988ea9086bba9181900360600190a16002546040517f38e04cbeb8c10f8f568618aa75be0f10b6729b8b4237743b4de20cbcde2839ee9161077f91849173ffffffffffffffffffffffffffffffffffffffff811691339174010000000000000000000000000000000000000000900460ff1690610e76565b60405180910390a1600160025474010000000000000000000000000000000000000000900460ff1660018111156107b8576107b8610d3c565b03610875576002545f906107e29073ffffffffffffffffffffffffffffffffffffffff1683610c5a565b905080610871576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4665655661756c743a206661696c656420746f2073656e642045544820746f2060448201527f4c322066656520726563697069656e7400000000000000000000000000000000606482015260840161069e565b5090565b6002546040517fc2b3e5ac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015262061a806024820152606060448201525f60648201527342000000000000000000000000000000000000169063c2b3e5ac9083906084015f604051808303818588803b158015610909575f80fd5b505af115801561091b573d5f803e3d5ffd5b505050505090565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610980573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109a49190610e08565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610a08576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180549082905560408051828152602081018490527f895a067c78583e800418fabf3da26a9496aab2ff3429cebdf7fefa642b2e42039101610479565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f81158015610a905750825b90505f8267ffffffffffffffff166001148015610aac5750303b155b905081158015610aba575080155b15610af1576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001660011785558315610b525784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b6002805473ffffffffffffffffffffffffffffffffffffffff8a167fffffffffffffffffffffffff000000000000000000000000000000000000000082168117835560018a81558993927fffffffffffffffffffffff000000000000000000000000000000000000000000169091179074010000000000000000000000000000000000000000908490811115610bea57610bea610d3c565b02179055508315610c505784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050565b5f610c66835a84610c6d565b9392505050565b5f805f805f858888f1949350505050565b803560028110610c8c575f80fd5b919050565b5f60208284031215610ca1575f80fd5b610c6682610c7e565b73ffffffffffffffffffffffffffffffffffffffff81168114610ccb575f80fd5b50565b5f60208284031215610cde575f80fd5b8135610c6681610caa565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60028110610d9e577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b9052565b60208101610db08284610d69565b92915050565b5f60208284031215610dc6575f80fd5b5035919050565b5f805f60608486031215610ddf575f80fd5b8335610dea81610caa565b925060208401359150610dff60408501610c7e565b90509250925092565b5f60208284031215610e18575f80fd5b8151610c6681610caa565b60408101610e318285610d69565b610c666020830184610d69565b80820180821115610db0577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b84815273ffffffffffffffffffffffffffffffffffffffff84811660208301528316604082015260808101610eae6060830184610d69565b9594505050505056fea164736f6c6343000819000a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000beb5fc579115071764c7423a4f12edde41f106ed00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001e4e9e05c420000000000000000000000004200000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000249f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001049623609d00000000000000000000000042000000000000000000000000000000000000110000000000000000000000006ca5002ca794cfeebc0ec0d04ef89a382bb3942500000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064b49dc741000000000000000000000000420000000000000000000000000000000000002b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000beb5fc579115071764c7423a4f12edde41f106ed0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000001104e9e05c4200000000000000000000000013b0d85ccb8bf860b6b79af3029fca081ae9bef200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000124f80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000102466cfa05700000000000000000000000000000000000000000000000000000000000000007a2bde9cfb7f80a4198677bdf885a43dc36c598688294f694cf64429164f140000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000f8f6080604052348015600e575f80fd5b5060156019565b60c9565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff161560685760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b039081161460c65780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b610eb9806100d65f395ff3fe6080604052600436106100d1575f3560e01c806382356d8a1161007c57806385b5b14d1161005757806385b5b14d14610276578063b49dc74114610295578063d0e12f90146102b4578063d3e5792b146102e3575f80fd5b806382356d8a1461020f5780638312f1491461024d57806384411d6514610262575f80fd5b80633ccfd60b116100ac5780633ccfd60b1461016c57806354fd4d501461018e57806366d003ac146101e3575f80fd5b80630d9019e1146100dc578063307f29621461012c5780633bbed4a01461014d575f80fd5b366100d857005b5f80fd5b3480156100e7575f80fd5b5060025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b348015610137575f80fd5b5061014b610146366004610c86565b6102f7565b005b348015610158575f80fd5b5061014b610167366004610cc3565b61047a565b348015610177575f80fd5b506101806105de565b604051908152602001610123565b348015610199575f80fd5b506101d66040518060400160405280600581526020017f312e362e3000000000000000000000000000000000000000000000000000000081525081565b6040516101239190610cde565b3480156101ee575f80fd5b506002546101029073ffffffffffffffffffffffffffffffffffffffff1681565b34801561021a575f80fd5b506002546102409074010000000000000000000000000000000000000000900460ff1681565b6040516101239190610d97565b348015610258575f80fd5b5061018060015481565b34801561026d575f80fd5b506101805f5481565b348015610281575f80fd5b5061014b610290366004610dab565b610918565b3480156102a0575f80fd5b5061014b6102af366004610dc2565b610a3b565b3480156102bf575f80fd5b5060025474010000000000000000000000000000000000000000900460ff16610240565b3480156102ee575f80fd5b50600154610180565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610354573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103789190610dfd565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146103dc576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547401000000000000000000000000000000000000000080820460ff1692849290917fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff9091169083600181111561043857610438610d31565b02179055507ff2ec44eb1c3b3acd547b76333eb2c4b27eee311860c57a9fdb04c95f62398fc8818360405161046e929190610e18565b60405180910390a15050565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104fb9190610dfd565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461055f576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f62e69886a5df0ba8ffcacbfc1388754e7abd9bde24b036354c561f1acd4e4593910161046e565b5f60015447101561069c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f4665655661756c743a207769746864726177616c20616d6f756e74206d75737460448201527f2062652067726561746572207468616e206d696e696d756d207769746864726160648201527f77616c20616d6f756e7400000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b479050805f808282546106af9190610e33565b90915550506002546040805183815273ffffffffffffffffffffffffffffffffffffffff90921660208301523382820152517fc8a211cc64b6ed1b50595a9fcb1932b6d1e5a6e8ef15b60e5b1f988ea9086bba9181900360600190a16002546040517f38e04cbeb8c10f8f568618aa75be0f10b6729b8b4237743b4de20cbcde2839ee9161077491849173ffffffffffffffffffffffffffffffffffffffff811691339174010000000000000000000000000000000000000000900460ff1690610e6b565b60405180910390a1600160025474010000000000000000000000000000000000000000900460ff1660018111156107ad576107ad610d31565b0361086a576002545f906107d79073ffffffffffffffffffffffffffffffffffffffff1683610c4f565b905080610866576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4665655661756c743a206661696c656420746f2073656e642045544820746f2060448201527f4c322066656520726563697069656e74000000000000000000000000000000006064820152608401610693565b5090565b6002546040517fc2b3e5ac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015262061a806024820152606060448201525f60648201527342000000000000000000000000000000000000169063c2b3e5ac9083906084015f604051808303818588803b1580156108fe575f80fd5b505af1158015610910573d5f803e3d5ffd5b505050505090565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610975573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109999190610dfd565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109fd576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180549082905560408051828152602081018490527f895a067c78583e800418fabf3da26a9496aab2ff3429cebdf7fefa642b2e4203910161046e565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f81158015610a855750825b90505f8267ffffffffffffffff166001148015610aa15750303b155b905081158015610aaf575080155b15610ae6576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001660011785558315610b475784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b6002805473ffffffffffffffffffffffffffffffffffffffff8a167fffffffffffffffffffffffff000000000000000000000000000000000000000082168117835560018a81558993927fffffffffffffffffffffff000000000000000000000000000000000000000000169091179074010000000000000000000000000000000000000000908490811115610bdf57610bdf610d31565b02179055508315610c455784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050565b5f610c5b835a84610c62565b9392505050565b5f805f805f858888f1949350505050565b803560028110610c81575f80fd5b919050565b5f60208284031215610c96575f80fd5b610c5b82610c73565b73ffffffffffffffffffffffffffffffffffffffff81168114610cc0575f80fd5b50565b5f60208284031215610cd3575f80fd5b8135610c5b81610c9f565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60028110610d93577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b9052565b60208101610da58284610d5e565b92915050565b5f60208284031215610dbb575f80fd5b5035919050565b5f805f60608486031215610dd4575f80fd5b8335610ddf81610c9f565b925060208401359150610df460408501610c73565b90509250925092565b5f60208284031215610e0d575f80fd5b8151610c5b81610c9f565b60408101610e268285610d5e565b610c5b6020830184610d5e565b80820180821115610da5577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b84815273ffffffffffffffffffffffffffffffffffffffff84811660208301528316604082015260808101610ea36060830184610d5e565b9594505050505056fea164736f6c6343000819000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000beb5fc579115071764c7423a4f12edde41f106ed00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001e4e9e05c420000000000000000000000004200000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000249f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001049623609d00000000000000000000000042000000000000000000000000000000000000190000000000000000000000003240dd3b3ba917563f63ea129cddff7fb696070500000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064b49dc741000000000000000000000000420000000000000000000000000000000000002b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000beb5fc579115071764c7423a4f12edde41f106ed0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000001104e9e05c4200000000000000000000000013b0d85ccb8bf860b6b79af3029fca081ae9bef200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000124f80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000102466cfa05700000000000000000000000000000000000000000000000000000000000000004ac8e160bee0acc95b22d1744fa9cc7068869945397f78a77ed68ef8ae1d87a900000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000f8f6080604052348015600e575f80fd5b5060156019565b60c9565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff161560685760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b039081161460c65780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b610eb9806100d65f395ff3fe6080604052600436106100d1575f3560e01c806382356d8a1161007c57806385b5b14d1161005757806385b5b14d14610276578063b49dc74114610295578063d0e12f90146102b4578063d3e5792b146102e3575f80fd5b806382356d8a1461020f5780638312f1491461024d57806384411d6514610262575f80fd5b80633ccfd60b116100ac5780633ccfd60b1461016c57806354fd4d501461018e57806366d003ac146101e3575f80fd5b80630d9019e1146100dc578063307f29621461012c5780633bbed4a01461014d575f80fd5b366100d857005b5f80fd5b3480156100e7575f80fd5b5060025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b348015610137575f80fd5b5061014b610146366004610c86565b6102f7565b005b348015610158575f80fd5b5061014b610167366004610cc3565b61047a565b348015610177575f80fd5b506101806105de565b604051908152602001610123565b348015610199575f80fd5b506101d66040518060400160405280600581526020017f312e362e3000000000000000000000000000000000000000000000000000000081525081565b6040516101239190610cde565b3480156101ee575f80fd5b506002546101029073ffffffffffffffffffffffffffffffffffffffff1681565b34801561021a575f80fd5b506002546102409074010000000000000000000000000000000000000000900460ff1681565b6040516101239190610d97565b348015610258575f80fd5b5061018060015481565b34801561026d575f80fd5b506101805f5481565b348015610281575f80fd5b5061014b610290366004610dab565b610918565b3480156102a0575f80fd5b5061014b6102af366004610dc2565b610a3b565b3480156102bf575f80fd5b5060025474010000000000000000000000000000000000000000900460ff16610240565b3480156102ee575f80fd5b50600154610180565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610354573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103789190610dfd565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146103dc576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547401000000000000000000000000000000000000000080820460ff1692849290917fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff9091169083600181111561043857610438610d31565b02179055507ff2ec44eb1c3b3acd547b76333eb2c4b27eee311860c57a9fdb04c95f62398fc8818360405161046e929190610e18565b60405180910390a15050565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104fb9190610dfd565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461055f576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f62e69886a5df0ba8ffcacbfc1388754e7abd9bde24b036354c561f1acd4e4593910161046e565b5f60015447101561069c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f4665655661756c743a207769746864726177616c20616d6f756e74206d75737460448201527f2062652067726561746572207468616e206d696e696d756d207769746864726160648201527f77616c20616d6f756e7400000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b479050805f808282546106af9190610e33565b90915550506002546040805183815273ffffffffffffffffffffffffffffffffffffffff90921660208301523382820152517fc8a211cc64b6ed1b50595a9fcb1932b6d1e5a6e8ef15b60e5b1f988ea9086bba9181900360600190a16002546040517f38e04cbeb8c10f8f568618aa75be0f10b6729b8b4237743b4de20cbcde2839ee9161077491849173ffffffffffffffffffffffffffffffffffffffff811691339174010000000000000000000000000000000000000000900460ff1690610e6b565b60405180910390a1600160025474010000000000000000000000000000000000000000900460ff1660018111156107ad576107ad610d31565b0361086a576002545f906107d79073ffffffffffffffffffffffffffffffffffffffff1683610c4f565b905080610866576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4665655661756c743a206661696c656420746f2073656e642045544820746f2060448201527f4c322066656520726563697069656e74000000000000000000000000000000006064820152608401610693565b5090565b6002546040517fc2b3e5ac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015262061a806024820152606060448201525f60648201527342000000000000000000000000000000000000169063c2b3e5ac9083906084015f604051808303818588803b1580156108fe575f80fd5b505af1158015610910573d5f803e3d5ffd5b505050505090565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610975573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109999190610dfd565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109fd576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180549082905560408051828152602081018490527f895a067c78583e800418fabf3da26a9496aab2ff3429cebdf7fefa642b2e4203910161046e565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f81158015610a855750825b90505f8267ffffffffffffffff166001148015610aa15750303b155b905081158015610aaf575080155b15610ae6576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001660011785558315610b475784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b6002805473ffffffffffffffffffffffffffffffffffffffff8a167fffffffffffffffffffffffff000000000000000000000000000000000000000082168117835560018a81558993927fffffffffffffffffffffff000000000000000000000000000000000000000000169091179074010000000000000000000000000000000000000000908490811115610bdf57610bdf610d31565b02179055508315610c455784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050565b5f610c5b835a84610c62565b9392505050565b5f805f805f858888f1949350505050565b803560028110610c81575f80fd5b919050565b5f60208284031215610c96575f80fd5b610c5b82610c73565b73ffffffffffffffffffffffffffffffffffffffff81168114610cc0575f80fd5b50565b5f60208284031215610cd3575f80fd5b8135610c5b81610c9f565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60028110610d93577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b9052565b60208101610da58284610d5e565b92915050565b5f60208284031215610dbb575f80fd5b5035919050565b5f805f60608486031215610dd4575f80fd5b8335610ddf81610c9f565b925060208401359150610df460408501610c73565b90509250925092565b5f60208284031215610e0d575f80fd5b8151610c5b81610c9f565b60408101610e268285610d5e565b610c5b6020830184610d5e565b80820180821115610da5577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b84815273ffffffffffffffffffffffffffffffffffffffff84811660208301528316604082015260808101610ea36060830184610d5e565b9594505050505056fea164736f6c6343000819000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000beb5fc579115071764c7423a4f12edde41f106ed00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001e4e9e05c420000000000000000000000004200000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000249f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001049623609d000000000000000000000000420000000000000000000000000000000000001a0000000000000000000000006b692240ef7a6b18aaf63a56a94d423c1b5cec0a00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064b49dc741000000000000000000000000420000000000000000000000000000000000002b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; - MultisigTask multisigTask = new RevenueShareV100UpgradePath(); - address rootSafe = address(0x5a0Aae59D09fccBdDb6C6CcEB07B7279367C3d2A); // L1PAO - address securityCouncilChildMultisig = address(0xc2819DC788505Aac350142A7A707BF9D03E3Bd03); - address[] memory allSafes = MultisigTaskTestHelper.getAllSafes(rootSafe, securityCouncilChildMultisig); - - (Action[] memory actions, uint256[] memory allOriginalNonces) = - _setupAndSimulate(taskConfigFilePath, 23434662, "mainnet", multisigTask, allSafes); - _assertCallDataMatches(multisigTask, actions, allSafes, allOriginalNonces, expectedCallData); - - string[] memory expectedDataToSign = new string[](2); - // Foundation - expectedDataToSign[0] = - "0x1901a4a9c312badf3fcaa05eafe5dc9bee8bd9316c78ee8b0bebe3115bb21b732672e9058ad53a314a39d8d71024bbae802345cd5b86f0133c8f1897b4b1c70ae80e"; - // Security Council - expectedDataToSign[1] = - "0x1901df53d510b56e539b90b369ef08fce3631020fbf921e3136ea5f8747c20bce96704658710877bdaa7bc6e316c9db98bd7e5c687ef31f09148c5dcf890475eccd7"; - _assertDataToSignNestedMultisig(multisigTask, actions, expectedDataToSign, MULTICALL3_ADDRESS, rootSafe); - } - - /// @notice Expected call data and data to sign generated by manually running the DeployFeesDepositor template at block 23197819 on mainnet. - /// Simulate from task directory (test/tasks/example/eth/016-deploy-fees-depositor/config.toml) with: - /// just --dotenv-path $(pwd)/.env --justfile ../../../../../src/improvements/justfile simulate (foundation|council) - function testRegressionCallDataMatches_DeployFeesDepositor() public { - string memory taskConfigFilePath = "test/tasks/example/eth/016-deploy-fees-depositor/config.toml"; - string memory expectedCallData = - "0x174dea7100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000010400000000000000000000000000000000000000000000000000000000000001e8000000000000000000000000013b0d85ccb8bf860b6b79af3029fca081ae9bef20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000f2466cfa0570000000000000000000000000000000000000000000000000000000000000000666565732d6465706f7369746f7200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000e9660a060405234801561001057600080fd5b50600160805261001e610023565b6100e3565b600054610100900460ff161561008f5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff90811610156100e1576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b608051610d9161010560003960008181610274015261048e0152610d916000f3fe6080604052600436106100cb5760003560e01c8063645006ca11610074578063a2a956171161004e578063a2a9561714610425578063dad544e014610445578063f68016b71461045a57600080fd5b8063645006ca1461038657806366125607146103c85780637b11936e146103e857600080fd5b80633e47158c116100a55780633e47158c146102fb57806352d84c621461031057806354fd4d501461033057600080fd5b80630de2db4d1461024057806338d38c97146102605780633cb747bf146102a357600080fd5b3661023b576040805134815247602082018190529133917f363f315f930a17d1266b86a20d6dd34b1cfbc5a9db9f13a65d06a689c3a2af8a910160405180910390a26001546bffffffffffffffffffffffff16811061023957600154600080546002546040517f3dbb202b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff6c0100000000000000000000000090950485166004820181905260606024830152606482019490945263ffffffff90911660448201529192620100009091041690633dbb202b9084906084016000604051808303818588803b1580156101ce57600080fd5b505af11580156101e2573d6000803e3d6000fd5b50505050508073ffffffffffffffffffffffffffffffffffffffff167f2acaf92365a0b69fb3570802396f62d51aabccd684036b72c3ce78699425e7ee8360405161022f91815260200190565b60405180910390a2505b005b600080fd5b34801561024c57600080fd5b5061023961025b366004610bde565b61048c565b34801561026c57600080fd5b5060405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020015b60405180910390f35b3480156102af57600080fd5b506000546102d69062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161029a565b34801561030757600080fd5b506102d661069e565b34801561031c57600080fd5b5061023961032b366004610c36565b6108a9565b34801561033c57600080fd5b506103796040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b60405161029a9190610c58565b34801561039257600080fd5b506001546103ab906bffffffffffffffffffffffff1681565b6040516bffffffffffffffffffffffff909116815260200161029a565b3480156103d457600080fd5b506102396103e3366004610ccb565b610928565b3480156103f457600080fd5b506001546102d6906c01000000000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b34801561043157600080fd5b50610239610440366004610ce8565b6109af565b34801561045157600080fd5b506102d6610a2e565b34801561046657600080fd5b506002546104779063ffffffff1681565b60405163ffffffff909116815260200161029a565b7f0000000000000000000000000000000000000000000000000000000000000000600054610100900460ff161580156104cc575060005460ff8083169116105b61055c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660ff831617610100179055610595610aab565b6000805473ffffffffffffffffffffffffffffffffffffffff8681166c01000000000000000000000000026bffffffffffffffffffffffff8916176001556002805463ffffffff87167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000009091161790557fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff9086166201000002167fffffffffffffffffffff000000000000000000000000000000000000000000ff9091161790556040517f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989061068f90839060ff91909116815260200190565b60405180910390a15050505050565b6000806106c97fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b905073ffffffffffffffffffffffffffffffffffffffff8116156106ec57919050565b6040518060400160405280601a81526020017f4f564d5f4c3143726f7373446f6d61696e4d657373656e67657200000000000081525051600261072f9190610d03565b604080513060208201526000918101919091527f4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000000919091179061078a906060015b604051602081830303815290604052805190602001205490565b146107c1576040517f54e433cd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080513060208201526001918101919091526000906107e390606001610770565b905073ffffffffffffffffffffffffffffffffffffffff811615610877578073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561084c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108709190610d67565b9250505090565b6040517f332144db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108b1610b2e565b6002805463ffffffff8381167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000083168117909355604080519190921680825260208201939093527f84858bb3fb3ecf87e268ebef250ef9ad9cd53ef7973ef7a0ec9d89470bb00a8091015b60405180910390a15050565b610930610b2e565b6001805473ffffffffffffffffffffffffffffffffffffffff8381166c010000000000000000000000008181026bffffffffffffffffffffffff85161790945560408051949093049091168084526020840191909152917f158f04d12e0403fdd63fbced694e8f70d3b87d04d8e2dfad526f5fcf6e49bbcf910161091c565b6109b7610b2e565b600180546bffffffffffffffffffffffff8381167fffffffffffffffffffffffffffffffffffffffff00000000000000000000000083168117909355604080519190921680825260208201939093527f132832be4270c0d1573ca543c41517dd443fe9daf5f21a9c74940e6db282e229910161091c565b6000610a3861069e565b73ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aa69190610d67565b905090565b33610ab461069e565b73ffffffffffffffffffffffffffffffffffffffff1614158015610af5575033610adc610a2e565b73ffffffffffffffffffffffffffffffffffffffff1614155b15610b2c576040517fc4050a2600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b33610b37610a2e565b73ffffffffffffffffffffffffffffffffffffffff1614610b2c576040517f7f12c64b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80356bffffffffffffffffffffffff81168114610ba057600080fd5b919050565b73ffffffffffffffffffffffffffffffffffffffff81168114610bc757600080fd5b50565b803563ffffffff81168114610ba057600080fd5b60008060008060808587031215610bf457600080fd5b610bfd85610b84565b93506020850135610c0d81610ba5565b92506040850135610c1d81610ba5565b9150610c2b60608601610bca565b905092959194509250565b600060208284031215610c4857600080fd5b610c5182610bca565b9392505050565b600060208083528351808285015260005b81811015610c8557858101830151858201604001528201610c69565b81811115610c97576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b600060208284031215610cdd57600080fd5b8135610c5181610ba5565b600060208284031215610cfa57600080fd5b610c5182610b84565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615610d62577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b500290565b600060208284031215610d7957600080fd5b8151610c5181610ba556fea164736f6c634300080f000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013b0d85ccb8bf860b6b79af3029fca081ae9bef20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000d8466cfa0570000000000000000000000000000000000000000000000000000000000000000666565732d6465706f7369746f7200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000ce760806040523480156200001157600080fd5b5060405162000cc738038062000cc783398181016040528101906200003791906200016f565b62000048816200004f60201b60201c565b50620001df565b600062000061620000ce60201b60201c565b905060007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610360001b90508281557f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f8284604051620000c1929190620001b2565b60405180910390a1505050565b60008060007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610360001b905080549150819250505090565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600062000137826200010a565b9050919050565b62000149816200012a565b81146200015557600080fd5b50565b60008151905062000169816200013e565b92915050565b60006020828403121562000188576200018762000105565b5b6000620001988482850162000158565b91505092915050565b620001ac816200012a565b82525050565b6000604082019050620001c96000830185620001a1565b620001d86020830184620001a1565b9392505050565b610ad880620001ef6000396000f3fe60806040526004361061004e5760003560e01c80633659cfe6146100675780634f1ef286146100905780635c60da1b146100c05780638f283970146100eb578063f851a440146101145761005d565b3661005d5761005b61013f565b005b61006561013f565b005b34801561007357600080fd5b5061008e60048036038101906100899190610715565b6101dc565b005b6100aa60048036038101906100a591906107a7565b610268565b6040516100b791906108a0565b60405180910390f35b3480156100cc57600080fd5b506100d56103ae565b6040516100e291906108d1565b60405180910390f35b3480156100f757600080fd5b50610112600480360381019061010d9190610715565b61043d565b005b34801561012057600080fd5b506101296104c9565b60405161013691906108d1565b60405180910390f35b6000610149610558565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036101ba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101b19061096f565b60405180910390fd5b3660008037600080366000845af43d6000803e806101d7573d6000fd5b3d6000f35b6101e461058f565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102495750600073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b1561025c57610257816105c6565b610265565b61026461013f565b5b50565b606061027261058f565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102d75750600073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b1561039e576102e5846105c6565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161030f9291906109ce565b600060405180830381855af49150503d806000811461034a576040519150601f19603f3d011682016040523d82523d6000602084013e61034f565b606091505b509150915081610394576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161038b90610a59565b60405180910390fd5b80925050506103a7565b6103a661013f565b5b9392505050565b60006103b861058f565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061041d5750600073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b156104315761042a610558565b905061043a565b61043961013f565b5b90565b61044561058f565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806104aa5750600073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b156104bd576104b881610638565b6104c6565b6104c561013f565b5b50565b60006104d361058f565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806105385750600073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b1561054c5761054561058f565b9050610555565b61055461013f565b5b90565b60008060007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b905080549150819250505090565b60008060007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610360001b905080549150819250505090565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b90508181558173ffffffffffffffffffffffffffffffffffffffff167fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b60405160405180910390a25050565b600061064261058f565b905060007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610360001b90508281557f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f82846040516106a0929190610a79565b60405180910390a1505050565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006106e2826106b7565b9050919050565b6106f2816106d7565b81146106fd57600080fd5b50565b60008135905061070f816106e9565b92915050565b60006020828403121561072b5761072a6106ad565b5b600061073984828501610700565b91505092915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261076757610766610742565b5b8235905067ffffffffffffffff81111561078457610783610747565b5b6020830191508360018202830111156107a05761079f61074c565b5b9250929050565b6000806000604084860312156107c0576107bf6106ad565b5b60006107ce86828701610700565b935050602084013567ffffffffffffffff8111156107ef576107ee6106b2565b5b6107fb86828701610751565b92509250509250925092565b600081519050919050565b600082825260208201905092915050565b60005b83811015610841578082015181840152602081019050610826565b83811115610850576000848401525b50505050565b6000601f19601f8301169050919050565b600061087282610807565b61087c8185610812565b935061088c818560208601610823565b61089581610856565b840191505092915050565b600060208201905081810360008301526108ba8184610867565b905092915050565b6108cb816106d7565b82525050565b60006020820190506108e660008301846108c2565b92915050565b600082825260208201905092915050565b7f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160008201527f6c697a6564000000000000000000000000000000000000000000000000000000602082015250565b60006109596025836108ec565b9150610964826108fd565b604082019050919050565b600060208201905081810360008301526109888161094c565b9050919050565b600081905092915050565b82818337600083830152505050565b60006109b5838561098f565b93506109c283858461099a565b82840190509392505050565b60006109db8284866109a9565b91508190509392505050565b7f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560008201527f6d656e746174696f6e20636f6e7472616374206661696c656400000000000000602082015250565b6000610a436039836108ec565b9150610a4e826109e7565b604082019050919050565b60006020820190508181036000830152610a7281610a36565b9050919050565b6000604082019050610a8e60008301856108c2565b610a9b60208301846108c2565b939250505056fea2646970667358221220e170e6bf8ee3cc199be5ea3ca30084b98725d89b560e407f600f4a174236633364736f6c634300080f0033000000000000000000000000543ba4aadbab8f9025686bd03993043599c6fb040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000543ba4aadbab8f9025686bd03993043599c6fb0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001249623609d0000000000000000000000004070ef4adfc04f537c7cf5742bb005b4e87b953000000000000000000000000090a79d28ad7f6d472ad1cfe3bad65204ab2969a2000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000840de2db4d0000000000000000000000000000000000000000000000004563918244f400000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000beb5fc579115071764c7423a4f12edde41f106ed00000000000000000000000000000000000000000000000000000000000493e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; - MultisigTask multisigTask = new DeployFeesDepositor(); - address rootSafe = address(0x5a0Aae59D09fccBdDb6C6CcEB07B7279367C3d2A); // L1PAO - address securityCouncilChildMultisig = address(0xc2819DC788505Aac350142A7A707BF9D03E3Bd03); - address[] memory allSafes = MultisigTaskTestHelper.getAllSafes(rootSafe, securityCouncilChildMultisig); - - (Action[] memory actions, uint256[] memory allOriginalNonces) = - _setupAndSimulate(taskConfigFilePath, 23197819, "mainnet", multisigTask, allSafes); - _assertCallDataMatches(multisigTask, actions, allSafes, allOriginalNonces, expectedCallData); - - string[] memory expectedDataToSign = new string[](2); - // Foundation - expectedDataToSign[0] = - "0x1901a4a9c312badf3fcaa05eafe5dc9bee8bd9316c78ee8b0bebe3115bb21b7326725164231e485f6dc9e25f4d32abf7ec7b88314ba0a65c7602e61c85f77d77f160"; - // Security Council - expectedDataToSign[1] = - "0x1901df53d510b56e539b90b369ef08fce3631020fbf921e3136ea5f8747c20bce96780d02fe7f03794508b9de312452403babba436c704cbd50c418d85a0fec772ef"; - _assertDataToSignNestedMultisig(multisigTask, actions, expectedDataToSign, MULTICALL3_ADDRESS, rootSafe); - } - /// @notice Expected call data and data to sign generated by manually running the GnosisSafeRotateSigner at block 9264006 on sepolia using script: /// forge script GnosisSafeRotateSigner --sig "simulate(string)" test/tasks/example/sep/016-gnosis-safe-remove-owner/config.toml --rpc-url sepolia --fork-block-number 9264006 -vv function testRegressionCallDataMatches_GnosisSafeRotateSigner() public { diff --git a/test/tasks/example/eth/015-revenue-share-upgrade/.env b/test/tasks/example/eth/015-revenue-share-upgrade/.env deleted file mode 100644 index be0c0bdcfe..0000000000 --- a/test/tasks/example/eth/015-revenue-share-upgrade/.env +++ /dev/null @@ -1,3 +0,0 @@ -TENDERLY_GAS=15000000 -FORK_BLOCK_NUMBER=23434662 -NESTED_SAFE_NAME_DEPTH_1=foundation \ No newline at end of file diff --git a/test/tasks/example/eth/015-revenue-share-upgrade/config.toml b/test/tasks/example/eth/015-revenue-share-upgrade/config.toml deleted file mode 100644 index 4cdeb7b8b2..0000000000 --- a/test/tasks/example/eth/015-revenue-share-upgrade/config.toml +++ /dev/null @@ -1,23 +0,0 @@ -templateName = "RevenueShareV100UpgradePath" - -# Portal and deployment configuration -portal = "0xbEb5Fc579115071764c7423A4f12eDde41f106Ed" # OptimismPortal address -saltSeed = "DeploymentSalt" # Deployment salt - -# Calculator Configuration -# Set to true to deploy the default SC Rev Share Calculator and L1Withdrawer -useDefaultCalculator = true - -# L1 Withdrawer Configuration -l1WithdrawerMinWithdrawalAmount = 350000 -# TODO(17505): This address MUST be updated once the appropriate FeesDepositor is deployed -# The deployment is done by running the task at test/tasks/example/eth/016-deploy-fees-depositor -l1WithdrawerRecipient = "0x742d35Cc6634C0532925a3b8D0C0C8b8B0c0C8b8" # L1 recipient address -l1WithdrawerGasLimit = 800000 # Gas limit for L1 withdrawal transactions - -# SC Rev Share Calculator Configuration -scRevShareCalcChainFeesRecipient = "0x8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b" # Chain fees recipient - -[addresses] -ProxyAdminOwner = "0x5a0Aae59D09fccBdDb6C6CcEB07B7279367C3d2A" -OptimismPortal = "0xbEb5Fc579115071764c7423A4f12eDde41f106Ed" \ No newline at end of file diff --git a/test/tasks/example/eth/016-deploy-fees-depositor/.env b/test/tasks/example/eth/016-deploy-fees-depositor/.env deleted file mode 100644 index d4a7b76058..0000000000 --- a/test/tasks/example/eth/016-deploy-fees-depositor/.env +++ /dev/null @@ -1,3 +0,0 @@ -TENDERLY_GAS=10000000 -NESTED_SAFE_NAME_DEPTH_1=council -FORK_BLOCK_NUMBER=23197819 \ No newline at end of file diff --git a/test/tasks/example/eth/016-deploy-fees-depositor/config.toml b/test/tasks/example/eth/016-deploy-fees-depositor/config.toml deleted file mode 100644 index 5efafdbd0b..0000000000 --- a/test/tasks/example/eth/016-deploy-fees-depositor/config.toml +++ /dev/null @@ -1,11 +0,0 @@ -templateName = "DeployFeesDepositor" - -salt = "fees-depositor" -minDepositAmount = 5000000000000000000 -l2Recipient = "0x0000000000000000000000000000000000000001" -portal = "0xbEb5Fc579115071764c7423A4f12eDde41f106Ed" -gasLimit = 300000 -proxyAdmin = "0x543bA4AADBAb8f9025686Bd03993043599c6fB04" - -[addresses] -ProxyAdminOwner = "0x5a0Aae59D09fccBdDb6C6CcEB07B7279367C3d2A" \ No newline at end of file diff --git a/test/tasks/example/eth/018-revshare-upgrade-and-setup/config.toml b/test/tasks/example/eth/016-revshare-upgrade-and-setup/config.toml similarity index 100% rename from test/tasks/example/eth/018-revshare-upgrade-and-setup/config.toml rename to test/tasks/example/eth/016-revshare-upgrade-and-setup/config.toml diff --git a/test/tasks/example/eth/017-revenue-share-upgrade-custom-calc/.env b/test/tasks/example/eth/017-revenue-share-upgrade-custom-calc/.env deleted file mode 100644 index cbd4c581e3..0000000000 --- a/test/tasks/example/eth/017-revenue-share-upgrade-custom-calc/.env +++ /dev/null @@ -1,3 +0,0 @@ -TENDERLY_GAS=15000000 -FORK_BLOCK_NUMBER=23434662 -NESTED_SAFE_NAME_DEPTH_1=foundation diff --git a/test/tasks/example/eth/017-revenue-share-upgrade-custom-calc/config.toml b/test/tasks/example/eth/017-revenue-share-upgrade-custom-calc/config.toml deleted file mode 100644 index c0bf6f0908..0000000000 --- a/test/tasks/example/eth/017-revenue-share-upgrade-custom-calc/config.toml +++ /dev/null @@ -1,16 +0,0 @@ -templateName = "RevenueShareV100UpgradePath" - -# Portal and deployment configuration -portal = "0xbEb5Fc579115071764c7423A4f12eDde41f106Ed" # OptimismPortal address -saltSeed = "DeploymentSalt" # Deployment salt - -# Calculator Configuration -# Set to false to use a custom calculator (skips deploying L1Withdrawer and SC Rev Share Calculator) -useDefaultCalculator = false - -# Custom Calculator Configuration -customCalculator = "0x8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b" - -[addresses] -ProxyAdminOwner = "0x5a0Aae59D09fccBdDb6C6CcEB07B7279367C3d2A" -OptimismPortal = "0xbEb5Fc579115071764c7423A4f12eDde41f106Ed" diff --git a/test/template/deploy-fees-depositor/DeployFeesDepositor.t.sol b/test/template/deploy-fees-depositor/DeployFeesDepositor.t.sol deleted file mode 100644 index ac50b54deb..0000000000 --- a/test/template/deploy-fees-depositor/DeployFeesDepositor.t.sol +++ /dev/null @@ -1,223 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.15; - -import {Test} from "forge-std/Test.sol"; -import {DeployFeesDepositor, IFeesDepositor} from "src/template/DeployFeesDepositor.sol"; -import {Action} from "src/libraries/MultisigTypes.sol"; -import {Create2} from "@openzeppelin/contracts/utils/Create2.sol"; -import {Proxy} from "optimism/packages/contracts-bedrock/src/universal/Proxy.sol"; -import {RevShareCodeRepo} from "src/libraries/RevShareCodeRepo.sol"; -import {IProxyAdmin} from "optimism/packages/contracts-bedrock/interfaces/universal/IProxyAdmin.sol"; - -/// @notice Test contract for the DeployFeesDepositor that expect reverts on misconfiguration of required fields. -contract DeployFeesDepositorRequiredFieldsTest is Test { - DeployFeesDepositor public template; - string internal constant TEMP_CONFIG_DIR = "test/template/deploy-fees-depositor/"; - - // Default valid values for tests - string internal constant DEFAULT_SALT = "test-fees-depositor"; - string internal constant DEFAULT_L2_RECIPIENT = "0x0000000000000000000000000000000000000001"; - string internal constant DEFAULT_PORTAL = "0xbEb5Fc579115071764c7423A4f12eDde41f106Ed"; - uint256 internal constant DEFAULT_GAS_LIMIT = 300000; - string internal constant DEFAULT_PROXY_ADMIN = "0x543bA4AADBAb8f9025686Bd03993043599c6fB04"; - - // Invalid values for tests - string internal constant ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"; - string internal constant EMPTY_STRING = ""; - uint256 internal constant UINT32_MAX_PLUS_ONE = 4294967296; - - function setUp() public { - vm.createSelectFork("mainnet", 23197819); - template = new DeployFeesDepositor(); - } - - /// @notice Helper to write a minimal config for testing validation - /// @param _salt Salt for deployment - /// @param _l2Recipient L2 recipient address - /// @param _portal Portal address - /// @param _gasLimit Gas limit for transactions - /// @param _proxyAdmin ProxyAdmin address - /// @return Path to the created config file - function _writeTestConfig( - string memory _salt, - string memory _l2Recipient, - string memory _portal, - uint256 _gasLimit, - string memory _proxyAdmin - ) internal returns (string memory) { - string memory config = string.concat( - 'templateName = "DeployFeesDepositor"\n\nsalt = "', - _salt, - '"\nminDepositAmount = 5000000000000000000\nl2Recipient = "', - _l2Recipient, - '"\nportal = "', - _portal, - '"\ngasLimit = ', - vm.toString(_gasLimit), - '\nproxyAdmin = "', - _proxyAdmin, - '"\n\n[addresses]\nProxyAdminOwner = "0x5a0Aae59D09fccBdDb6C6CcEB07B7279367C3d2A"' - ); - string memory configPath = string.concat(TEMP_CONFIG_DIR, "temp-config-", vm.toString(uint256(uint32(msg.sig))), ".toml"); - vm.writeFile(configPath, config); - return configPath; - } - - /// @notice Tests that the template reverts when the salt is an empty string. - function test_deployFeesDepositor_salt_empty_string_reverts() public { - string memory configPath = _writeTestConfig( - EMPTY_STRING, // INVALID - salt is empty - DEFAULT_L2_RECIPIENT, - DEFAULT_PORTAL, - DEFAULT_GAS_LIMIT, - DEFAULT_PROXY_ADMIN - ); - vm.expectRevert("salt must be set"); - template.simulate(configPath); - vm.removeFile(configPath); - } - - /// @notice Tests that the template reverts when the l2Recipient is a zero address. - function test_deployFeesDepositor_l2Recipient_zero_address_reverts() public { - string memory configPath = _writeTestConfig( - DEFAULT_SALT, - ZERO_ADDRESS, // INVALID - l2Recipient is zero address - DEFAULT_PORTAL, - DEFAULT_GAS_LIMIT, - DEFAULT_PROXY_ADMIN - ); - vm.expectRevert("l2Recipient must be set"); - template.simulate(configPath); - vm.removeFile(configPath); - } - - /// @notice Tests that the template reverts when the portal is a zero address. - function test_deployFeesDepositor_portal_zero_address_reverts() public { - string memory configPath = _writeTestConfig( - DEFAULT_SALT, - DEFAULT_L2_RECIPIENT, - ZERO_ADDRESS, // INVALID - portal is zero address - DEFAULT_GAS_LIMIT, - DEFAULT_PROXY_ADMIN - ); - vm.expectRevert("portal must be set"); - template.simulate(configPath); - vm.removeFile(configPath); - } - - /// @notice Tests that the template reverts when the gasLimit is zero. - function test_deployFeesDepositor_gasLimit_zero_reverts() public { - string memory configPath = _writeTestConfig( - DEFAULT_SALT, - DEFAULT_L2_RECIPIENT, - DEFAULT_PORTAL, - 0, // INVALID - gasLimit is zero - DEFAULT_PROXY_ADMIN - ); - vm.expectRevert("gasLimit must be set"); - template.simulate(configPath); - vm.removeFile(configPath); - } - - /// @notice Tests that the template reverts when the gasLimit is too high. - function test_deployFeesDepositor_gasLimit_too_high_reverts() public { - string memory configPath = _writeTestConfig( - DEFAULT_SALT, - DEFAULT_L2_RECIPIENT, - DEFAULT_PORTAL, - UINT32_MAX_PLUS_ONE, // INVALID - gasLimit exceeds uint32.max - DEFAULT_PROXY_ADMIN - ); - vm.expectRevert("gasLimit must be less than uint32.max"); - template.simulate(configPath); - vm.removeFile(configPath); - } - - /// @notice Tests that the template reverts when the ProxyAdmin is a zero address. - function test_deployFeesDepositor_proxyAdmin_zero_address_reverts() public { - string memory configPath = _writeTestConfig( - DEFAULT_SALT, - DEFAULT_L2_RECIPIENT, - DEFAULT_PORTAL, - DEFAULT_GAS_LIMIT, - ZERO_ADDRESS // INVALID - proxyAdmin is zero address - ); - vm.expectRevert("proxyAdmin must be set"); - template.simulate(configPath); - vm.removeFile(configPath); - } -} - -/// @notice Test contract for successful deployment of the FeesDepositor template. -contract DeployFeesDepositorSuccessTest is Test { - DeployFeesDepositor public template; - - // Expected configuration values from the task config - string public constant SALT = "fees-depositor"; - uint96 public constant MIN_DEPOSIT_AMOUNT = 5000000000000000000; - address public constant L2_RECIPIENT = 0x0000000000000000000000000000000000000001; - address public constant PORTAL = 0xbEb5Fc579115071764c7423A4f12eDde41f106Ed; - uint32 public constant GAS_LIMIT = 300000; - address public constant PROXY_ADMIN = 0x543bA4AADBAb8f9025686Bd03993043599c6fB04; - address public constant PROXY_ADMIN_OWNER = 0x5a0Aae59D09fccBdDb6C6CcEB07B7279367C3d2A; - address internal constant CREATE2_DEPLOYER = address(0x13b0D85CcB8bf860b6b79AF3029fCA081AE9beF2); - - string public constant configPath = "test/tasks/example/eth/016-deploy-fees-depositor/config.toml"; - - function setUp() public { - vm.createSelectFork("mainnet", 23197819); - template = new DeployFeesDepositor(); - } - - /// @notice Tests successful deployment and initialization of FeesDepositor - function test_deployFeesDepositor_succeds() public { - // Execute the simulation - (, Action[] memory actions,, address rootSafe) = template.simulate(configPath, new address[](0)); - - // Verify the root safe is correct - assertEq(rootSafe, PROXY_ADMIN_OWNER, "Root safe should be ProxyAdminOwner"); - - // Verify actions were created (should have 3: deploy impl, deploy proxy, upgradeAndCall) - assertEq(actions.length, 3, "Should have exactly 3 actions"); - - // Calculate expected deployed addresses using the same logic as the template - bytes memory proxyInitCode = bytes.concat(type(Proxy).creationCode, abi.encode(PROXY_ADMIN)); - address proxyAddress = Create2.computeAddress(bytes32(bytes(SALT)), keccak256(proxyInitCode), CREATE2_DEPLOYER); - address implAddress = Create2.computeAddress( - bytes32(bytes(SALT)), keccak256(RevShareCodeRepo.feesDepositorCreationCode), CREATE2_DEPLOYER - ); - - // Verify action 0: Deploy implementation - assertEq(actions[0].target, CREATE2_DEPLOYER, "Action 0 should target CREATE2_DEPLOYER"); - assertEq(actions[0].value, 0, "Action 0 should have no value"); - assertGt(actions[0].arguments.length, 0, "Action 0 should have calldata"); - - // Verify action 1: Deploy proxy - assertEq(actions[1].target, CREATE2_DEPLOYER, "Action 1 should target CREATE2_DEPLOYER"); - assertEq(actions[1].value, 0, "Action 1 should have no value"); - assertGt(actions[1].arguments.length, 0, "Action 1 should have calldata"); - - // Verify action 2: UpgradeAndCall - assertEq(actions[2].target, PROXY_ADMIN, "Action 2 should target ProxyAdmin"); - assertEq(actions[2].value, 0, "Action 2 should have no value"); - assertGt(actions[2].arguments.length, 0, "Action 2 should have calldata"); - - // Verify both contracts were deployed - assertTrue(proxyAddress.code.length > 0, "Proxy should be deployed"); - assertTrue(implAddress.code.length > 0, "Implementation should be deployed"); - - // Verify proxy was initialized with correct values - IFeesDepositor feesDepositor = IFeesDepositor(payable(proxyAddress)); - assertEq(feesDepositor.minDepositAmount(), MIN_DEPOSIT_AMOUNT, "minDepositAmount should match config"); - assertEq(feesDepositor.l2Recipient(), L2_RECIPIENT, "l2Recipient should match config"); - assertEq(feesDepositor.gasLimit(), GAS_LIMIT, "gasLimit should match config"); - - // Verify the template's public variables were set correctly - assertEq(template.salt(), SALT, "Salt should match config"); - assertEq(template.l2Recipient(), L2_RECIPIENT, "l2Recipient should match config"); - assertEq(template.minDepositAmount(), MIN_DEPOSIT_AMOUNT, "minDepositAmount should match config"); - assertEq(template.portal(), PORTAL, "portal should match config"); - assertEq(template.gasLimit(), GAS_LIMIT, "gasLimit should match config"); - assertEq(template.proxyAdmin(), PROXY_ADMIN, "proxyAdmin should match config"); - } -} From 0f59f65f98683a497844867b7d16c75a62cdf43c Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Mon, 10 Nov 2025 17:38:43 -0300 Subject: [PATCH 47/69] chore: remove deprecated test --- .../integration/RevenueShareIntegration.t.sol | 180 ------------------ 1 file changed, 180 deletions(-) delete mode 100644 test/integration/RevenueShareIntegration.t.sol diff --git a/test/integration/RevenueShareIntegration.t.sol b/test/integration/RevenueShareIntegration.t.sol deleted file mode 100644 index c0cf4a723c..0000000000 --- a/test/integration/RevenueShareIntegration.t.sol +++ /dev/null @@ -1,180 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.15; - -import {RevenueShareV100UpgradePath} from "src/template/RevenueShareUpgradePath.sol"; -import {Action} from "src/libraries/MultisigTypes.sol"; -import {IntegrationBase} from "./IntegrationBase.t.sol"; -import {Test} from "forge-std/Test.sol"; - -enum WithdrawalNetwork { - L1, - L2 -} - -interface IFeeVault { - function MIN_WITHDRAWAL_AMOUNT() external view returns (uint256); - function RECIPIENT() external view returns (address); - 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); -} - -interface IFeeSplitter { - function sharesCalculator() external view returns (address); -} - -interface IL1Withdrawer { - function minWithdrawalAmount() external view returns (uint256); - function recipient() external view returns (address); - function withdrawalGasLimit() external view returns (uint32); -} - -interface ISuperchainRevSharesCalculator { - function shareRecipient() external view returns (address payable); - function remainderRecipient() external view returns (address payable); -} - -contract RevenueShareIntegrationTest is IntegrationBase { - RevenueShareV100UpgradePath public revenueShareTemplate; - - // Fork IDs - uint256 internal _mainnetForkId; - uint256 internal _l2ForkId; - - // L1 addresses - address internal constant OP_MAINNET_PORTAL = 0xbEb5Fc579115071764c7423A4f12eDde41f106Ed; - - // L2 predeploys - /// @notice Address of the Sequencer Fee Vault Predeploy on L2. - address internal constant SEQUENCER_FEE_VAULT = 0x4200000000000000000000000000000000000011; - /// @notice Address of the Operator Fee Vault Predeploy on L2. - address internal constant OPERATOR_FEE_VAULT = 0x420000000000000000000000000000000000001b; - /// @notice Address of the Base Fee Vault Predeploy on L2. - address internal constant BASE_FEE_VAULT = 0x4200000000000000000000000000000000000019; - /// @notice Address of the L1 Fee Vault Predeploy on L2. - address internal constant L1_FEE_VAULT = 0x420000000000000000000000000000000000001A; - /// @notice Address of the FeeSplitter Predeploy on L2. - address internal constant FEE_SPLITTER = 0x420000000000000000000000000000000000002B; - - // Deployed contracts (precalculated as they are deployed with CREATE2) - /// @notice Address of the L1 Withdrawer Predeploy on L2. - address internal constant L1_WITHDRAWER = 0x524E512Dd372C70E7866a7825481385b7b533af0; - /// @notice Address of the Rev Share Calculator Predeploy on L2. - address internal constant REV_SHARE_CALCULATOR = 0x72aa66CaA04C9bd83Ecc43c65cff2Cf837EE4BB3; - - function setUp() public { - _mainnetForkId = vm.createFork("http://127.0.0.1:8545"); - _l2ForkId = vm.createFork("http://127.0.0.1:9545"); - vm.selectFork(_mainnetForkId); - revenueShareTemplate = new RevenueShareV100UpgradePath(); - } - - /// @notice Test the integration of the revenue share system when the chain is opting in - function test_revenueShare_defaultCalculator_integration() public { - string memory _configPath = "test/tasks/example/eth/015-revenue-share-upgrade/config.toml"; - - // Step 1: Execute L1 transaction recording logs - vm.recordLogs(); - revenueShareTemplate.simulate(_configPath, new address[](0)); - - // Step 2: Relay messages from L1 to L2 - // Pass true for _isSimulate since simulate() emits events twice - uint256[] memory forkIds = new uint256[](1); - forkIds[0] = _l2ForkId; - - address[] memory portals = new address[](1); - portals[0] = OP_MAINNET_PORTAL; - - _relayAllMessages(forkIds, true, portals); - - // Step 3: Assert the state of the L2 contracts - string memory _config = vm.readFile(_configPath); - - // L1Withdrawer: check withdrawal threshold and fees depositor - assertEq( - IL1Withdrawer(L1_WITHDRAWER).minWithdrawalAmount(), - vm.parseTomlUint(_config, ".l1WithdrawerMinWithdrawalAmount") - ); - assertEq(IL1Withdrawer(L1_WITHDRAWER).recipient(), vm.parseTomlAddress(_config, ".l1WithdrawerRecipient")); - assertEq(IL1Withdrawer(L1_WITHDRAWER).withdrawalGasLimit(), vm.parseTomlUint(_config, ".l1WithdrawerGasLimit")); - - // Rev Share Calculator: check chain fees recipient and remainder recipient - assertEq(ISuperchainRevSharesCalculator(REV_SHARE_CALCULATOR).shareRecipient(), L1_WITHDRAWER); - assertEq( - ISuperchainRevSharesCalculator(REV_SHARE_CALCULATOR).remainderRecipient(), - vm.parseTomlAddress(_config, ".scRevShareCalcChainFeesRecipient") - ); - - // Fee Splitter: check calculator is set - assertEq(IFeeSplitter(FEE_SPLITTER).sharesCalculator(), REV_SHARE_CALCULATOR); - - // Vaults: recipient should be fee splitter, withdrawal network should be L2, min withdrawal amount 0 - // getters for legacy and the new values should be the same - _assertFeeVaultsState(); - } - - /// @notice Test the integration of the revenue share system when the chain is opting in with a custom calculator - function test_revenueShare_customCalculator_integration() public { - string memory _configPath = "test/tasks/example/eth/017-revenue-share-upgrade-custom-calc/config.toml"; - - // Step 1: Execute L1 transaction recording logs - vm.recordLogs(); - revenueShareTemplate.simulate(_configPath, new address[](0)); - - // Step 2: Relay messages from L1 to L2 - // Pass true for _isSimulate since simulate() emits events twice - uint256[] memory forkIds = new uint256[](1); - forkIds[0] = _l2ForkId; - - address[] memory portals = new address[](1); - portals[0] = OP_MAINNET_PORTAL; - - _relayAllMessages(forkIds, true, portals); - - // Step 3: Assert the state of the L2 contracts - string memory _config = vm.readFile(_configPath); - - // L1Withdrawer: check it wasn't deployed - assertEq(L1_WITHDRAWER.code.length, 0); - - // Rev Share Calculator: check it wasn't deployed - assertEq(REV_SHARE_CALCULATOR.code.length, 0); - - // Fee Splitter: check calculator is set - assertEq(IFeeSplitter(FEE_SPLITTER).sharesCalculator(), vm.parseTomlAddress(_config, ".customCalculator")); - - // Vaults: recipient should be fee splitter, withdrawal network should be L2, min withdrawal amount 0 - // getters for legacy and the new values should be the same - _assertFeeVaultsState(); - } - - /// @notice Assert the configuration of the fee vaults - /// @dev Ensures both the legacy and the new getters return the same value - function _assertFeeVaultsState() internal view { - _assertVaultGetters(SEQUENCER_FEE_VAULT, FEE_SPLITTER, WithdrawalNetwork.L2, 0); - _assertVaultGetters(OPERATOR_FEE_VAULT, FEE_SPLITTER, WithdrawalNetwork.L2, 0); - _assertVaultGetters(BASE_FEE_VAULT, FEE_SPLITTER, WithdrawalNetwork.L2, 0); - _assertVaultGetters(L1_FEE_VAULT, FEE_SPLITTER, WithdrawalNetwork.L2, 0); - } - - /// @notice Assert the configuration of a fee vault - /// @param _vault The address of the fee vault - /// @param _recipient The recipient of the fee vault - /// @param _withdrawalNetwork The withdrawal network of the fee vault - /// @param _minWithdrawalAmount The minimum withdrawal amount of the fee vault - /// @dev Ensures both the legacy and the new getters return the same value - function _assertVaultGetters( - address _vault, - address _recipient, - WithdrawalNetwork _withdrawalNetwork, - uint256 _minWithdrawalAmount - ) internal view { - assertEq(IFeeVault(_vault).recipient(), _recipient); - assertEq(uint256(IFeeVault(_vault).withdrawalNetwork()), uint256(_withdrawalNetwork)); - assertEq(IFeeVault(_vault).minWithdrawalAmount(), _minWithdrawalAmount); - assertEq(IFeeVault(_vault).RECIPIENT(), _recipient); - assertEq(uint256(IFeeVault(_vault).WITHDRAWAL_NETWORK()), uint256(_withdrawalNetwork)); - assertEq(IFeeVault(_vault).MIN_WITHDRAWAL_AMOUNT(), _minWithdrawalAmount); - } -} From 6a015e9d35adb5c8e769b1b71671bb587200a1de Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Mon, 10 Nov 2025 17:59:27 -0300 Subject: [PATCH 48/69] refactor: use common library for all revshare configs/data/creation codes --- src/RevShareContractsUpgrader.sol | 64 +- src/libraries/RevShareCodeRepo.sol | 24 - src/libraries/RevShareGasLimits.sol | 32 - src/libraries/RevShareLibrary.sol | 86 +++ src/libraries/RevSharePredeploys.sol | 23 - src/template/RevenueShareUpgradePath.sol | 164 +++-- .../RevenueShareUpgradePath.t.sol | 570 ------------------ 7 files changed, 198 insertions(+), 765 deletions(-) delete mode 100644 src/libraries/RevShareCodeRepo.sol delete mode 100644 src/libraries/RevShareGasLimits.sol create mode 100644 src/libraries/RevShareLibrary.sol delete mode 100644 src/libraries/RevSharePredeploys.sol delete mode 100644 test/template/revenue-share-upgrade-path/RevenueShareUpgradePath.t.sol diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol index 6c9fa78b22..815be502c8 100644 --- a/src/RevShareContractsUpgrader.sol +++ b/src/RevShareContractsUpgrader.sol @@ -1,9 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import {RevSharePredeploys} from "src/libraries/RevSharePredeploys.sol"; -import {RevShareCodeRepo} from "src/libraries/RevShareCodeRepo.sol"; -import {RevShareGasLimits} from "src/libraries/RevShareGasLimits.sol"; +import {RevShareLibrary} from "src/libraries/RevShareLibrary.sol"; import {Utils} from "src/libraries/Utils.sol"; // Interfaces @@ -19,7 +17,7 @@ import {IFeeVault} from "src/interfaces/IFeeVault.sol"; /// 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 is RevSharePredeploys { +contract RevShareContractsUpgrader { /// @notice Base salt seed for CREATE2 deployments string private constant SALT_SEED = "RevShare"; @@ -75,20 +73,20 @@ contract RevShareContractsUpgrader is RevSharePredeploys { // This prevents the edge case where fees could be sent to an uninitialized FeeSplitter bytes32 feeSplitterSalt = _getSalt("FeeSplitter"); address feeSplitterImpl = - Utils.getCreate2Address(feeSplitterSalt, RevShareCodeRepo.feeSplitterCreationCode, CREATE2_DEPLOYER); + Utils.getCreate2Address(feeSplitterSalt, RevShareLibrary.feeSplitterCreationCode, RevShareLibrary.CREATE2_DEPLOYER); _depositCreate2( _portals[i], - RevShareGasLimits.FEE_SPLITTER_DEPLOYMENT_GAS_LIMIT, + RevShareLibrary.FEE_SPLITTER_DEPLOYMENT_GAS_LIMIT, feeSplitterSalt, - RevShareCodeRepo.feeSplitterCreationCode + RevShareLibrary.feeSplitterCreationCode ); _depositCall( _portals[i], - address(PROXY_ADMIN), - RevShareGasLimits.UPGRADE_GAS_LIMIT, + address(RevShareLibrary.PROXY_ADMIN), + RevShareLibrary.UPGRADE_GAS_LIMIT, abi.encodeCall( IProxyAdmin.upgradeAndCall, - (payable(FEE_SPLITTER), feeSplitterImpl, abi.encodeCall(IFeeSplitter.initialize, (calculator))) + (payable(RevShareLibrary.FEE_SPLITTER), feeSplitterImpl, abi.encodeCall(IFeeSplitter.initialize, (calculator))) ) ); @@ -123,8 +121,8 @@ contract RevShareContractsUpgrader is RevSharePredeploys { // Set calculator on fee splitter _depositCall( _portals[i], - FEE_SPLITTER, - RevShareGasLimits.SETTERS_GAS_LIMIT, + RevShareLibrary.FEE_SPLITTER, + RevShareLibrary.SETTERS_GAS_LIMIT, abi.encodeCall(IFeeSplitter.setSharesCalculator, (calculator)) ); @@ -145,39 +143,39 @@ contract RevShareContractsUpgrader is RevSharePredeploys { ) private returns (address calculator) { // Deploy L1Withdrawer bytes memory l1WithdrawerInitCode = bytes.concat( - RevShareCodeRepo.l1WithdrawerCreationCode, + RevShareLibrary.l1WithdrawerCreationCode, abi.encode(_l1WithdrawerConfig.minWithdrawalAmount, _l1WithdrawerConfig.recipient, _l1WithdrawerConfig.gasLimit) ); bytes32 l1WithdrawerSalt = _getSalt("L1Withdrawer"); - address l1Withdrawer = Utils.getCreate2Address(l1WithdrawerSalt, l1WithdrawerInitCode, CREATE2_DEPLOYER); + address l1Withdrawer = Utils.getCreate2Address(l1WithdrawerSalt, l1WithdrawerInitCode, RevShareLibrary.CREATE2_DEPLOYER); _depositCreate2( - _portal, RevShareGasLimits.L1_WITHDRAWER_DEPLOYMENT_GAS_LIMIT, l1WithdrawerSalt, l1WithdrawerInitCode + _portal, RevShareLibrary.L1_WITHDRAWER_DEPLOYMENT_GAS_LIMIT, l1WithdrawerSalt, l1WithdrawerInitCode ); // Deploy SuperchainRevenueShareCalculator bytes memory calculatorInitCode = - bytes.concat(RevShareCodeRepo.scRevShareCalculatorCreationCode, abi.encode(l1Withdrawer, _chainFeesRecipient)); + bytes.concat(RevShareLibrary.scRevShareCalculatorCreationCode, abi.encode(l1Withdrawer, _chainFeesRecipient)); bytes32 calculatorSalt = _getSalt("SCRevShareCalculator"); - calculator = Utils.getCreate2Address(calculatorSalt, calculatorInitCode, CREATE2_DEPLOYER); + calculator = Utils.getCreate2Address(calculatorSalt, calculatorInitCode, RevShareLibrary.CREATE2_DEPLOYER); _depositCreate2( - _portal, RevShareGasLimits.SC_REV_SHARE_CALCULATOR_DEPLOYMENT_GAS_LIMIT, calculatorSalt, calculatorInitCode + _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 = [OPERATOR_FEE_VAULT, SEQUENCER_FEE_WALLET, BASE_FEE_VAULT, L1_FEE_VAULT]; + 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], RevShareGasLimits.SETTERS_GAS_LIMIT, abi.encodeCall(IFeeVault.setRecipient, (FEE_SPLITTER)) + _portal, vaults[i], RevShareLibrary.SETTERS_GAS_LIMIT, abi.encodeCall(IFeeVault.setRecipient, (RevShareLibrary.FEE_SPLITTER)) ); _depositCall( - _portal, vaults[i], RevShareGasLimits.SETTERS_GAS_LIMIT, abi.encodeCall(IFeeVault.setMinWithdrawalAmount, (0)) + _portal, vaults[i], RevShareLibrary.SETTERS_GAS_LIMIT, abi.encodeCall(IFeeVault.setMinWithdrawalAmount, (0)) ); _depositCall( - _portal, vaults[i], RevShareGasLimits.SETTERS_GAS_LIMIT, abi.encodeCall(IFeeVault.setWithdrawalNetwork, (IFeeVault.WithdrawalNetwork.L2)) + _portal, vaults[i], RevShareLibrary.SETTERS_GAS_LIMIT, abi.encodeCall(IFeeVault.setWithdrawalNetwork, (IFeeVault.WithdrawalNetwork.L2)) ); } } @@ -185,24 +183,24 @@ contract RevShareContractsUpgrader is RevSharePredeploys { /// @notice Upgrades all 4 vaults with RevShare configuration (recipient=FeeSplitter, minWithdrawal=0, network=L2). /// @param _portal The OptimismPortal2 address for the target L2 function _upgradeVaultsWithRevShareConfig(address _portal) private { - address[4] memory vaultProxies = [OPERATOR_FEE_VAULT, SEQUENCER_FEE_WALLET, BASE_FEE_VAULT, L1_FEE_VAULT]; + address[4] memory vaultProxies = [RevShareLibrary.OPERATOR_FEE_VAULT, RevShareLibrary.SEQUENCER_FEE_WALLET, RevShareLibrary.BASE_FEE_VAULT, RevShareLibrary.L1_FEE_VAULT]; bytes[4] memory creationCodes = [ - RevShareCodeRepo.operatorFeeVaultCreationCode, - RevShareCodeRepo.sequencerFeeVaultCreationCode, - RevShareCodeRepo.baseFeeVaultCreationCode, - RevShareCodeRepo.l1FeeVaultCreationCode + RevShareLibrary.operatorFeeVaultCreationCode, + RevShareLibrary.sequencerFeeVaultCreationCode, + RevShareLibrary.baseFeeVaultCreationCode, + RevShareLibrary.l1FeeVaultCreationCode ]; string[4] memory vaultNames = ["OperatorFeeVault", "SequencerFeeVault", "BaseFeeVault", "L1FeeVault"]; for (uint256 i; i < vaultProxies.length; i++) { bytes32 salt = _getSalt(vaultNames[i]); - address impl = Utils.getCreate2Address(salt, creationCodes[i], CREATE2_DEPLOYER); + address impl = Utils.getCreate2Address(salt, creationCodes[i], RevShareLibrary.CREATE2_DEPLOYER); - _depositCreate2(_portal, RevShareGasLimits.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, salt, creationCodes[i]); + _depositCreate2(_portal, RevShareLibrary.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, salt, creationCodes[i]); _depositCall( _portal, - address(PROXY_ADMIN), - RevShareGasLimits.UPGRADE_GAS_LIMIT, + address(RevShareLibrary.PROXY_ADMIN), + RevShareLibrary.UPGRADE_GAS_LIMIT, abi.encodeCall( IProxyAdmin.upgradeAndCall, ( @@ -210,7 +208,7 @@ contract RevShareContractsUpgrader is RevSharePredeploys { impl, abi.encodeCall( IFeeVault.initialize, - (FEE_SPLITTER, 0, IFeeVault.WithdrawalNetwork.L2) // recipient=FeeSplitter, minWithdrawal=0, network=L2 + (RevShareLibrary.FEE_SPLITTER, 0, IFeeVault.WithdrawalNetwork.L2) // recipient=FeeSplitter, minWithdrawal=0, network=L2 ) ) ) @@ -225,7 +223,7 @@ contract RevShareContractsUpgrader is RevSharePredeploys { /// @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(CREATE2_DEPLOYER), + address(RevShareLibrary.CREATE2_DEPLOYER), 0, _gasLimit, false, diff --git a/src/libraries/RevShareCodeRepo.sol b/src/libraries/RevShareCodeRepo.sol deleted file mode 100644 index a7a14583ca..0000000000 --- a/src/libraries/RevShareCodeRepo.sol +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.15; - -/// @notice Library for storing the creation code for the revenue share contracts. -library RevShareCodeRepo { - /// @notice The creation code for each fee vault, fee splitter, l1 withdrawer, FeesDepositor and sc rev share calculator. - /// Obtained from https://github.com/defi-wonderland/optimism at commit 989afa818dfee3ee1fba715584c2f7e8663268f8 - bytes public constant operatorFeeVaultCreationCode = - hex"6080604052348015600e575f80fd5b5060156019565b60c9565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff161560685760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b039081161460c65780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b610eb9806100d65f395ff3fe6080604052600436106100d1575f3560e01c806382356d8a1161007c57806385b5b14d1161005757806385b5b14d14610276578063b49dc74114610295578063d0e12f90146102b4578063d3e5792b146102e3575f80fd5b806382356d8a1461020f5780638312f1491461024d57806384411d6514610262575f80fd5b80633ccfd60b116100ac5780633ccfd60b1461016c57806354fd4d501461018e57806366d003ac146101e3575f80fd5b80630d9019e1146100dc578063307f29621461012c5780633bbed4a01461014d575f80fd5b366100d857005b5f80fd5b3480156100e7575f80fd5b5060025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b348015610137575f80fd5b5061014b610146366004610c86565b6102f7565b005b348015610158575f80fd5b5061014b610167366004610cc3565b61047a565b348015610177575f80fd5b506101806105de565b604051908152602001610123565b348015610199575f80fd5b506101d66040518060400160405280600581526020017f312e312e3000000000000000000000000000000000000000000000000000000081525081565b6040516101239190610cde565b3480156101ee575f80fd5b506002546101029073ffffffffffffffffffffffffffffffffffffffff1681565b34801561021a575f80fd5b506002546102409074010000000000000000000000000000000000000000900460ff1681565b6040516101239190610d97565b348015610258575f80fd5b5061018060015481565b34801561026d575f80fd5b506101805f5481565b348015610281575f80fd5b5061014b610290366004610dab565b610918565b3480156102a0575f80fd5b5061014b6102af366004610dc2565b610a3b565b3480156102bf575f80fd5b5060025474010000000000000000000000000000000000000000900460ff16610240565b3480156102ee575f80fd5b50600154610180565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610354573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103789190610dfd565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146103dc576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547401000000000000000000000000000000000000000080820460ff1692849290917fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff9091169083600181111561043857610438610d31565b02179055507ff2ec44eb1c3b3acd547b76333eb2c4b27eee311860c57a9fdb04c95f62398fc8818360405161046e929190610e18565b60405180910390a15050565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104fb9190610dfd565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461055f576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f62e69886a5df0ba8ffcacbfc1388754e7abd9bde24b036354c561f1acd4e4593910161046e565b5f60015447101561069c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f4665655661756c743a207769746864726177616c20616d6f756e74206d75737460448201527f2062652067726561746572207468616e206d696e696d756d207769746864726160648201527f77616c20616d6f756e7400000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b479050805f808282546106af9190610e33565b90915550506002546040805183815273ffffffffffffffffffffffffffffffffffffffff90921660208301523382820152517fc8a211cc64b6ed1b50595a9fcb1932b6d1e5a6e8ef15b60e5b1f988ea9086bba9181900360600190a16002546040517f38e04cbeb8c10f8f568618aa75be0f10b6729b8b4237743b4de20cbcde2839ee9161077491849173ffffffffffffffffffffffffffffffffffffffff811691339174010000000000000000000000000000000000000000900460ff1690610e6b565b60405180910390a1600160025474010000000000000000000000000000000000000000900460ff1660018111156107ad576107ad610d31565b0361086a576002545f906107d79073ffffffffffffffffffffffffffffffffffffffff1683610c4f565b905080610866576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4665655661756c743a206661696c656420746f2073656e642045544820746f2060448201527f4c322066656520726563697069656e74000000000000000000000000000000006064820152608401610693565b5090565b6002546040517fc2b3e5ac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015262061a806024820152606060448201525f60648201527342000000000000000000000000000000000000169063c2b3e5ac9083906084015f604051808303818588803b1580156108fe575f80fd5b505af1158015610910573d5f803e3d5ffd5b505050505090565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610975573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109999190610dfd565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109fd576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180549082905560408051828152602081018490527f895a067c78583e800418fabf3da26a9496aab2ff3429cebdf7fefa642b2e4203910161046e565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f81158015610a855750825b90505f8267ffffffffffffffff166001148015610aa15750303b155b905081158015610aaf575080155b15610ae6576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001660011785558315610b475784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b6002805473ffffffffffffffffffffffffffffffffffffffff8a167fffffffffffffffffffffffff000000000000000000000000000000000000000082168117835560018a81558993927fffffffffffffffffffffff000000000000000000000000000000000000000000169091179074010000000000000000000000000000000000000000908490811115610bdf57610bdf610d31565b02179055508315610c455784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050565b5f610c5b835a84610c62565b9392505050565b5f805f805f858888f1949350505050565b803560028110610c81575f80fd5b919050565b5f60208284031215610c96575f80fd5b610c5b82610c73565b73ffffffffffffffffffffffffffffffffffffffff81168114610cc0575f80fd5b50565b5f60208284031215610cd3575f80fd5b8135610c5b81610c9f565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60028110610d93577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b9052565b60208101610da58284610d5e565b92915050565b5f60208284031215610dbb575f80fd5b5035919050565b5f805f60608486031215610dd4575f80fd5b8335610ddf81610c9f565b925060208401359150610df460408501610c73565b90509250925092565b5f60208284031215610e0d575f80fd5b8151610c5b81610c9f565b60408101610e268285610d5e565b610c5b6020830184610d5e565b80820180821115610da5577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b84815273ffffffffffffffffffffffffffffffffffffffff84811660208301528316604082015260808101610ea36060830184610d5e565b9594505050505056fea164736f6c6343000819000a"; - bytes public constant sequencerFeeVaultCreationCode = - hex"6080604052348015600e575f80fd5b5060156019565b60c9565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff161560685760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b039081161460c65780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b610ec4806100d65f395ff3fe6080604052600436106100dc575f3560e01c80638312f1491161007c578063b49dc74111610057578063b49dc741146102a0578063d0e12f90146102bf578063d3e5792b146102ee578063d4ff9218146100e7575f80fd5b80638312f1491461025857806384411d651461026d57806385b5b14d14610281575f80fd5b80633ccfd60b116100b75780633ccfd60b1461017757806354fd4d501461019957806366d003ac146101ee57806382356d8a1461021a575f80fd5b80630d9019e1146100e7578063307f2962146101375780633bbed4a014610158575f80fd5b366100e357005b5f80fd5b3480156100f2575f80fd5b5060025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b348015610142575f80fd5b50610156610151366004610c91565b610302565b005b348015610163575f80fd5b50610156610172366004610cce565b610485565b348015610182575f80fd5b5061018b6105e9565b60405190815260200161012e565b3480156101a4575f80fd5b506101e16040518060400160405280600581526020017f312e362e3000000000000000000000000000000000000000000000000000000081525081565b60405161012e9190610ce9565b3480156101f9575f80fd5b5060025461010d9073ffffffffffffffffffffffffffffffffffffffff1681565b348015610225575f80fd5b5060025461024b9074010000000000000000000000000000000000000000900460ff1681565b60405161012e9190610da2565b348015610263575f80fd5b5061018b60015481565b348015610278575f80fd5b5061018b5f5481565b34801561028c575f80fd5b5061015661029b366004610db6565b610923565b3480156102ab575f80fd5b506101566102ba366004610dcd565b610a46565b3480156102ca575f80fd5b5060025474010000000000000000000000000000000000000000900460ff1661024b565b3480156102f9575f80fd5b5060015461018b565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561035f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103839190610e08565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146103e7576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547401000000000000000000000000000000000000000080820460ff1692849290917fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff9091169083600181111561044357610443610d3c565b02179055507ff2ec44eb1c3b3acd547b76333eb2c4b27eee311860c57a9fdb04c95f62398fc88183604051610479929190610e23565b60405180910390a15050565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104e2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105069190610e08565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461056a576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f62e69886a5df0ba8ffcacbfc1388754e7abd9bde24b036354c561f1acd4e45939101610479565b5f6001544710156106a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f4665655661756c743a207769746864726177616c20616d6f756e74206d75737460448201527f2062652067726561746572207468616e206d696e696d756d207769746864726160648201527f77616c20616d6f756e7400000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b479050805f808282546106ba9190610e3e565b90915550506002546040805183815273ffffffffffffffffffffffffffffffffffffffff90921660208301523382820152517fc8a211cc64b6ed1b50595a9fcb1932b6d1e5a6e8ef15b60e5b1f988ea9086bba9181900360600190a16002546040517f38e04cbeb8c10f8f568618aa75be0f10b6729b8b4237743b4de20cbcde2839ee9161077f91849173ffffffffffffffffffffffffffffffffffffffff811691339174010000000000000000000000000000000000000000900460ff1690610e76565b60405180910390a1600160025474010000000000000000000000000000000000000000900460ff1660018111156107b8576107b8610d3c565b03610875576002545f906107e29073ffffffffffffffffffffffffffffffffffffffff1683610c5a565b905080610871576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4665655661756c743a206661696c656420746f2073656e642045544820746f2060448201527f4c322066656520726563697069656e7400000000000000000000000000000000606482015260840161069e565b5090565b6002546040517fc2b3e5ac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015262061a806024820152606060448201525f60648201527342000000000000000000000000000000000000169063c2b3e5ac9083906084015f604051808303818588803b158015610909575f80fd5b505af115801561091b573d5f803e3d5ffd5b505050505090565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610980573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109a49190610e08565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610a08576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180549082905560408051828152602081018490527f895a067c78583e800418fabf3da26a9496aab2ff3429cebdf7fefa642b2e42039101610479565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f81158015610a905750825b90505f8267ffffffffffffffff166001148015610aac5750303b155b905081158015610aba575080155b15610af1576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001660011785558315610b525784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b6002805473ffffffffffffffffffffffffffffffffffffffff8a167fffffffffffffffffffffffff000000000000000000000000000000000000000082168117835560018a81558993927fffffffffffffffffffffff000000000000000000000000000000000000000000169091179074010000000000000000000000000000000000000000908490811115610bea57610bea610d3c565b02179055508315610c505784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050565b5f610c66835a84610c6d565b9392505050565b5f805f805f858888f1949350505050565b803560028110610c8c575f80fd5b919050565b5f60208284031215610ca1575f80fd5b610c6682610c7e565b73ffffffffffffffffffffffffffffffffffffffff81168114610ccb575f80fd5b50565b5f60208284031215610cde575f80fd5b8135610c6681610caa565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60028110610d9e577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b9052565b60208101610db08284610d69565b92915050565b5f60208284031215610dc6575f80fd5b5035919050565b5f805f60608486031215610ddf575f80fd5b8335610dea81610caa565b925060208401359150610dff60408501610c7e565b90509250925092565b5f60208284031215610e18575f80fd5b8151610c6681610caa565b60408101610e318285610d69565b610c666020830184610d69565b80820180821115610db0577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b84815273ffffffffffffffffffffffffffffffffffffffff84811660208301528316604082015260808101610eae6060830184610d69565b9594505050505056fea164736f6c6343000819000a"; - bytes public constant baseFeeVaultCreationCode = - hex"6080604052348015600e575f80fd5b5060156019565b60c9565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff161560685760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b039081161460c65780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b610eb9806100d65f395ff3fe6080604052600436106100d1575f3560e01c806382356d8a1161007c57806385b5b14d1161005757806385b5b14d14610276578063b49dc74114610295578063d0e12f90146102b4578063d3e5792b146102e3575f80fd5b806382356d8a1461020f5780638312f1491461024d57806384411d6514610262575f80fd5b80633ccfd60b116100ac5780633ccfd60b1461016c57806354fd4d501461018e57806366d003ac146101e3575f80fd5b80630d9019e1146100dc578063307f29621461012c5780633bbed4a01461014d575f80fd5b366100d857005b5f80fd5b3480156100e7575f80fd5b5060025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b348015610137575f80fd5b5061014b610146366004610c86565b6102f7565b005b348015610158575f80fd5b5061014b610167366004610cc3565b61047a565b348015610177575f80fd5b506101806105de565b604051908152602001610123565b348015610199575f80fd5b506101d66040518060400160405280600581526020017f312e362e3000000000000000000000000000000000000000000000000000000081525081565b6040516101239190610cde565b3480156101ee575f80fd5b506002546101029073ffffffffffffffffffffffffffffffffffffffff1681565b34801561021a575f80fd5b506002546102409074010000000000000000000000000000000000000000900460ff1681565b6040516101239190610d97565b348015610258575f80fd5b5061018060015481565b34801561026d575f80fd5b506101805f5481565b348015610281575f80fd5b5061014b610290366004610dab565b610918565b3480156102a0575f80fd5b5061014b6102af366004610dc2565b610a3b565b3480156102bf575f80fd5b5060025474010000000000000000000000000000000000000000900460ff16610240565b3480156102ee575f80fd5b50600154610180565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610354573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103789190610dfd565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146103dc576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547401000000000000000000000000000000000000000080820460ff1692849290917fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff9091169083600181111561043857610438610d31565b02179055507ff2ec44eb1c3b3acd547b76333eb2c4b27eee311860c57a9fdb04c95f62398fc8818360405161046e929190610e18565b60405180910390a15050565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104fb9190610dfd565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461055f576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f62e69886a5df0ba8ffcacbfc1388754e7abd9bde24b036354c561f1acd4e4593910161046e565b5f60015447101561069c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f4665655661756c743a207769746864726177616c20616d6f756e74206d75737460448201527f2062652067726561746572207468616e206d696e696d756d207769746864726160648201527f77616c20616d6f756e7400000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b479050805f808282546106af9190610e33565b90915550506002546040805183815273ffffffffffffffffffffffffffffffffffffffff90921660208301523382820152517fc8a211cc64b6ed1b50595a9fcb1932b6d1e5a6e8ef15b60e5b1f988ea9086bba9181900360600190a16002546040517f38e04cbeb8c10f8f568618aa75be0f10b6729b8b4237743b4de20cbcde2839ee9161077491849173ffffffffffffffffffffffffffffffffffffffff811691339174010000000000000000000000000000000000000000900460ff1690610e6b565b60405180910390a1600160025474010000000000000000000000000000000000000000900460ff1660018111156107ad576107ad610d31565b0361086a576002545f906107d79073ffffffffffffffffffffffffffffffffffffffff1683610c4f565b905080610866576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4665655661756c743a206661696c656420746f2073656e642045544820746f2060448201527f4c322066656520726563697069656e74000000000000000000000000000000006064820152608401610693565b5090565b6002546040517fc2b3e5ac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015262061a806024820152606060448201525f60648201527342000000000000000000000000000000000000169063c2b3e5ac9083906084015f604051808303818588803b1580156108fe575f80fd5b505af1158015610910573d5f803e3d5ffd5b505050505090565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610975573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109999190610dfd565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109fd576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180549082905560408051828152602081018490527f895a067c78583e800418fabf3da26a9496aab2ff3429cebdf7fefa642b2e4203910161046e565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f81158015610a855750825b90505f8267ffffffffffffffff166001148015610aa15750303b155b905081158015610aaf575080155b15610ae6576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001660011785558315610b475784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b6002805473ffffffffffffffffffffffffffffffffffffffff8a167fffffffffffffffffffffffff000000000000000000000000000000000000000082168117835560018a81558993927fffffffffffffffffffffff000000000000000000000000000000000000000000169091179074010000000000000000000000000000000000000000908490811115610bdf57610bdf610d31565b02179055508315610c455784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050565b5f610c5b835a84610c62565b9392505050565b5f805f805f858888f1949350505050565b803560028110610c81575f80fd5b919050565b5f60208284031215610c96575f80fd5b610c5b82610c73565b73ffffffffffffffffffffffffffffffffffffffff81168114610cc0575f80fd5b50565b5f60208284031215610cd3575f80fd5b8135610c5b81610c9f565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60028110610d93577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b9052565b60208101610da58284610d5e565b92915050565b5f60208284031215610dbb575f80fd5b5035919050565b5f805f60608486031215610dd4575f80fd5b8335610ddf81610c9f565b925060208401359150610df460408501610c73565b90509250925092565b5f60208284031215610e0d575f80fd5b8151610c5b81610c9f565b60408101610e268285610d5e565b610c5b6020830184610d5e565b80820180821115610da5577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b84815273ffffffffffffffffffffffffffffffffffffffff84811660208301528316604082015260808101610ea36060830184610d5e565b9594505050505056fea164736f6c6343000819000a"; - bytes public constant l1FeeVaultCreationCode = - hex"6080604052348015600e575f80fd5b5060156019565b60c9565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff161560685760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b039081161460c65780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b610eb9806100d65f395ff3fe6080604052600436106100d1575f3560e01c806382356d8a1161007c57806385b5b14d1161005757806385b5b14d14610276578063b49dc74114610295578063d0e12f90146102b4578063d3e5792b146102e3575f80fd5b806382356d8a1461020f5780638312f1491461024d57806384411d6514610262575f80fd5b80633ccfd60b116100ac5780633ccfd60b1461016c57806354fd4d501461018e57806366d003ac146101e3575f80fd5b80630d9019e1146100dc578063307f29621461012c5780633bbed4a01461014d575f80fd5b366100d857005b5f80fd5b3480156100e7575f80fd5b5060025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b348015610137575f80fd5b5061014b610146366004610c86565b6102f7565b005b348015610158575f80fd5b5061014b610167366004610cc3565b61047a565b348015610177575f80fd5b506101806105de565b604051908152602001610123565b348015610199575f80fd5b506101d66040518060400160405280600581526020017f312e362e3000000000000000000000000000000000000000000000000000000081525081565b6040516101239190610cde565b3480156101ee575f80fd5b506002546101029073ffffffffffffffffffffffffffffffffffffffff1681565b34801561021a575f80fd5b506002546102409074010000000000000000000000000000000000000000900460ff1681565b6040516101239190610d97565b348015610258575f80fd5b5061018060015481565b34801561026d575f80fd5b506101805f5481565b348015610281575f80fd5b5061014b610290366004610dab565b610918565b3480156102a0575f80fd5b5061014b6102af366004610dc2565b610a3b565b3480156102bf575f80fd5b5060025474010000000000000000000000000000000000000000900460ff16610240565b3480156102ee575f80fd5b50600154610180565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610354573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103789190610dfd565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146103dc576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547401000000000000000000000000000000000000000080820460ff1692849290917fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff9091169083600181111561043857610438610d31565b02179055507ff2ec44eb1c3b3acd547b76333eb2c4b27eee311860c57a9fdb04c95f62398fc8818360405161046e929190610e18565b60405180910390a15050565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104fb9190610dfd565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461055f576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f62e69886a5df0ba8ffcacbfc1388754e7abd9bde24b036354c561f1acd4e4593910161046e565b5f60015447101561069c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f4665655661756c743a207769746864726177616c20616d6f756e74206d75737460448201527f2062652067726561746572207468616e206d696e696d756d207769746864726160648201527f77616c20616d6f756e7400000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b479050805f808282546106af9190610e33565b90915550506002546040805183815273ffffffffffffffffffffffffffffffffffffffff90921660208301523382820152517fc8a211cc64b6ed1b50595a9fcb1932b6d1e5a6e8ef15b60e5b1f988ea9086bba9181900360600190a16002546040517f38e04cbeb8c10f8f568618aa75be0f10b6729b8b4237743b4de20cbcde2839ee9161077491849173ffffffffffffffffffffffffffffffffffffffff811691339174010000000000000000000000000000000000000000900460ff1690610e6b565b60405180910390a1600160025474010000000000000000000000000000000000000000900460ff1660018111156107ad576107ad610d31565b0361086a576002545f906107d79073ffffffffffffffffffffffffffffffffffffffff1683610c4f565b905080610866576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4665655661756c743a206661696c656420746f2073656e642045544820746f2060448201527f4c322066656520726563697069656e74000000000000000000000000000000006064820152608401610693565b5090565b6002546040517fc2b3e5ac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015262061a806024820152606060448201525f60648201527342000000000000000000000000000000000000169063c2b3e5ac9083906084015f604051808303818588803b1580156108fe575f80fd5b505af1158015610910573d5f803e3d5ffd5b505050505090565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610975573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109999190610dfd565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109fd576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180549082905560408051828152602081018490527f895a067c78583e800418fabf3da26a9496aab2ff3429cebdf7fefa642b2e4203910161046e565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f81158015610a855750825b90505f8267ffffffffffffffff166001148015610aa15750303b155b905081158015610aaf575080155b15610ae6576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001660011785558315610b475784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b6002805473ffffffffffffffffffffffffffffffffffffffff8a167fffffffffffffffffffffffff000000000000000000000000000000000000000082168117835560018a81558993927fffffffffffffffffffffff000000000000000000000000000000000000000000169091179074010000000000000000000000000000000000000000908490811115610bdf57610bdf610d31565b02179055508315610c455784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050565b5f610c5b835a84610c62565b9392505050565b5f805f805f858888f1949350505050565b803560028110610c81575f80fd5b919050565b5f60208284031215610c96575f80fd5b610c5b82610c73565b73ffffffffffffffffffffffffffffffffffffffff81168114610cc0575f80fd5b50565b5f60208284031215610cd3575f80fd5b8135610c5b81610c9f565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60028110610d93577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b9052565b60208101610da58284610d5e565b92915050565b5f60208284031215610dbb575f80fd5b5035919050565b5f805f60608486031215610dd4575f80fd5b8335610ddf81610c9f565b925060208401359150610df460408501610c73565b90509250925092565b5f60208284031215610e0d575f80fd5b8151610c5b81610c9f565b60408101610e268285610d5e565b610c5b6020830184610d5e565b80820180821115610da5577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b84815273ffffffffffffffffffffffffffffffffffffffff84811660208301528316604082015260808101610ea36060830184610d5e565b9594505050505056fea164736f6c6343000819000a"; - bytes public constant feeSplitterCreationCode = - hex"6080604052348015600e575f80fd5b5060156019565b60d4565b5f54610100900460ff161560835760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b5f5460ff908116101560d2575f805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b6112f1806100e15f395ff3fe608060405260043610610096575f3560e01c80637dfbd04911610066578063b87ea8d41161004c578063b87ea8d414610313578063c4d66de814610327578063d61a398b14610346575f80fd5b80637dfbd049146102dd5780637fc81bb7146102f4575f80fd5b80630a7617b3146101dd5780630c0544a3146101fe578063394d27311461026057806354fd4d5014610288575f80fd5b366101d9577fe3007e9730850b5618eacb0537bef0cf0f1600267ae8549e472449d77b731e455c6100f3576040517f17617f6100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b337342000000000000000000000000000000000000111480159061012b57503373420000000000000000000000000000000000001914155b801561014b57503373420000000000000000000000000000000000001a14155b801561016b57503373420000000000000000000000000000000000001b14155b156101a2576040517f9dcde10900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405134815233907f2ccfc58c2cef4ee590b5f16be0548cc54afc12e1c66a67b362b7d640fd16bb2d9060200160405180910390a2005b5f80fd5b3480156101e8575f80fd5b506101fc6101f7366004610f4b565b61039c565b005b348015610209575f80fd5b5060015461023a9070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1681565b6040516fffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561026b575f80fd5b5060015461023a906fffffffffffffffffffffffffffffffff1681565b348015610293575f80fd5b506102d06040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516102579190610f66565b3480156102e8575f80fd5b5061023a6301e1338081565b3480156102ff575f80fd5b506101fc61030e366004610fb9565b61055e565b34801561031e575f80fd5b506101fc610706565b348015610332575f80fd5b506101fc610341366004610f4b565b610aea565b348015610351575f80fd5b505f546103779062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610257565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103f9573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061041d9190610fe8565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610481576040517f38bac74200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166104ce576040517f99c6ec0800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f805473ffffffffffffffffffffffffffffffffffffffff838116620100008181027fffffffffffffffffffff0000000000000000000000000000000000000000ffff85161790945560408051949093049091168084526020840191909152917f16417cc372deec0caee5f52e2ad77a5f07b4591fd56b4ff31b6e20f817d4daeb91015b60405180910390a15050565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105bb573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105df9190610fe8565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610643576040517f38bac74200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6301e133806fffffffffffffffffffffffffffffffff82161115610693576040517f30b9f35e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180546fffffffffffffffffffffffffffffffff8381167001000000000000000000000000000000008181028385161790945560408051949093049091168084526020840191909152917f4492086b630ed3846eec0979dd87a71c814ceb1c6dab80ab81e3450b21e4de289101610552565b60015461073b906fffffffffffffffffffffffffffffffff700100000000000000000000000000000000820481169116611030565b6fffffffffffffffffffffffffffffffff16421015610786576040517f1e4a9f3a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffffffffffff0000000000000000000000000000000016426fffffffffffffffffffffffffffffffff161781556107cb90610ce0565b5f6107e9734200000000000000000000000000000000000011610d06565b90505f610809734200000000000000000000000000000000000019610d06565b90505f61082973420000000000000000000000000000000000001a610d06565b90505f61084973420000000000000000000000000000000000001b610d06565b90506108545f610ce0565b5f82826108618688611060565b61086b9190611060565b6108759190611060565b9050805f036108b0576040517fc8972e5200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80546040517f54e7f42d000000000000000000000000000000000000000000000000000000008152600481018890526024810187905260448101859052606481018690526201000090910473ffffffffffffffffffffffffffffffffffffffff16906354e7f42d906084015f60405180830381865afa158015610936573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261097b9190810190611118565b905080515f036109b7576040517f763970d600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f805b8251811015610a6e575f8382815181106109d6576109d66111e7565b60200260200101515f015190505f8483815181106109f6576109f66111e7565b6020026020010151602001519050805f03610a12575050610a66565b5f610a1d8383610f03565b905080610a56576040517fd68d1b1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a608286611060565b94505050505b6001016109ba565b50828114610aa8576040517f9c01eac000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f73f9a13241a1848ec157967f3a85601709353e616f1f2605d818c0f2d21774df8284604051610ad9929190611214565b60405180910390a150505050505050565b5f54610100900460ff1615808015610b0857505f54600160ff909116105b80610b215750303b158015610b2157505f5460ff166001145b610bb1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840160405180910390fd5b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610c0d575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b5f80547fffffffffffffffffffff0000000000000000000000000000000000000000ffff166201000073ffffffffffffffffffffffffffffffffffffffff851602179055600180546fffffffffffffffffffffffffffffffff1672015180000000000000000000000000000000001790558015610cdc575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249890602001610552565b5050565b807fe3007e9730850b5618eacb0537bef0cf0f1600267ae8549e472449d77b731e455d50565b5f60018273ffffffffffffffffffffffffffffffffffffffff166382356d8a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d52573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d7691906112af565b6001811115610d8757610d87611282565b14610dbe576040517fb4726cbe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff166366d003ac6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e1e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e429190610fe8565b73ffffffffffffffffffffffffffffffffffffffff1614610e8f576040517fc3380cef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff16633ccfd60b6040518163ffffffff1660e01b81526004016020604051808303815f875af1158015610ed9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610efd91906112cd565b92915050565b5f610f0f835a84610f16565b9392505050565b5f805f805f858888f1949350505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f48575f80fd5b50565b5f60208284031215610f5b575f80fd5b8135610f0f81610f27565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b5f60208284031215610fc9575f80fd5b81356fffffffffffffffffffffffffffffffff81168114610f0f575f80fd5b5f60208284031215610ff8575f80fd5b8151610f0f81610f27565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b6fffffffffffffffffffffffffffffffff81811683821601908082111561105957611059611003565b5092915050565b80820180821115610efd57610efd611003565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6040805190810167ffffffffffffffff811182821017156110c3576110c3611073565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561111057611110611073565b604052919050565b5f6020808385031215611129575f80fd5b825167ffffffffffffffff80821115611140575f80fd5b818501915085601f830112611153575f80fd5b81518181111561116557611165611073565b611173848260051b016110c9565b818152848101925060069190911b830184019087821115611192575f80fd5b928401925b818410156111dc57604084890312156111ae575f80fd5b6111b66110a0565b84516111c181610f27565b81528486015186820152835260409093019291840191611197565b979650505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b604080825283518282018190525f91906020906060850190828801855b8281101561126c578151805173ffffffffffffffffffffffffffffffffffffffff168552850151858501529285019290840190600101611231565b5050508093505050508260208301529392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b5f602082840312156112bf575f80fd5b815160028110610f0f575f80fd5b5f602082840312156112dd575f80fd5b505191905056fea164736f6c6343000819000a"; - bytes public constant scRevShareCalculatorCreationCode = - hex"6080604052348015600e575f80fd5b50604051610955380380610955833981016040819052602b916074565b5f80546001600160a01b039384166001600160a01b0319918216179091556001805492909316911617905560a0565b80516001600160a01b0381168114606f575f80fd5b919050565b5f80604083850312156084575f80fd5b608b83605a565b9150609760208401605a565b90509250929050565b6108a8806100ad5f395ff3fe608060405234801561000f575f80fd5b506004361061009f575f3560e01c80635b201d83116100725780637b42d6c2116100585780637b42d6c21461019157806396d842be1461019a5780639c662fdd146101b9575f80fd5b80635b201d831461016b578063712d7bb814610189575f80fd5b806329f33ec8146100a35780634b012e9a146100ed57806354e7f42d1461010257806354fd4d5014610122575b5f80fd5b6001546100c39073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6101006100fb3660046106a3565b6101cc565b005b6101156101103660046106c5565b610325565b6040516100e491906106f4565b61015e6040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516100e49190610758565b61017461271081565b60405163ffffffff90911681526020016100e4565b61017460fa81565b6101746105dc81565b5f546100c39073ffffffffffffffffffffffffffffffffffffffff1681565b6101006101c73660046106a3565b610524565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610229573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061024d91906107ab565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146102b1576040517f67102c4c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917fc7b7459ad1ab31862524bf0c4a5e6a8518c60f27607a5c483a58ea27e30c214c9190a35050565b6040805160028082526060828101909352816020015b604080518082019091525f808252602082015281526020019060019003908161033b575050604080518082019091525f805473ffffffffffffffffffffffffffffffffffffffff16825260208201819052825192935090918391906103a2576103a26107c6565b6020026020010181905250604051806040016040528060015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020015f8152508160018151811061040c5761040c6107c6565b60209081029190910101525f82846104248789610820565b61042e9190610820565b6104389190610820565b90505f61271061044960fa84610839565b6104539190610850565b9050805f0361048e576040517f0174e42600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6104998584610888565b90505f6127106104ab6105dc84610839565b6104b59190610850565b90505f8184116104c557816104c7565b835b905080865f815181106104dc576104dc6107c6565b60209081029190910181015101526104f48186610888565b86600181518110610507576105076107c6565b602002602001015160200181815250505050505050949350505050565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610581573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105a591906107ab565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610609576040517f67102c4c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f28c1e0a919cd3b91d6d516417dedc06a2bd7954ad8960315347250b1aee2a4f1905f90a35050565b73ffffffffffffffffffffffffffffffffffffffff811681146106a0575f80fd5b50565b5f602082840312156106b3575f80fd5b81356106be8161067f565b9392505050565b5f805f80608085870312156106d8575f80fd5b5050823594602084013594506040840135936060013592509050565b602080825282518282018190525f919060409081850190868401855b8281101561074b578151805173ffffffffffffffffffffffffffffffffffffffff168552860151868501529284019290850190600101610710565b5091979650505050505050565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b5f602082840312156107bb575f80fd5b81516106be8161067f565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b80820180821115610833576108336107f3565b92915050565b8082028115828204841417610833576108336107f3565b5f82610883577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b81810381811115610833576108336107f356fea164736f6c6343000819000a"; - bytes public constant l1WithdrawerCreationCode = - hex"6080604052348015600e575f80fd5b50604051610908380380610908833981016040819052602b916067565b5f929092556001805463ffffffff909316600160a01b026001600160c01b03199093166001600160a01b039092169190911791909117905560b8565b5f805f606084860312156078575f80fd5b835160208501519093506001600160a01b03811681146095575f80fd5b604085015190925063ffffffff8116811460ad575f80fd5b809150509250925092565b610843806100c55f395ff3fe608060405260043610610071575f3560e01c806366d003ac1161004c57806366d003ac146102995780638312f149146102ea57806385b5b14d1461030c5780639d7955b41461032b575f80fd5b80633bbed4a0146101d7578063500bf72f146101f657806354fd4d5014610244575f80fd5b366101d3576040805134815247602082018190529133917f363f315f930a17d1266b86a20d6dd34b1cfbc5a9db9f13a65d06a689c3a2af8a910160405180910390a25f5481106101d1576001546040517f3dbb202b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152606060248201525f60648201527401000000000000000000000000000000000000000090910463ffffffff16604482015273420000000000000000000000000000000000000790633dbb202b9083906084015f604051808303818588803b158015610169575f80fd5b505af115801561017b573d5f803e3d5ffd5b505060015460405185815273ffffffffffffffffffffffffffffffffffffffff90911693507f6d92f7d3303f995bf21956bb0c51b388bae348eaf45c23debd2cfa3fcd9ec6469250602001905060405180910390a25b005b5f80fd5b3480156101e2575f80fd5b506101d16101f136600461076c565b61034a565b348015610201575f80fd5b5060015461022a9074010000000000000000000000000000000000000000900463ffffffff1681565b60405163ffffffff90911681526020015b60405180910390f35b34801561024f575f80fd5b5061028c6040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b60405161023b919061078e565b3480156102a4575f80fd5b506001546102c59073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161023b565b3480156102f5575f80fd5b506102fe5f5481565b60405190815260200161023b565b348015610317575f80fd5b506101d16103263660046107e1565b6104b6565b348015610336575f80fd5b506101d16103453660046107f8565b6105d8565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103a7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103cb919061081b565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461042f576040517f807b982000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f62e69886a5df0ba8ffcacbfc1388754e7abd9bde24b036354c561f1acd4e459391015b60405180910390a15050565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610513573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610537919061081b565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461059b576040517f807b982000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80549082905560408051828152602081018490527f895a067c78583e800418fabf3da26a9496aab2ff3429cebdf7fefa642b2e420391016104aa565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610635573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610659919061081b565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106bd576040517f807b982000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001805463ffffffff838116740100000000000000000000000000000000000000008181027fffffffffffffffff00000000ffffffffffffffffffffffffffffffffffffffff85161790945560408051949093049091168084526020840191909152917fd00b9b2acb0059a20066ca19b541618141c03305a0a6644d43277758c539b5de91016104aa565b73ffffffffffffffffffffffffffffffffffffffff81168114610769575f80fd5b50565b5f6020828403121561077c575f80fd5b813561078781610748565b9392505050565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b5f602082840312156107f1575f80fd5b5035919050565b5f60208284031215610808575f80fd5b813563ffffffff81168114610787575f80fd5b5f6020828403121561082b575f80fd5b81516107878161074856fea164736f6c6343000819000a"; - bytes public constant feesDepositorCreationCode = - hex"60a060405234801561001057600080fd5b50600160805261001e610023565b6100e3565b600054610100900460ff161561008f5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff90811610156100e1576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b608051610d9161010560003960008181610274015261048e0152610d916000f3fe6080604052600436106100cb5760003560e01c8063645006ca11610074578063a2a956171161004e578063a2a9561714610425578063dad544e014610445578063f68016b71461045a57600080fd5b8063645006ca1461038657806366125607146103c85780637b11936e146103e857600080fd5b80633e47158c116100a55780633e47158c146102fb57806352d84c621461031057806354fd4d501461033057600080fd5b80630de2db4d1461024057806338d38c97146102605780633cb747bf146102a357600080fd5b3661023b576040805134815247602082018190529133917f363f315f930a17d1266b86a20d6dd34b1cfbc5a9db9f13a65d06a689c3a2af8a910160405180910390a26001546bffffffffffffffffffffffff16811061023957600154600080546002546040517f3dbb202b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff6c0100000000000000000000000090950485166004820181905260606024830152606482019490945263ffffffff90911660448201529192620100009091041690633dbb202b9084906084016000604051808303818588803b1580156101ce57600080fd5b505af11580156101e2573d6000803e3d6000fd5b50505050508073ffffffffffffffffffffffffffffffffffffffff167f2acaf92365a0b69fb3570802396f62d51aabccd684036b72c3ce78699425e7ee8360405161022f91815260200190565b60405180910390a2505b005b600080fd5b34801561024c57600080fd5b5061023961025b366004610bde565b61048c565b34801561026c57600080fd5b5060405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020015b60405180910390f35b3480156102af57600080fd5b506000546102d69062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161029a565b34801561030757600080fd5b506102d661069e565b34801561031c57600080fd5b5061023961032b366004610c36565b6108a9565b34801561033c57600080fd5b506103796040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b60405161029a9190610c58565b34801561039257600080fd5b506001546103ab906bffffffffffffffffffffffff1681565b6040516bffffffffffffffffffffffff909116815260200161029a565b3480156103d457600080fd5b506102396103e3366004610ccb565b610928565b3480156103f457600080fd5b506001546102d6906c01000000000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b34801561043157600080fd5b50610239610440366004610ce8565b6109af565b34801561045157600080fd5b506102d6610a2e565b34801561046657600080fd5b506002546104779063ffffffff1681565b60405163ffffffff909116815260200161029a565b7f0000000000000000000000000000000000000000000000000000000000000000600054610100900460ff161580156104cc575060005460ff8083169116105b61055c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660ff831617610100179055610595610aab565b6000805473ffffffffffffffffffffffffffffffffffffffff8681166c01000000000000000000000000026bffffffffffffffffffffffff8916176001556002805463ffffffff87167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000009091161790557fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff9086166201000002167fffffffffffffffffffff000000000000000000000000000000000000000000ff9091161790556040517f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989061068f90839060ff91909116815260200190565b60405180910390a15050505050565b6000806106c97fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b905073ffffffffffffffffffffffffffffffffffffffff8116156106ec57919050565b6040518060400160405280601a81526020017f4f564d5f4c3143726f7373446f6d61696e4d657373656e67657200000000000081525051600261072f9190610d03565b604080513060208201526000918101919091527f4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000000919091179061078a906060015b604051602081830303815290604052805190602001205490565b146107c1576040517f54e433cd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080513060208201526001918101919091526000906107e390606001610770565b905073ffffffffffffffffffffffffffffffffffffffff811615610877578073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561084c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108709190610d67565b9250505090565b6040517f332144db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108b1610b2e565b6002805463ffffffff8381167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000083168117909355604080519190921680825260208201939093527f84858bb3fb3ecf87e268ebef250ef9ad9cd53ef7973ef7a0ec9d89470bb00a8091015b60405180910390a15050565b610930610b2e565b6001805473ffffffffffffffffffffffffffffffffffffffff8381166c010000000000000000000000008181026bffffffffffffffffffffffff85161790945560408051949093049091168084526020840191909152917f158f04d12e0403fdd63fbced694e8f70d3b87d04d8e2dfad526f5fcf6e49bbcf910161091c565b6109b7610b2e565b600180546bffffffffffffffffffffffff8381167fffffffffffffffffffffffffffffffffffffffff00000000000000000000000083168117909355604080519190921680825260208201939093527f132832be4270c0d1573ca543c41517dd443fe9daf5f21a9c74940e6db282e229910161091c565b6000610a3861069e565b73ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aa69190610d67565b905090565b33610ab461069e565b73ffffffffffffffffffffffffffffffffffffffff1614158015610af5575033610adc610a2e565b73ffffffffffffffffffffffffffffffffffffffff1614155b15610b2c576040517fc4050a2600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b33610b37610a2e565b73ffffffffffffffffffffffffffffffffffffffff1614610b2c576040517f7f12c64b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80356bffffffffffffffffffffffff81168114610ba057600080fd5b919050565b73ffffffffffffffffffffffffffffffffffffffff81168114610bc757600080fd5b50565b803563ffffffff81168114610ba057600080fd5b60008060008060808587031215610bf457600080fd5b610bfd85610b84565b93506020850135610c0d81610ba5565b92506040850135610c1d81610ba5565b9150610c2b60608601610bca565b905092959194509250565b600060208284031215610c4857600080fd5b610c5182610bca565b9392505050565b600060208083528351808285015260005b81811015610c8557858101830151858201604001528201610c69565b81811115610c97576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b600060208284031215610cdd57600080fd5b8135610c5181610ba5565b600060208284031215610cfa57600080fd5b610c5182610b84565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615610d62577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b500290565b600060208284031215610d7957600080fd5b8151610c5181610ba556fea164736f6c634300080f000a"; -} diff --git a/src/libraries/RevShareGasLimits.sol b/src/libraries/RevShareGasLimits.sol deleted file mode 100644 index a8c3d248ec..0000000000 --- a/src/libraries/RevShareGasLimits.sol +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.15; - -/// @notice Library for storing the gas limits for the calls done in the Revenue Share templates -library RevShareGasLimits { - /// @notice Based on Tenderly simulations, these are the actual gas costs for each of the L2 operations: - /// - L1Withdrawer deployment: 558,056 - /// - SC Rev Share Calculator deployment: 579,688 - /// - Fee Vaults deployment: ~831,000 - /// - Fee Splitter deployment: 1,121,747 - /// - upgrade: ~48,000 - /// - setters: ~50,000 - /// The gas limits below include a buffer to ensure successful execution. - - /// @notice The gas limit for the SC Rev Share Calculator deployment. - uint64 internal constant SC_REV_SHARE_CALCULATOR_DEPLOYMENT_GAS_LIMIT = 681_986; - - /// @notice The gas limit for the L1 Withdrawer deployment. - uint64 internal constant L1_WITHDRAWER_DEPLOYMENT_GAS_LIMIT = 656_536; - - /// @notice The gas limit for the Fee Vaults deployment. - uint64 internal constant FEE_VAULTS_DEPLOYMENT_GAS_LIMIT = 1_200_000; - - /// @notice The gas limit for the Fee Splitter deployment. - uint64 internal constant FEE_SPLITTER_DEPLOYMENT_GAS_LIMIT = 1_319_702; - - /// @notice The gas limit for the upgrade calls on L2. - uint64 internal constant UPGRADE_GAS_LIMIT = 150_000; - - /// @notice The gas limit for the Fee Vaults deployment. - uint64 internal constant SETTERS_GAS_LIMIT = 50_000; -} diff --git a/src/libraries/RevShareLibrary.sol b/src/libraries/RevShareLibrary.sol new file mode 100644 index 0000000000..5c57d590aa --- /dev/null +++ b/src/libraries/RevShareLibrary.sol @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +/// @notice Unified library for Revenue Share system containing creation code, gas limits, and predeploys. +/// @dev This library combines the functionality of RevShare, RevShare, and RevSharePredeploys. +library RevShareLibrary { + // ============================ + // Creation Code Repository + // ============================ + + /// @notice The creation code for each fee vault, fee splitter, l1 withdrawer, FeesDepositor and sc rev share calculator. + /// Obtained from https://github.com/defi-wonderland/optimism at commit 0f21af947798a94aa50e797c61f576ca18b1334d + bytes public constant operatorFeeVaultCreationCode = + hex"6080604052348015600e575f80fd5b5060156019565b60c9565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff161560685760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b039081161460c65780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b610e8d806100d65f395ff3fe6080604052600436106100d1575f3560e01c806382356d8a1161007c57806385b5b14d1161005757806385b5b14d14610276578063b49dc74114610295578063d0e12f90146102b4578063d3e5792b146102e3575f80fd5b806382356d8a1461020f5780638312f1491461024d57806384411d6514610262575f80fd5b80633ccfd60b116100ac5780633ccfd60b1461016c57806354fd4d501461018e57806366d003ac146101e3575f80fd5b80630d9019e1146100dc578063307f29621461012c5780633bbed4a01461014d575f80fd5b366100d857005b5f80fd5b3480156100e7575f80fd5b5060025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b348015610137575f80fd5b5061014b610146366004610c5a565b6102f7565b005b348015610158575f80fd5b5061014b610167366004610c97565b61047a565b348015610177575f80fd5b506101806105de565b604051908152602001610123565b348015610199575f80fd5b506101d66040518060400160405280600581526020017f312e312e3000000000000000000000000000000000000000000000000000000081525081565b6040516101239190610cb2565b3480156101ee575f80fd5b506002546101029073ffffffffffffffffffffffffffffffffffffffff1681565b34801561021a575f80fd5b506002546102409074010000000000000000000000000000000000000000900460ff1681565b6040516101239190610d6b565b348015610258575f80fd5b5061018060015481565b34801561026d575f80fd5b506101805f5481565b348015610281575f80fd5b5061014b610290366004610d7f565b6108ec565b3480156102a0575f80fd5b5061014b6102af366004610d96565b610a0f565b3480156102bf575f80fd5b5060025474010000000000000000000000000000000000000000900460ff16610240565b3480156102ee575f80fd5b50600154610180565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610354573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103789190610dd1565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146103dc576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547401000000000000000000000000000000000000000080820460ff1692849290917fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff9091169083600181111561043857610438610d05565b02179055507ff2ec44eb1c3b3acd547b76333eb2c4b27eee311860c57a9fdb04c95f62398fc8818360405161046e929190610dec565b60405180910390a15050565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104fb9190610dd1565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461055f576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f62e69886a5df0ba8ffcacbfc1388754e7abd9bde24b036354c561f1acd4e4593910161046e565b5f60015447101561069c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f4665655661756c743a207769746864726177616c20616d6f756e74206d75737460448201527f2062652067726561746572207468616e206d696e696d756d207769746864726160648201527f77616c20616d6f756e7400000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b479050805f808282546106af9190610e07565b90915550506002546040805183815273ffffffffffffffffffffffffffffffffffffffff909216602083018190523383830152905190917fc8a211cc64b6ed1b50595a9fcb1932b6d1e5a6e8ef15b60e5b1f988ea9086bba919081900360600190a16002546040517f38e04cbeb8c10f8f568618aa75be0f10b6729b8b4237743b4de20cbcde2839ee916107649185918591339174010000000000000000000000000000000000000000900460ff1690610e3f565b60405180910390a1600160025474010000000000000000000000000000000000000000900460ff16600181111561079d5761079d610d05565b03610841575f6107ad8284610c23565b90508061083c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4665655661756c743a206661696c656420746f2073656e642045544820746f2060448201527f4c322066656520726563697069656e74000000000000000000000000000000006064820152608401610693565b505090565b6040517fc2b3e5ac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015262061a806024820152606060448201525f60648201527342000000000000000000000000000000000000169063c2b3e5ac9084906084015f604051808303818588803b1580156108d1575f80fd5b505af11580156108e3573d5f803e3d5ffd5b50505050505090565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610949573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061096d9190610dd1565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109d1576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180549082905560408051828152602081018490527f895a067c78583e800418fabf3da26a9496aab2ff3429cebdf7fefa642b2e4203910161046e565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f81158015610a595750825b90505f8267ffffffffffffffff166001148015610a755750303b155b905081158015610a83575080155b15610aba576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001660011785558315610b1b5784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b6002805473ffffffffffffffffffffffffffffffffffffffff8a167fffffffffffffffffffffffff000000000000000000000000000000000000000082168117835560018a81558993927fffffffffffffffffffffff000000000000000000000000000000000000000000169091179074010000000000000000000000000000000000000000908490811115610bb357610bb3610d05565b02179055508315610c195784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050565b5f610c2f835a84610c36565b9392505050565b5f805f805f858888f1949350505050565b803560028110610c55575f80fd5b919050565b5f60208284031215610c6a575f80fd5b610c2f82610c47565b73ffffffffffffffffffffffffffffffffffffffff81168114610c94575f80fd5b50565b5f60208284031215610ca7575f80fd5b8135610c2f81610c73565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60028110610d67577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b9052565b60208101610d798284610d32565b92915050565b5f60208284031215610d8f575f80fd5b5035919050565b5f805f60608486031215610da8575f80fd5b8335610db381610c73565b925060208401359150610dc860408501610c47565b90509250925092565b5f60208284031215610de1575f80fd5b8151610c2f81610c73565b60408101610dfa8285610d32565b610c2f6020830184610d32565b80820180821115610d79577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b84815273ffffffffffffffffffffffffffffffffffffffff84811660208301528316604082015260808101610e776060830184610d32565b9594505050505056fea164736f6c6343000819000a"; + bytes public constant sequencerFeeVaultCreationCode = + hex"6080604052348015600e575f80fd5b5060156019565b60c9565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff161560685760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b039081161460c65780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b610e98806100d65f395ff3fe6080604052600436106100dc575f3560e01c80638312f1491161007c578063b49dc74111610057578063b49dc741146102a0578063d0e12f90146102bf578063d3e5792b146102ee578063d4ff9218146100e7575f80fd5b80638312f1491461025857806384411d651461026d57806385b5b14d14610281575f80fd5b80633ccfd60b116100b75780633ccfd60b1461017757806354fd4d501461019957806366d003ac146101ee57806382356d8a1461021a575f80fd5b80630d9019e1146100e7578063307f2962146101375780633bbed4a014610158575f80fd5b366100e357005b5f80fd5b3480156100f2575f80fd5b5060025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b348015610142575f80fd5b50610156610151366004610c65565b610302565b005b348015610163575f80fd5b50610156610172366004610ca2565b610485565b348015610182575f80fd5b5061018b6105e9565b60405190815260200161012e565b3480156101a4575f80fd5b506101e16040518060400160405280600581526020017f312e362e3000000000000000000000000000000000000000000000000000000081525081565b60405161012e9190610cbd565b3480156101f9575f80fd5b5060025461010d9073ffffffffffffffffffffffffffffffffffffffff1681565b348015610225575f80fd5b5060025461024b9074010000000000000000000000000000000000000000900460ff1681565b60405161012e9190610d76565b348015610263575f80fd5b5061018b60015481565b348015610278575f80fd5b5061018b5f5481565b34801561028c575f80fd5b5061015661029b366004610d8a565b6108f7565b3480156102ab575f80fd5b506101566102ba366004610da1565b610a1a565b3480156102ca575f80fd5b5060025474010000000000000000000000000000000000000000900460ff1661024b565b3480156102f9575f80fd5b5060015461018b565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561035f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103839190610ddc565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146103e7576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547401000000000000000000000000000000000000000080820460ff1692849290917fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff9091169083600181111561044357610443610d10565b02179055507ff2ec44eb1c3b3acd547b76333eb2c4b27eee311860c57a9fdb04c95f62398fc88183604051610479929190610df7565b60405180910390a15050565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104e2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105069190610ddc565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461056a576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f62e69886a5df0ba8ffcacbfc1388754e7abd9bde24b036354c561f1acd4e45939101610479565b5f6001544710156106a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f4665655661756c743a207769746864726177616c20616d6f756e74206d75737460448201527f2062652067726561746572207468616e206d696e696d756d207769746864726160648201527f77616c20616d6f756e7400000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b479050805f808282546106ba9190610e12565b90915550506002546040805183815273ffffffffffffffffffffffffffffffffffffffff909216602083018190523383830152905190917fc8a211cc64b6ed1b50595a9fcb1932b6d1e5a6e8ef15b60e5b1f988ea9086bba919081900360600190a16002546040517f38e04cbeb8c10f8f568618aa75be0f10b6729b8b4237743b4de20cbcde2839ee9161076f9185918591339174010000000000000000000000000000000000000000900460ff1690610e4a565b60405180910390a1600160025474010000000000000000000000000000000000000000900460ff1660018111156107a8576107a8610d10565b0361084c575f6107b88284610c2e565b905080610847576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4665655661756c743a206661696c656420746f2073656e642045544820746f2060448201527f4c322066656520726563697069656e7400000000000000000000000000000000606482015260840161069e565b505090565b6040517fc2b3e5ac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015262061a806024820152606060448201525f60648201527342000000000000000000000000000000000000169063c2b3e5ac9084906084015f604051808303818588803b1580156108dc575f80fd5b505af11580156108ee573d5f803e3d5ffd5b50505050505090565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610954573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109789190610ddc565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109dc576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180549082905560408051828152602081018490527f895a067c78583e800418fabf3da26a9496aab2ff3429cebdf7fefa642b2e42039101610479565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f81158015610a645750825b90505f8267ffffffffffffffff166001148015610a805750303b155b905081158015610a8e575080155b15610ac5576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001660011785558315610b265784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b6002805473ffffffffffffffffffffffffffffffffffffffff8a167fffffffffffffffffffffffff000000000000000000000000000000000000000082168117835560018a81558993927fffffffffffffffffffffff000000000000000000000000000000000000000000169091179074010000000000000000000000000000000000000000908490811115610bbe57610bbe610d10565b02179055508315610c245784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050565b5f610c3a835a84610c41565b9392505050565b5f805f805f858888f1949350505050565b803560028110610c60575f80fd5b919050565b5f60208284031215610c75575f80fd5b610c3a82610c52565b73ffffffffffffffffffffffffffffffffffffffff81168114610c9f575f80fd5b50565b5f60208284031215610cb2575f80fd5b8135610c3a81610c7e565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60028110610d72577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b9052565b60208101610d848284610d3d565b92915050565b5f60208284031215610d9a575f80fd5b5035919050565b5f805f60608486031215610db3575f80fd5b8335610dbe81610c7e565b925060208401359150610dd360408501610c52565b90509250925092565b5f60208284031215610dec575f80fd5b8151610c3a81610c7e565b60408101610e058285610d3d565b610c3a6020830184610d3d565b80820180821115610d84577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b84815273ffffffffffffffffffffffffffffffffffffffff84811660208301528316604082015260808101610e826060830184610d3d565b9594505050505056fea164736f6c6343000819000a"; + bytes public constant baseFeeVaultCreationCode = + hex"6080604052348015600e575f80fd5b5060156019565b60c9565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff161560685760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b039081161460c65780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b610e8d806100d65f395ff3fe6080604052600436106100d1575f3560e01c806382356d8a1161007c57806385b5b14d1161005757806385b5b14d14610276578063b49dc74114610295578063d0e12f90146102b4578063d3e5792b146102e3575f80fd5b806382356d8a1461020f5780638312f1491461024d57806384411d6514610262575f80fd5b80633ccfd60b116100ac5780633ccfd60b1461016c57806354fd4d501461018e57806366d003ac146101e3575f80fd5b80630d9019e1146100dc578063307f29621461012c5780633bbed4a01461014d575f80fd5b366100d857005b5f80fd5b3480156100e7575f80fd5b5060025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b348015610137575f80fd5b5061014b610146366004610c5a565b6102f7565b005b348015610158575f80fd5b5061014b610167366004610c97565b61047a565b348015610177575f80fd5b506101806105de565b604051908152602001610123565b348015610199575f80fd5b506101d66040518060400160405280600581526020017f312e362e3000000000000000000000000000000000000000000000000000000081525081565b6040516101239190610cb2565b3480156101ee575f80fd5b506002546101029073ffffffffffffffffffffffffffffffffffffffff1681565b34801561021a575f80fd5b506002546102409074010000000000000000000000000000000000000000900460ff1681565b6040516101239190610d6b565b348015610258575f80fd5b5061018060015481565b34801561026d575f80fd5b506101805f5481565b348015610281575f80fd5b5061014b610290366004610d7f565b6108ec565b3480156102a0575f80fd5b5061014b6102af366004610d96565b610a0f565b3480156102bf575f80fd5b5060025474010000000000000000000000000000000000000000900460ff16610240565b3480156102ee575f80fd5b50600154610180565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610354573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103789190610dd1565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146103dc576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547401000000000000000000000000000000000000000080820460ff1692849290917fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff9091169083600181111561043857610438610d05565b02179055507ff2ec44eb1c3b3acd547b76333eb2c4b27eee311860c57a9fdb04c95f62398fc8818360405161046e929190610dec565b60405180910390a15050565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104fb9190610dd1565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461055f576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f62e69886a5df0ba8ffcacbfc1388754e7abd9bde24b036354c561f1acd4e4593910161046e565b5f60015447101561069c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f4665655661756c743a207769746864726177616c20616d6f756e74206d75737460448201527f2062652067726561746572207468616e206d696e696d756d207769746864726160648201527f77616c20616d6f756e7400000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b479050805f808282546106af9190610e07565b90915550506002546040805183815273ffffffffffffffffffffffffffffffffffffffff909216602083018190523383830152905190917fc8a211cc64b6ed1b50595a9fcb1932b6d1e5a6e8ef15b60e5b1f988ea9086bba919081900360600190a16002546040517f38e04cbeb8c10f8f568618aa75be0f10b6729b8b4237743b4de20cbcde2839ee916107649185918591339174010000000000000000000000000000000000000000900460ff1690610e3f565b60405180910390a1600160025474010000000000000000000000000000000000000000900460ff16600181111561079d5761079d610d05565b03610841575f6107ad8284610c23565b90508061083c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4665655661756c743a206661696c656420746f2073656e642045544820746f2060448201527f4c322066656520726563697069656e74000000000000000000000000000000006064820152608401610693565b505090565b6040517fc2b3e5ac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015262061a806024820152606060448201525f60648201527342000000000000000000000000000000000000169063c2b3e5ac9084906084015f604051808303818588803b1580156108d1575f80fd5b505af11580156108e3573d5f803e3d5ffd5b50505050505090565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610949573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061096d9190610dd1565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109d1576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180549082905560408051828152602081018490527f895a067c78583e800418fabf3da26a9496aab2ff3429cebdf7fefa642b2e4203910161046e565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f81158015610a595750825b90505f8267ffffffffffffffff166001148015610a755750303b155b905081158015610a83575080155b15610aba576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001660011785558315610b1b5784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b6002805473ffffffffffffffffffffffffffffffffffffffff8a167fffffffffffffffffffffffff000000000000000000000000000000000000000082168117835560018a81558993927fffffffffffffffffffffff000000000000000000000000000000000000000000169091179074010000000000000000000000000000000000000000908490811115610bb357610bb3610d05565b02179055508315610c195784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050565b5f610c2f835a84610c36565b9392505050565b5f805f805f858888f1949350505050565b803560028110610c55575f80fd5b919050565b5f60208284031215610c6a575f80fd5b610c2f82610c47565b73ffffffffffffffffffffffffffffffffffffffff81168114610c94575f80fd5b50565b5f60208284031215610ca7575f80fd5b8135610c2f81610c73565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60028110610d67577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b9052565b60208101610d798284610d32565b92915050565b5f60208284031215610d8f575f80fd5b5035919050565b5f805f60608486031215610da8575f80fd5b8335610db381610c73565b925060208401359150610dc860408501610c47565b90509250925092565b5f60208284031215610de1575f80fd5b8151610c2f81610c73565b60408101610dfa8285610d32565b610c2f6020830184610d32565b80820180821115610d79577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b84815273ffffffffffffffffffffffffffffffffffffffff84811660208301528316604082015260808101610e776060830184610d32565b9594505050505056fea164736f6c6343000819000a"; + bytes public constant l1FeeVaultCreationCode = + hex"6080604052348015600e575f80fd5b5060156019565b60c9565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff161560685760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b039081161460c65780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b610e8d806100d65f395ff3fe6080604052600436106100d1575f3560e01c806382356d8a1161007c57806385b5b14d1161005757806385b5b14d14610276578063b49dc74114610295578063d0e12f90146102b4578063d3e5792b146102e3575f80fd5b806382356d8a1461020f5780638312f1491461024d57806384411d6514610262575f80fd5b80633ccfd60b116100ac5780633ccfd60b1461016c57806354fd4d501461018e57806366d003ac146101e3575f80fd5b80630d9019e1146100dc578063307f29621461012c5780633bbed4a01461014d575f80fd5b366100d857005b5f80fd5b3480156100e7575f80fd5b5060025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b348015610137575f80fd5b5061014b610146366004610c5a565b6102f7565b005b348015610158575f80fd5b5061014b610167366004610c97565b61047a565b348015610177575f80fd5b506101806105de565b604051908152602001610123565b348015610199575f80fd5b506101d66040518060400160405280600581526020017f312e362e3000000000000000000000000000000000000000000000000000000081525081565b6040516101239190610cb2565b3480156101ee575f80fd5b506002546101029073ffffffffffffffffffffffffffffffffffffffff1681565b34801561021a575f80fd5b506002546102409074010000000000000000000000000000000000000000900460ff1681565b6040516101239190610d6b565b348015610258575f80fd5b5061018060015481565b34801561026d575f80fd5b506101805f5481565b348015610281575f80fd5b5061014b610290366004610d7f565b6108ec565b3480156102a0575f80fd5b5061014b6102af366004610d96565b610a0f565b3480156102bf575f80fd5b5060025474010000000000000000000000000000000000000000900460ff16610240565b3480156102ee575f80fd5b50600154610180565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610354573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103789190610dd1565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146103dc576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547401000000000000000000000000000000000000000080820460ff1692849290917fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff9091169083600181111561043857610438610d05565b02179055507ff2ec44eb1c3b3acd547b76333eb2c4b27eee311860c57a9fdb04c95f62398fc8818360405161046e929190610dec565b60405180910390a15050565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104fb9190610dd1565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461055f576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f62e69886a5df0ba8ffcacbfc1388754e7abd9bde24b036354c561f1acd4e4593910161046e565b5f60015447101561069c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f4665655661756c743a207769746864726177616c20616d6f756e74206d75737460448201527f2062652067726561746572207468616e206d696e696d756d207769746864726160648201527f77616c20616d6f756e7400000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b479050805f808282546106af9190610e07565b90915550506002546040805183815273ffffffffffffffffffffffffffffffffffffffff909216602083018190523383830152905190917fc8a211cc64b6ed1b50595a9fcb1932b6d1e5a6e8ef15b60e5b1f988ea9086bba919081900360600190a16002546040517f38e04cbeb8c10f8f568618aa75be0f10b6729b8b4237743b4de20cbcde2839ee916107649185918591339174010000000000000000000000000000000000000000900460ff1690610e3f565b60405180910390a1600160025474010000000000000000000000000000000000000000900460ff16600181111561079d5761079d610d05565b03610841575f6107ad8284610c23565b90508061083c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4665655661756c743a206661696c656420746f2073656e642045544820746f2060448201527f4c322066656520726563697069656e74000000000000000000000000000000006064820152608401610693565b505090565b6040517fc2b3e5ac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015262061a806024820152606060448201525f60648201527342000000000000000000000000000000000000169063c2b3e5ac9084906084015f604051808303818588803b1580156108d1575f80fd5b505af11580156108e3573d5f803e3d5ffd5b50505050505090565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610949573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061096d9190610dd1565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109d1576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180549082905560408051828152602081018490527f895a067c78583e800418fabf3da26a9496aab2ff3429cebdf7fefa642b2e4203910161046e565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f81158015610a595750825b90505f8267ffffffffffffffff166001148015610a755750303b155b905081158015610a83575080155b15610aba576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001660011785558315610b1b5784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b6002805473ffffffffffffffffffffffffffffffffffffffff8a167fffffffffffffffffffffffff000000000000000000000000000000000000000082168117835560018a81558993927fffffffffffffffffffffff000000000000000000000000000000000000000000169091179074010000000000000000000000000000000000000000908490811115610bb357610bb3610d05565b02179055508315610c195784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050565b5f610c2f835a84610c36565b9392505050565b5f805f805f858888f1949350505050565b803560028110610c55575f80fd5b919050565b5f60208284031215610c6a575f80fd5b610c2f82610c47565b73ffffffffffffffffffffffffffffffffffffffff81168114610c94575f80fd5b50565b5f60208284031215610ca7575f80fd5b8135610c2f81610c73565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60028110610d67577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b9052565b60208101610d798284610d32565b92915050565b5f60208284031215610d8f575f80fd5b5035919050565b5f805f60608486031215610da8575f80fd5b8335610db381610c73565b925060208401359150610dc860408501610c47565b90509250925092565b5f60208284031215610de1575f80fd5b8151610c2f81610c73565b60408101610dfa8285610d32565b610c2f6020830184610d32565b80820180821115610d79577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b84815273ffffffffffffffffffffffffffffffffffffffff84811660208301528316604082015260808101610e776060830184610d32565b9594505050505056fea164736f6c6343000819000a"; + bytes public constant feeSplitterCreationCode = + hex"6080604052348015600e575f80fd5b5060156019565b60d4565b5f54610100900460ff161560835760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b5f5460ff908116101560d2575f805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b611308806100e15f395ff3fe608060405260043610610096575f3560e01c80637dfbd04911610066578063b87ea8d41161004c578063b87ea8d414610284578063c4d66de814610298578063d61a398b146102b7575f80fd5b80637dfbd0491461024e5780637fc81bb714610265575f80fd5b80630a7617b31461014e5780630c0544a31461016f578063394d2731146101d157806354fd4d50146101f9575f80fd5b3661014a573373ffffffffffffffffffffffffffffffffffffffff7f21346dddac42cc163a6523eefc19df981df7352c870dc3b0b17a6a92fc6fe8135c161461010b576040517f14885cf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805134815247602082018190529133917f213e72af0d3613bd643cff3059f872c1015e6541624e37872bf95eefbaf220a8910160405180910390a2005b5f80fd5b348015610159575f80fd5b5061016d610168366004610f49565b61030d565b005b34801561017a575f80fd5b506001546101ab9070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1681565b6040516fffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101dc575f80fd5b506001546101ab906fffffffffffffffffffffffffffffffff1681565b348015610204575f80fd5b506102416040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516101c89190610f64565b348015610259575f80fd5b506101ab6301e1338081565b348015610270575f80fd5b5061016d61027f366004610fb7565b6104cf565b34801561028f575f80fd5b5061016d6106c2565b3480156102a3575f80fd5b5061016d6102b2366004610f49565b610a9a565b3480156102c2575f80fd5b505f546102e89062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101c8565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561036a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061038e9190610fe6565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146103f2576040517f38bac74200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff811661043f576040517f99c6ec0800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f805473ffffffffffffffffffffffffffffffffffffffff838116620100008181027fffffffffffffffffffff0000000000000000000000000000000000000000ffff85161790945560408051949093049091168084526020840191909152917f16417cc372deec0caee5f52e2ad77a5f07b4591fd56b4ff31b6e20f817d4daeb91015b60405180910390a15050565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561052c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105509190610fe6565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146105b4576040517f38bac74200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806fffffffffffffffffffffffffffffffff165f036105ff576040517fcf85916100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6301e133806fffffffffffffffffffffffffffffffff8216111561064f576040517f30b9f35e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180546fffffffffffffffffffffffffffffffff8381167001000000000000000000000000000000008181028385161790945560408051949093049091168084526020840191909152917f4492086b630ed3846eec0979dd87a71c814ceb1c6dab80ab81e3450b21e4de2891016104c3565b6001546106f7906fffffffffffffffffffffffffffffffff70010000000000000000000000000000000082048116911661102e565b6fffffffffffffffffffffffffffffffff16421015610742576040517f1e4a9f3a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffffffffffff0000000000000000000000000000000016426fffffffffffffffffffffffffffffffff161790555f61079c734200000000000000000000000000000000000011610c8e565b90505f6107bc734200000000000000000000000000000000000019610c8e565b90505f6107dc73420000000000000000000000000000000000001a610c8e565b90505f6107fc73420000000000000000000000000000000000001b610c8e565b90506108075f610edb565b5f8282610814868861105e565b61081e919061105e565b610828919061105e565b9050805f03610863576040517fc8972e5200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80546040517f54e7f42d000000000000000000000000000000000000000000000000000000008152600481018890526024810187905260448101859052606481018690526201000090910473ffffffffffffffffffffffffffffffffffffffff16906354e7f42d906084015f60405180830381865afa1580156108e9573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261092e919081019061111c565b80519091505f81900361096d576040517f763970d600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f805b82811015610a1d575f84828151811061098b5761098b6111eb565b6020026020010151602001519050805f036109a65750610a15565b5f6109cd8684815181106109bc576109bc6111eb565b60200260200101515f015183610f01565b905080610a06576040517fd68d1b1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a10828561105e565b935050505b600101610970565b50838114610a57576040517f9c01eac000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f73f9a13241a1848ec157967f3a85601709353e616f1f2605d818c0f2d21774df8385604051610a88929190611218565b60405180910390a15050505050505050565b5f54610100900460ff1615808015610ab857505f54600160ff909116105b80610ad15750303b158015610ad157505f5460ff166001145b610b61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840160405180910390fd5b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610bbd575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b5f80547fffffffffffffffffffff0000000000000000000000000000000000000000ffff166201000073ffffffffffffffffffffffffffffffffffffffff85160217905572015180000000000000000000000000000000006fffffffffffffffffffffffffffffffff4216176001558015610c8a575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498906020016104c3565b5050565b5f60018273ffffffffffffffffffffffffffffffffffffffff166382356d8a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610cda573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cfe91906112b3565b6001811115610d0f57610d0f611286565b14610d46576040517fb4726cbe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff166366d003ac6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610da6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610dca9190610fe6565b73ffffffffffffffffffffffffffffffffffffffff1614610e17576040517fc3380cef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b47610e2183610edb565b8273ffffffffffffffffffffffffffffffffffffffff16633ccfd60b6040518163ffffffff1660e01b81526004016020604051808303815f875af1158015610e6b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e8f91906112d1565b91504782610e9d83836112e8565b14610ed4576040517f87c91c5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050919050565b807f21346dddac42cc163a6523eefc19df981df7352c870dc3b0b17a6a92fc6fe8135d50565b5f610f0d835a84610f14565b9392505050565b5f805f805f858888f1949350505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f46575f80fd5b50565b5f60208284031215610f59575f80fd5b8135610f0d81610f25565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b5f60208284031215610fc7575f80fd5b81356fffffffffffffffffffffffffffffffff81168114610f0d575f80fd5b5f60208284031215610ff6575f80fd5b8151610f0d81610f25565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b6fffffffffffffffffffffffffffffffff81811683821601908082111561105757611057611001565b5092915050565b8082018082111561107157611071611001565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6040805190810167ffffffffffffffff811182821017156110c7576110c7611077565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561111457611114611077565b604052919050565b5f602080838503121561112d575f80fd5b825167ffffffffffffffff80821115611144575f80fd5b818501915085601f830112611157575f80fd5b81518181111561116957611169611077565b611177848260051b016110cd565b818152848101925060069190911b830184019087821115611196575f80fd5b928401925b818410156111e057604084890312156111b2575f80fd5b6111ba6110a4565b84516111c581610f25565b8152848601518682015283526040909301929184019161119b565b979650505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b604080825283518282018190525f91906020906060850190828801855b82811015611270578151805173ffffffffffffffffffffffffffffffffffffffff168552850151858501529285019290840190600101611235565b5050508093505050508260208301529392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b5f602082840312156112c3575f80fd5b815160028110610f0d575f80fd5b5f602082840312156112e1575f80fd5b5051919050565b818103818111156110715761107161100156fea164736f6c6343000819000a"; + bytes public constant scRevShareCalculatorCreationCode = + hex"6080604052348015600e575f80fd5b50604051610955380380610955833981016040819052602b916074565b5f80546001600160a01b039384166001600160a01b0319918216179091556001805492909316911617905560a0565b80516001600160a01b0381168114606f575f80fd5b919050565b5f80604083850312156084575f80fd5b608b83605a565b9150609760208401605a565b90509250929050565b6108a8806100ad5f395ff3fe608060405234801561000f575f80fd5b506004361061009f575f3560e01c80635b201d83116100725780637b42d6c2116100585780637b42d6c21461019157806396d842be1461019a5780639c662fdd146101b9575f80fd5b80635b201d831461016b578063712d7bb814610189575f80fd5b806329f33ec8146100a35780634b012e9a146100ed57806354e7f42d1461010257806354fd4d5014610122575b5f80fd5b6001546100c39073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6101006100fb3660046106a3565b6101cc565b005b6101156101103660046106c5565b610325565b6040516100e491906106f4565b61015e6040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516100e49190610758565b61017461271081565b60405163ffffffff90911681526020016100e4565b61017460fa81565b6101746105dc81565b5f546100c39073ffffffffffffffffffffffffffffffffffffffff1681565b6101006101c73660046106a3565b610524565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610229573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061024d91906107ab565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146102b1576040517f67102c4c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917fc7b7459ad1ab31862524bf0c4a5e6a8518c60f27607a5c483a58ea27e30c214c9190a35050565b6040805160028082526060828101909352816020015b604080518082019091525f808252602082015281526020019060019003908161033b575050604080518082019091525f805473ffffffffffffffffffffffffffffffffffffffff16825260208201819052825192935090918391906103a2576103a26107c6565b6020026020010181905250604051806040016040528060015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020015f8152508160018151811061040c5761040c6107c6565b60209081029190910101525f82846104248789610820565b61042e9190610820565b6104389190610820565b90505f61271061044960fa84610839565b6104539190610850565b9050805f0361048e576040517f0174e42600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6104998584610888565b90505f6127106104ab6105dc84610839565b6104b59190610850565b90505f8184116104c557816104c7565b835b905080865f815181106104dc576104dc6107c6565b60209081029190910181015101526104f48186610888565b86600181518110610507576105076107c6565b602002602001015160200181815250505050505050949350505050565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610581573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105a591906107ab565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610609576040517f67102c4c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f28c1e0a919cd3b91d6d516417dedc06a2bd7954ad8960315347250b1aee2a4f1905f90a35050565b73ffffffffffffffffffffffffffffffffffffffff811681146106a0575f80fd5b50565b5f602082840312156106b3575f80fd5b81356106be8161067f565b9392505050565b5f805f80608085870312156106d8575f80fd5b5050823594602084013594506040840135936060013592509050565b602080825282518282018190525f919060409081850190868401855b8281101561074b578151805173ffffffffffffffffffffffffffffffffffffffff168552860151868501529284019290850190600101610710565b5091979650505050505050565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b5f602082840312156107bb575f80fd5b81516106be8161067f565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b80820180821115610833576108336107f3565b92915050565b8082028115828204841417610833576108336107f3565b5f82610883577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b81810381811115610833576108336107f356fea164736f6c6343000819000a"; + bytes public constant l1WithdrawerCreationCode = + hex"6080604052348015600e575f80fd5b50604051610908380380610908833981016040819052602b916067565b5f929092556001805463ffffffff909316600160a01b026001600160c01b03199093166001600160a01b039092169190911791909117905560b8565b5f805f606084860312156078575f80fd5b835160208501519093506001600160a01b03811681146095575f80fd5b604085015190925063ffffffff8116811460ad575f80fd5b809150509250925092565b610843806100c55f395ff3fe608060405260043610610071575f3560e01c806366d003ac1161004c57806366d003ac146102995780638312f149146102ea57806385b5b14d1461030c5780639d7955b41461032b575f80fd5b80633bbed4a0146101d7578063500bf72f146101f657806354fd4d5014610244575f80fd5b366101d3576040805134815247602082018190529133917f363f315f930a17d1266b86a20d6dd34b1cfbc5a9db9f13a65d06a689c3a2af8a910160405180910390a25f5481106101d1576001546040517f3dbb202b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152606060248201525f60648201527401000000000000000000000000000000000000000090910463ffffffff16604482015273420000000000000000000000000000000000000790633dbb202b9083906084015f604051808303818588803b158015610169575f80fd5b505af115801561017b573d5f803e3d5ffd5b505060015460405185815273ffffffffffffffffffffffffffffffffffffffff90911693507f6d92f7d3303f995bf21956bb0c51b388bae348eaf45c23debd2cfa3fcd9ec6469250602001905060405180910390a25b005b5f80fd5b3480156101e2575f80fd5b506101d16101f136600461076c565b61034a565b348015610201575f80fd5b5060015461022a9074010000000000000000000000000000000000000000900463ffffffff1681565b60405163ffffffff90911681526020015b60405180910390f35b34801561024f575f80fd5b5061028c6040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b60405161023b919061078e565b3480156102a4575f80fd5b506001546102c59073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161023b565b3480156102f5575f80fd5b506102fe5f5481565b60405190815260200161023b565b348015610317575f80fd5b506101d16103263660046107e1565b6104b6565b348015610336575f80fd5b506101d16103453660046107f8565b6105d8565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103a7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103cb919061081b565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461042f576040517f807b982000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f62e69886a5df0ba8ffcacbfc1388754e7abd9bde24b036354c561f1acd4e459391015b60405180910390a15050565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610513573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610537919061081b565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461059b576040517f807b982000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80549082905560408051828152602081018490527f895a067c78583e800418fabf3da26a9496aab2ff3429cebdf7fefa642b2e420391016104aa565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610635573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610659919061081b565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106bd576040517f807b982000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001805463ffffffff838116740100000000000000000000000000000000000000008181027fffffffffffffffff00000000ffffffffffffffffffffffffffffffffffffffff85161790945560408051949093049091168084526020840191909152917fd00b9b2acb0059a20066ca19b541618141c03305a0a6644d43277758c539b5de91016104aa565b73ffffffffffffffffffffffffffffffffffffffff81168114610769575f80fd5b50565b5f6020828403121561077c575f80fd5b813561078781610748565b9392505050565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b5f602082840312156107f1575f80fd5b5035919050565b5f60208284031215610808575f80fd5b813563ffffffff81168114610787575f80fd5b5f6020828403121561082b575f80fd5b81516107878161074856fea164736f6c6343000819000a"; + + // ============================ + // Gas Limits + // ============================ + + /// @notice Based on Tenderly simulations, these are the actual gas costs for each of the L2 operations: + /// - L1Withdrawer deployment: 558,056 + /// - SC Rev Share Calculator deployment: 579,688 + /// - Fee Vaults deployment: ~831,000 + /// - Fee Splitter deployment: 1,121,747 + /// - upgrade: ~48,000 + /// - setters: ~50,000 + /// The gas limits below include a buffer to ensure successful execution. + + /// @notice The gas limit for the SC Rev Share Calculator deployment. + uint64 internal constant SC_REV_SHARE_CALCULATOR_DEPLOYMENT_GAS_LIMIT = 681_986; + + /// @notice The gas limit for the L1 Withdrawer deployment. + uint64 internal constant L1_WITHDRAWER_DEPLOYMENT_GAS_LIMIT = 656_536; + + /// @notice The gas limit for the Fee Vaults deployment. + uint64 internal constant FEE_VAULTS_DEPLOYMENT_GAS_LIMIT = 1_200_000; + + /// @notice The gas limit for the Fee Splitter deployment. + uint64 internal constant FEE_SPLITTER_DEPLOYMENT_GAS_LIMIT = 1_319_702; + + /// @notice The gas limit for the upgrade calls on L2. + uint64 internal constant UPGRADE_GAS_LIMIT = 150_000; + + /// @notice The gas limit for the Fee Vaults deployment. + uint64 internal constant SETTERS_GAS_LIMIT = 50_000; + + // ============================ + // Predeploy Addresses + // ============================ + + /// @notice Address of the Create2Deployer Preinstall on L2. + address internal constant CREATE2_DEPLOYER = 0x13b0D85CcB8bf860b6b79AF3029fCA081AE9beF2; + + /// @notice Address of the Operator Fee Vault Predeploy on L2. + address internal constant OPERATOR_FEE_VAULT = 0x420000000000000000000000000000000000001b; + + /// @notice Address of the FeeSplitter Predeploy on L2. + address internal constant FEE_SPLITTER = 0x420000000000000000000000000000000000002B; + + /// @notice Address of the Sequencer Fee Vault Predeploy on L2. + address internal constant SEQUENCER_FEE_WALLET = 0x4200000000000000000000000000000000000011; + + /// @notice Address of the L1 Fee Vault Predeploy on L2. + address internal constant L1_FEE_VAULT = 0x420000000000000000000000000000000000001A; + + /// @notice Address of the Base Fee Vault Predeploy on L2. + address internal constant BASE_FEE_VAULT = 0x4200000000000000000000000000000000000019; + + /// @notice The default recipient for the FeeVault once part of the Revenue Share system. + address public constant FEE_VAULT_RECIPIENT = FEE_SPLITTER; + + /// @notice Address of the ProxyAdmin predeploy on L2. + address internal constant PROXY_ADMIN = 0x4200000000000000000000000000000000000018; +} diff --git a/src/libraries/RevSharePredeploys.sol b/src/libraries/RevSharePredeploys.sol deleted file mode 100644 index 09d66d9cb4..0000000000 --- a/src/libraries/RevSharePredeploys.sol +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.15; - -// TODO: Import `FeeSplitter` and `OperatorFeeVault` from the Optimism contracts library once they are included. -/// @notice Library for storing the predeploys for the Revenue Share templates -abstract contract RevSharePredeploys { - /// @notice Address of the Create2Deployer Preinstall on L2. - address internal constant CREATE2_DEPLOYER = 0x13b0D85CcB8bf860b6b79AF3029fCA081AE9beF2; - /// @notice Address of the Operator Fee Vault Predeploy on L2. - address internal constant OPERATOR_FEE_VAULT = 0x420000000000000000000000000000000000001b; - /// @notice Address of the FeeSplitter Predeploy on L2. - address internal constant FEE_SPLITTER = 0x420000000000000000000000000000000000002B; - /// @notice Address of the Sequencer Fee Vault Predeploy on L2. - address internal constant SEQUENCER_FEE_WALLET = 0x4200000000000000000000000000000000000011; - /// @notice Address of the L1 Fee Vault Predeploy on L2. - address internal constant L1_FEE_VAULT = 0x420000000000000000000000000000000000001A; - /// @notice Address of the Base Fee Vault Predeploy on L2. - address internal constant BASE_FEE_VAULT = 0x4200000000000000000000000000000000000019; - /// @notice The default recipient for the FeeVault once part of the Revenue Share system. - address public constant FEE_VAULT_RECIPIENT = FEE_SPLITTER; - /// @notice Address of the ProxyAdmin predeploy on L2. - address internal constant PROXY_ADMIN = 0x4200000000000000000000000000000000000018; -} diff --git a/src/template/RevenueShareUpgradePath.sol b/src/template/RevenueShareUpgradePath.sol index 60048cf1ce..25c43a355a 100644 --- a/src/template/RevenueShareUpgradePath.sol +++ b/src/template/RevenueShareUpgradePath.sol @@ -7,10 +7,8 @@ import {stdToml} from "lib/forge-std/src/StdToml.sol"; import {SimpleTaskBase} from "src/tasks/types/SimpleTaskBase.sol"; import {Action} from "src/libraries/MultisigTypes.sol"; import {MultisigTaskPrinter} from "src/libraries/MultisigTaskPrinter.sol"; -import {RevShareCodeRepo} from "src/libraries/RevShareCodeRepo.sol"; -import {RevShareGasLimits} from "src/libraries/RevShareGasLimits.sol"; +import {RevShareLibrary} from "src/libraries/RevShareLibrary.sol"; import {Utils} from "src/libraries/Utils.sol"; -import {RevSharePredeploys} from "src/libraries/RevSharePredeploys.sol"; /// @notice Interface for the OptimismPortal2 in L1. This is the main interaction point for the template. interface IOptimismPortal2 { @@ -41,7 +39,7 @@ interface IProxyAdmin { } /// @notice A template contract for chains to upgrade to the Revenue Share v1.0.0 implementation. -contract RevenueShareV100UpgradePath is SimpleTaskBase, RevSharePredeploys { +contract RevenueShareV100UpgradePath is SimpleTaskBase { using LibString for string; using stdToml for string; @@ -163,21 +161,21 @@ contract RevenueShareV100UpgradePath is SimpleTaskBase, RevSharePredeploys { // Calculate addresses and data to deploy L1 Withdrawer bytes memory _l1WithdrawerInitCode = bytes.concat( - RevShareCodeRepo.l1WithdrawerCreationCode, + RevShareLibrary.l1WithdrawerCreationCode, abi.encode(l1WithdrawerMinWithdrawalAmount, l1WithdrawerRecipient, l1WithdrawerGasLimit) ); _l1WithdrawerCalldata = abi.encodeCall(ICreate2Deployer.deploy, (0, _getSalt(saltSeed, "L1Withdrawer"), _l1WithdrawerInitCode)); _l1WithdrawerPrecalculatedAddress = - Utils.getCreate2Address(_getSalt(saltSeed, "L1Withdrawer"), _l1WithdrawerInitCode, CREATE2_DEPLOYER); + Utils.getCreate2Address(_getSalt(saltSeed, "L1Withdrawer"), _l1WithdrawerInitCode, RevShareLibrary.CREATE2_DEPLOYER); // Expected calls for L1 Withdrawer: 1 (deploy) _incrementCallsToPortal( abi.encodeCall( IOptimismPortal2.depositTransaction, ( - address(CREATE2_DEPLOYER), + address(RevShareLibrary.CREATE2_DEPLOYER), 0, - RevShareGasLimits.L1_WITHDRAWER_DEPLOYMENT_GAS_LIMIT, + RevShareLibrary.L1_WITHDRAWER_DEPLOYMENT_GAS_LIMIT, false, _l1WithdrawerCalldata ) @@ -191,7 +189,7 @@ contract RevenueShareV100UpgradePath is SimpleTaskBase, RevSharePredeploys { ); bytes memory _scRevShareCalculatorInitCode = bytes.concat( - RevShareCodeRepo.scRevShareCalculatorCreationCode, + RevShareLibrary.scRevShareCalculatorCreationCode, abi.encode(_l1WithdrawerPrecalculatedAddress, scRevShareCalcChainFeesRecipient) ); _scRevShareCalculatorCalldata = abi.encodeCall( @@ -199,7 +197,7 @@ contract RevenueShareV100UpgradePath is SimpleTaskBase, RevSharePredeploys { ); _scRevShareCalculatorPrecalculatedAddress = Utils.getCreate2Address( - _getSalt(saltSeed, "SCRevShareCalculator"), _scRevShareCalculatorInitCode, CREATE2_DEPLOYER + _getSalt(saltSeed, "SCRevShareCalculator"), _scRevShareCalculatorInitCode, RevShareLibrary.CREATE2_DEPLOYER ); // Expected calls for SC Rev Shares Calculator: 1 (deploy) @@ -207,9 +205,9 @@ contract RevenueShareV100UpgradePath is SimpleTaskBase, RevSharePredeploys { abi.encodeCall( IOptimismPortal2.depositTransaction, ( - address(CREATE2_DEPLOYER), + address(RevShareLibrary.CREATE2_DEPLOYER), 0, - RevShareGasLimits.SC_REV_SHARE_CALCULATOR_DEPLOYMENT_GAS_LIMIT, + RevShareLibrary.SC_REV_SHARE_CALCULATOR_DEPLOYMENT_GAS_LIMIT, false, _scRevShareCalculatorCalldata ) @@ -224,9 +222,9 @@ contract RevenueShareV100UpgradePath is SimpleTaskBase, RevSharePredeploys { // Calculate addresses and data to deploy vaults // Calculate addresses and data to deploy OperatorFeeVault - bytes memory _operatorFeeVaultInitCode = RevShareCodeRepo.operatorFeeVaultCreationCode; + bytes memory _operatorFeeVaultInitCode = RevShareLibrary.operatorFeeVaultCreationCode; _operatorFeeVaultPrecalculatedAddress = - Utils.getCreate2Address(_getSalt(saltSeed, "OperatorFeeVault"), _operatorFeeVaultInitCode, CREATE2_DEPLOYER); + Utils.getCreate2Address(_getSalt(saltSeed, "OperatorFeeVault"), _operatorFeeVaultInitCode, RevShareLibrary.CREATE2_DEPLOYER); _operatorFeeVaultCalldata = abi.encodeCall( ICreate2Deployer.deploy, (0, _getSalt(saltSeed, "OperatorFeeVault"), _operatorFeeVaultInitCode) @@ -236,9 +234,9 @@ contract RevenueShareV100UpgradePath is SimpleTaskBase, RevSharePredeploys { abi.encodeCall( IOptimismPortal2.depositTransaction, ( - address(CREATE2_DEPLOYER), + address(RevShareLibrary.CREATE2_DEPLOYER), 0, - RevShareGasLimits.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, + RevShareLibrary.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, false, _operatorFeeVaultCalldata ) @@ -248,19 +246,19 @@ contract RevenueShareV100UpgradePath is SimpleTaskBase, RevSharePredeploys { abi.encodeCall( IOptimismPortal2.depositTransaction, ( - address(PROXY_ADMIN), + address(RevShareLibrary.PROXY_ADMIN), 0, - RevShareGasLimits.UPGRADE_GAS_LIMIT, + RevShareLibrary.UPGRADE_GAS_LIMIT, false, abi.encodeCall( IProxyAdmin.upgradeAndCall, ( - payable(OPERATOR_FEE_VAULT), + payable(RevShareLibrary.OPERATOR_FEE_VAULT), address(_operatorFeeVaultPrecalculatedAddress), abi.encodeCall( IFeeVault.initialize, ( - FEE_VAULT_RECIPIENT, + RevShareLibrary.FEE_VAULT_RECIPIENT, FEE_VAULT_MIN_WITHDRAWAL_AMOUNT, FEE_VAULT_WITHDRAWAL_NETWORK ) @@ -272,9 +270,9 @@ contract RevenueShareV100UpgradePath is SimpleTaskBase, RevSharePredeploys { ); // Calculate addresses and data to deploy SequencerFeeVault - bytes memory _sequencerFeeVaultInitCode = RevShareCodeRepo.sequencerFeeVaultCreationCode; + bytes memory _sequencerFeeVaultInitCode = RevShareLibrary.sequencerFeeVaultCreationCode; _sequencerFeeVaultPrecalculatedAddress = Utils.getCreate2Address( - _getSalt(saltSeed, "SequencerFeeVault"), _sequencerFeeVaultInitCode, CREATE2_DEPLOYER + _getSalt(saltSeed, "SequencerFeeVault"), _sequencerFeeVaultInitCode, RevShareLibrary.CREATE2_DEPLOYER ); _sequencerFeeVaultCalldata = abi.encodeCall( ICreate2Deployer.deploy, (0, _getSalt(saltSeed, "SequencerFeeVault"), _sequencerFeeVaultInitCode) @@ -285,9 +283,9 @@ contract RevenueShareV100UpgradePath is SimpleTaskBase, RevSharePredeploys { abi.encodeCall( IOptimismPortal2.depositTransaction, ( - address(CREATE2_DEPLOYER), + address(RevShareLibrary.CREATE2_DEPLOYER), 0, - RevShareGasLimits.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, + RevShareLibrary.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, false, _sequencerFeeVaultCalldata ) @@ -297,19 +295,19 @@ contract RevenueShareV100UpgradePath is SimpleTaskBase, RevSharePredeploys { abi.encodeCall( IOptimismPortal2.depositTransaction, ( - address(PROXY_ADMIN), + address(RevShareLibrary.PROXY_ADMIN), 0, - RevShareGasLimits.UPGRADE_GAS_LIMIT, + RevShareLibrary.UPGRADE_GAS_LIMIT, false, abi.encodeCall( IProxyAdmin.upgradeAndCall, ( - payable(SEQUENCER_FEE_WALLET), + payable(RevShareLibrary.SEQUENCER_FEE_WALLET), address(_sequencerFeeVaultPrecalculatedAddress), abi.encodeCall( IFeeVault.initialize, ( - FEE_VAULT_RECIPIENT, + RevShareLibrary.FEE_VAULT_RECIPIENT, FEE_VAULT_MIN_WITHDRAWAL_AMOUNT, FEE_VAULT_WITHDRAWAL_NETWORK ) @@ -321,9 +319,9 @@ contract RevenueShareV100UpgradePath is SimpleTaskBase, RevSharePredeploys { ); // Calculate addresses and data to deploy BaseFeeVault - bytes memory _baseFeeVaultInitCode = RevShareCodeRepo.baseFeeVaultCreationCode; + bytes memory _baseFeeVaultInitCode = RevShareLibrary.baseFeeVaultCreationCode; _baseFeeVaultPrecalculatedAddress = - Utils.getCreate2Address(_getSalt(saltSeed, "BaseFeeVault"), _baseFeeVaultInitCode, CREATE2_DEPLOYER); + Utils.getCreate2Address(_getSalt(saltSeed, "BaseFeeVault"), _baseFeeVaultInitCode, RevShareLibrary.CREATE2_DEPLOYER); _baseFeeVaultCalldata = abi.encodeCall(ICreate2Deployer.deploy, (0, _getSalt(saltSeed, "BaseFeeVault"), _baseFeeVaultInitCode)); @@ -332,9 +330,9 @@ contract RevenueShareV100UpgradePath is SimpleTaskBase, RevSharePredeploys { abi.encodeCall( IOptimismPortal2.depositTransaction, ( - address(CREATE2_DEPLOYER), + address(RevShareLibrary.CREATE2_DEPLOYER), 0, - RevShareGasLimits.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, + RevShareLibrary.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, false, _baseFeeVaultCalldata ) @@ -344,18 +342,18 @@ contract RevenueShareV100UpgradePath is SimpleTaskBase, RevSharePredeploys { abi.encodeCall( IOptimismPortal2.depositTransaction, ( - address(PROXY_ADMIN), + address(RevShareLibrary.PROXY_ADMIN), 0, - RevShareGasLimits.UPGRADE_GAS_LIMIT, + RevShareLibrary.UPGRADE_GAS_LIMIT, false, abi.encodeCall( IProxyAdmin.upgradeAndCall, ( - payable(BASE_FEE_VAULT), + payable(RevShareLibrary.BASE_FEE_VAULT), address(_baseFeeVaultPrecalculatedAddress), abi.encodeCall( IFeeVault.initialize, - (FEE_VAULT_RECIPIENT, FEE_VAULT_MIN_WITHDRAWAL_AMOUNT, FEE_VAULT_WITHDRAWAL_NETWORK) + (RevShareLibrary.FEE_VAULT_RECIPIENT, FEE_VAULT_MIN_WITHDRAWAL_AMOUNT, FEE_VAULT_WITHDRAWAL_NETWORK) ) ) ) @@ -364,9 +362,9 @@ contract RevenueShareV100UpgradePath is SimpleTaskBase, RevSharePredeploys { ); // Calculate addresses and data to deploy L1FeeVault - bytes memory _l1FeeVaultInitCode = RevShareCodeRepo.l1FeeVaultCreationCode; + bytes memory _l1FeeVaultInitCode = RevShareLibrary.l1FeeVaultCreationCode; _l1FeeVaultPrecalculatedAddress = - Utils.getCreate2Address(_getSalt(saltSeed, "L1FeeVault"), _l1FeeVaultInitCode, CREATE2_DEPLOYER); + Utils.getCreate2Address(_getSalt(saltSeed, "L1FeeVault"), _l1FeeVaultInitCode, RevShareLibrary.CREATE2_DEPLOYER); _l1FeeVaultCalldata = abi.encodeCall(ICreate2Deployer.deploy, (0, _getSalt(saltSeed, "L1FeeVault"), _l1FeeVaultInitCode)); @@ -375,9 +373,9 @@ contract RevenueShareV100UpgradePath is SimpleTaskBase, RevSharePredeploys { abi.encodeCall( IOptimismPortal2.depositTransaction, ( - address(CREATE2_DEPLOYER), + address(RevShareLibrary.CREATE2_DEPLOYER), 0, - RevShareGasLimits.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, + RevShareLibrary.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, false, _l1FeeVaultCalldata ) @@ -387,18 +385,18 @@ contract RevenueShareV100UpgradePath is SimpleTaskBase, RevSharePredeploys { abi.encodeCall( IOptimismPortal2.depositTransaction, ( - address(PROXY_ADMIN), + address(RevShareLibrary.PROXY_ADMIN), 0, - RevShareGasLimits.UPGRADE_GAS_LIMIT, + RevShareLibrary.UPGRADE_GAS_LIMIT, false, abi.encodeCall( IProxyAdmin.upgradeAndCall, ( - payable(L1_FEE_VAULT), + payable(RevShareLibrary.L1_FEE_VAULT), address(_l1FeeVaultPrecalculatedAddress), abi.encodeCall( IFeeVault.initialize, - (FEE_VAULT_RECIPIENT, FEE_VAULT_MIN_WITHDRAWAL_AMOUNT, FEE_VAULT_WITHDRAWAL_NETWORK) + (RevShareLibrary.FEE_VAULT_RECIPIENT, FEE_VAULT_MIN_WITHDRAWAL_AMOUNT, FEE_VAULT_WITHDRAWAL_NETWORK) ) ) ) @@ -408,10 +406,10 @@ contract RevenueShareV100UpgradePath is SimpleTaskBase, RevSharePredeploys { // Calculate addresses and data to deploy Fee Splitter _feeSplitterCalldata = abi.encodeCall( - ICreate2Deployer.deploy, (0, _getSalt(saltSeed, "FeeSplitter"), RevShareCodeRepo.feeSplitterCreationCode) + ICreate2Deployer.deploy, (0, _getSalt(saltSeed, "FeeSplitter"), RevShareLibrary.feeSplitterCreationCode) ); _feeSplitterPrecalculatedAddress = Utils.getCreate2Address( - _getSalt(saltSeed, "FeeSplitter"), RevShareCodeRepo.feeSplitterCreationCode, CREATE2_DEPLOYER + _getSalt(saltSeed, "FeeSplitter"), RevShareLibrary.feeSplitterCreationCode, RevShareLibrary.CREATE2_DEPLOYER ); // Expected calls for FeeSplitter: 2 (deploy + upgradeAndCall) @@ -419,9 +417,9 @@ contract RevenueShareV100UpgradePath is SimpleTaskBase, RevSharePredeploys { abi.encodeCall( IOptimismPortal2.depositTransaction, ( - address(CREATE2_DEPLOYER), + address(RevShareLibrary.CREATE2_DEPLOYER), 0, - RevShareGasLimits.FEE_SPLITTER_DEPLOYMENT_GAS_LIMIT, + RevShareLibrary.FEE_SPLITTER_DEPLOYMENT_GAS_LIMIT, false, _feeSplitterCalldata ) @@ -431,14 +429,14 @@ contract RevenueShareV100UpgradePath is SimpleTaskBase, RevSharePredeploys { abi.encodeCall( IOptimismPortal2.depositTransaction, ( - address(PROXY_ADMIN), + address(RevShareLibrary.PROXY_ADMIN), 0, - RevShareGasLimits.UPGRADE_GAS_LIMIT, + RevShareLibrary.UPGRADE_GAS_LIMIT, false, abi.encodeCall( IProxyAdmin.upgradeAndCall, ( - payable(FEE_SPLITTER), + payable(RevShareLibrary.FEE_SPLITTER), address(_feeSplitterPrecalculatedAddress), abi.encodeCall(IFeeSplitter.initialize, (_scRevShareCalculatorPrecalculatedAddress)) ) @@ -464,18 +462,18 @@ contract RevenueShareV100UpgradePath is SimpleTaskBase, RevSharePredeploys { if (useDefaultCalculator) { // Deploy L1 Withdrawer IOptimismPortal2(payable(portal)).depositTransaction( - address(CREATE2_DEPLOYER), + address(RevShareLibrary.CREATE2_DEPLOYER), 0, - RevShareGasLimits.L1_WITHDRAWER_DEPLOYMENT_GAS_LIMIT, + RevShareLibrary.L1_WITHDRAWER_DEPLOYMENT_GAS_LIMIT, false, _l1WithdrawerCalldata ); // Deploy SC Rev Share Calculator IOptimismPortal2(payable(portal)).depositTransaction( - address(CREATE2_DEPLOYER), + address(RevShareLibrary.CREATE2_DEPLOYER), 0, - RevShareGasLimits.SC_REV_SHARE_CALCULATOR_DEPLOYMENT_GAS_LIMIT, + RevShareLibrary.SC_REV_SHARE_CALCULATOR_DEPLOYMENT_GAS_LIMIT, false, _scRevShareCalculatorCalldata ); @@ -512,26 +510,26 @@ contract RevenueShareV100UpgradePath is SimpleTaskBase, RevSharePredeploys { // Deploy the fee vaults // Deploy the operator fee vault IOptimismPortal2(payable(portal)).depositTransaction( - address(CREATE2_DEPLOYER), + address(RevShareLibrary.CREATE2_DEPLOYER), 0, - RevShareGasLimits.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, + RevShareLibrary.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, false, _operatorFeeVaultCalldata ); IOptimismPortal2(payable(portal)).depositTransaction( - address(PROXY_ADMIN), + address(RevShareLibrary.PROXY_ADMIN), 0, - RevShareGasLimits.UPGRADE_GAS_LIMIT, + RevShareLibrary.UPGRADE_GAS_LIMIT, false, abi.encodeCall( IProxyAdmin.upgradeAndCall, ( - payable(OPERATOR_FEE_VAULT), + payable(RevShareLibrary.OPERATOR_FEE_VAULT), address(_operatorFeeVaultPrecalculatedAddress), abi.encodeCall( IFeeVault.initialize, ( - FEE_VAULT_RECIPIENT, + RevShareLibrary.FEE_VAULT_RECIPIENT, FEE_VAULT_MIN_WITHDRAWAL_AMOUNT, FEE_VAULT_WITHDRAWAL_NETWORK ) @@ -542,26 +540,26 @@ contract RevenueShareV100UpgradePath is SimpleTaskBase, RevSharePredeploys { // Deploy the sequencer fee vault IOptimismPortal2(payable(portal)).depositTransaction( - address(CREATE2_DEPLOYER), + address(RevShareLibrary.CREATE2_DEPLOYER), 0, - RevShareGasLimits.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, + RevShareLibrary.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, false, _sequencerFeeVaultCalldata ); IOptimismPortal2(payable(portal)).depositTransaction( - address(PROXY_ADMIN), + address(RevShareLibrary.PROXY_ADMIN), 0, - RevShareGasLimits.UPGRADE_GAS_LIMIT, + RevShareLibrary.UPGRADE_GAS_LIMIT, false, abi.encodeCall( IProxyAdmin.upgradeAndCall, ( - payable(SEQUENCER_FEE_WALLET), + payable(RevShareLibrary.SEQUENCER_FEE_WALLET), address(_sequencerFeeVaultPrecalculatedAddress), abi.encodeCall( IFeeVault.initialize, ( - FEE_VAULT_RECIPIENT, + RevShareLibrary.FEE_VAULT_RECIPIENT, FEE_VAULT_MIN_WITHDRAWAL_AMOUNT, FEE_VAULT_WITHDRAWAL_NETWORK ) @@ -572,25 +570,25 @@ contract RevenueShareV100UpgradePath is SimpleTaskBase, RevSharePredeploys { // Deploy the base fee vault IOptimismPortal2(payable(portal)).depositTransaction( - address(CREATE2_DEPLOYER), + address(RevShareLibrary.CREATE2_DEPLOYER), 0, - RevShareGasLimits.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, + RevShareLibrary.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, false, _baseFeeVaultCalldata ); IOptimismPortal2(payable(portal)).depositTransaction( - address(PROXY_ADMIN), + address(RevShareLibrary.PROXY_ADMIN), 0, - RevShareGasLimits.UPGRADE_GAS_LIMIT, + RevShareLibrary.UPGRADE_GAS_LIMIT, false, abi.encodeCall( IProxyAdmin.upgradeAndCall, ( - payable(BASE_FEE_VAULT), + payable(RevShareLibrary.BASE_FEE_VAULT), address(_baseFeeVaultPrecalculatedAddress), abi.encodeCall( IFeeVault.initialize, - (FEE_VAULT_RECIPIENT, FEE_VAULT_MIN_WITHDRAWAL_AMOUNT, FEE_VAULT_WITHDRAWAL_NETWORK) + (RevShareLibrary.FEE_VAULT_RECIPIENT, FEE_VAULT_MIN_WITHDRAWAL_AMOUNT, FEE_VAULT_WITHDRAWAL_NETWORK) ) ) ) @@ -598,21 +596,21 @@ contract RevenueShareV100UpgradePath is SimpleTaskBase, RevSharePredeploys { // Deploy the l1 fee vault IOptimismPortal2(payable(portal)).depositTransaction( - address(CREATE2_DEPLOYER), 0, RevShareGasLimits.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, false, _l1FeeVaultCalldata + address(RevShareLibrary.CREATE2_DEPLOYER), 0, RevShareLibrary.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, false, _l1FeeVaultCalldata ); IOptimismPortal2(payable(portal)).depositTransaction( - address(PROXY_ADMIN), + address(RevShareLibrary.PROXY_ADMIN), 0, - RevShareGasLimits.UPGRADE_GAS_LIMIT, + RevShareLibrary.UPGRADE_GAS_LIMIT, false, abi.encodeCall( IProxyAdmin.upgradeAndCall, ( - payable(L1_FEE_VAULT), + payable(RevShareLibrary.L1_FEE_VAULT), address(_l1FeeVaultPrecalculatedAddress), abi.encodeCall( IFeeVault.initialize, - (FEE_VAULT_RECIPIENT, FEE_VAULT_MIN_WITHDRAWAL_AMOUNT, FEE_VAULT_WITHDRAWAL_NETWORK) + (RevShareLibrary.FEE_VAULT_RECIPIENT, FEE_VAULT_MIN_WITHDRAWAL_AMOUNT, FEE_VAULT_WITHDRAWAL_NETWORK) ) ) ) @@ -623,22 +621,22 @@ contract RevenueShareV100UpgradePath is SimpleTaskBase, RevSharePredeploys { function _deployFeeSplitter() private { // Deploy Fee Splitter IOptimismPortal2(payable(portal)).depositTransaction( - address(CREATE2_DEPLOYER), + address(RevShareLibrary.CREATE2_DEPLOYER), 0, - RevShareGasLimits.FEE_SPLITTER_DEPLOYMENT_GAS_LIMIT, + RevShareLibrary.FEE_SPLITTER_DEPLOYMENT_GAS_LIMIT, false, _feeSplitterCalldata ); IOptimismPortal2(payable(portal)).depositTransaction( - address(PROXY_ADMIN), + address(RevShareLibrary.PROXY_ADMIN), 0, - RevShareGasLimits.UPGRADE_GAS_LIMIT, + RevShareLibrary.UPGRADE_GAS_LIMIT, false, abi.encodeCall( IProxyAdmin.upgradeAndCall, ( - payable(FEE_SPLITTER), + payable(RevShareLibrary.FEE_SPLITTER), address(_feeSplitterPrecalculatedAddress), abi.encodeCall(IFeeSplitter.initialize, (_scRevShareCalculatorPrecalculatedAddress)) ) diff --git a/test/template/revenue-share-upgrade-path/RevenueShareUpgradePath.t.sol b/test/template/revenue-share-upgrade-path/RevenueShareUpgradePath.t.sol deleted file mode 100644 index 36c72fa33a..0000000000 --- a/test/template/revenue-share-upgrade-path/RevenueShareUpgradePath.t.sol +++ /dev/null @@ -1,570 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.15; - -import {Test} from "forge-std/Test.sol"; -import {stdStorage, StdStorage} from "forge-std/StdStorage.sol"; -import {VmSafe} from "forge-std/Vm.sol"; -import {IGnosisSafe, Enum} from "@base-contracts/script/universal/IGnosisSafe.sol"; -import {IMulticall3} from "forge-std/interfaces/IMulticall3.sol"; -import {Signatures} from "@base-contracts/script/universal/Signatures.sol"; - -import {RevenueShareV100UpgradePath} from "src/template/RevenueShareUpgradePath.sol"; -import {SimpleAddressRegistry} from "src/SimpleAddressRegistry.sol"; -import {Action, TaskPayload, SafeData} from "src/libraries/MultisigTypes.sol"; -import {Utils} from "src/libraries/Utils.sol"; -import {AddressAliasHelper} from "@eth-optimism-bedrock/src/vendor/AddressAliasHelper.sol"; -import {RevShareGasLimits} from "src/libraries/RevShareGasLimits.sol"; - -interface IOptimismPortal2 { - function depositTransaction(address _to, uint256 _value, uint64 _gasLimit, bool _isCreation, bytes memory _data) - external - payable; -} - -interface ICreate2Deployer { - function deploy(uint256 _value, bytes32 _salt, bytes memory _code) external; -} - -interface IProxyAdmin { - function upgrade(address _proxy, address _implementation) external; - function upgradeAndCall(address _proxy, address _implementation, bytes memory _data) - external - payable - returns (bytes memory); -} - -/// @notice Test contract for the RevenueShareUpgradePath that expect reverts on misconfiguration of required fields. -contract RevenueShareUpgradePathRequiredFieldsTest is Test { - RevenueShareV100UpgradePath public template; - string internal constant TEMP_CONFIG_DIR = "test/template/revenue-share-upgrade-path/"; - - // Default valid values for tests - string internal constant DEFAULT_PORTAL = "0xbEb5Fc579115071764c7423A4f12eDde41f106Ed"; - string internal constant DEFAULT_SALT_SEED = "test-salt"; - string internal constant DEFAULT_CUSTOM_CALCULATOR = "0x1111111111111111111111111111111111111111"; - string internal constant DEFAULT_L1_WITHDRAWER_RECIPIENT = "0x742d35Cc6634C0532925a3b8D0C0C8b8B0c0C8b8"; - uint256 internal constant DEFAULT_L1_WITHDRAWER_GAS_LIMIT = 800000; - string internal constant DEFAULT_SC_REV_SHARE_CALC_CHAIN_FEES_RECIPIENT = "0x8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b8B0c0C8b"; - - // Invalid values for tests - string internal constant ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"; - string internal constant EMPTY_STRING = ""; - uint256 internal constant UINT32_MAX_PLUS_ONE = 4294967296; - - function setUp() public { - vm.createSelectFork("mainnet", 23197819); - template = new RevenueShareV100UpgradePath(); - } - - /// @notice Helper to write a minimal config for testing validation - /// @param _portal Portal address - /// @param _saltSeed Salt seed for deployment - /// @param _useDefaultCalculator Whether to use default calculator (true) or custom calculator (false) - /// @param _customCalculator Custom calculator address (only needed if _useDefaultCalculator is false) - /// @param _l1WithdrawerRecipient L1 withdrawer recipient (only needed if using default calculator) - /// @param _l1WithdrawerGasLimit L1 withdrawer gas limit (only needed if using default calculator) - /// @param _scRevShareCalcChainFeesRecipient Chain fees recipient (only needed if using default calculator) - /// @return Path to the created config file - function _writeTestConfig( - string memory _portal, - string memory _saltSeed, - bool _useDefaultCalculator, - string memory _customCalculator, - string memory _l1WithdrawerRecipient, - uint256 _l1WithdrawerGasLimit, - string memory _scRevShareCalcChainFeesRecipient - ) internal returns (string memory) { - string memory config = string.concat( - 'templateName = "RevenueShareV100UpgradePath"\n\nportal = "', - _portal, - '"\nsaltSeed = "', - _saltSeed, - '"\nuseDefaultCalculator = ', - _useDefaultCalculator ? 'true' : 'false', - '\n\n' - ); - - // Add calculator-specific fields based on useDefaultCalculator - if (_useDefaultCalculator) { - config = string.concat( - config, - 'l1WithdrawerMinWithdrawalAmount = 350000\nl1WithdrawerRecipient = "', - _l1WithdrawerRecipient, - '"\nl1WithdrawerGasLimit = ', - vm.toString(_l1WithdrawerGasLimit), - '\n\nscRevShareCalcChainFeesRecipient = "', - _scRevShareCalcChainFeesRecipient, - '"\n\n' - ); - } else { - config = string.concat( - config, - 'customCalculator = "', - _customCalculator, - '"\n\n' - ); - } - - config = string.concat( - config, - '[addresses]\nProxyAdminOwner = "0x5a0Aae59D09fccBdDb6C6CcEB07B7279367C3d2A"\n', - 'OptimismPortal = "0xbEb5Fc579115071764c7423A4f12eDde41f106Ed"' - ); - - string memory configPath = string.concat(TEMP_CONFIG_DIR, "temp-config-", vm.toString(uint256(uint32(msg.sig))), ".toml"); - vm.writeFile(configPath, config); - return configPath; - } - - /// @notice Tests that the template reverts when the portal is a zero address. - function test_revenueShareUpgradePath_portal_zero_address_reverts() public { - bool useDefaultCalculator = true; - - string memory configPath = _writeTestConfig( - ZERO_ADDRESS, // INVALID - portal is zero address - DEFAULT_SALT_SEED, - useDefaultCalculator, - ZERO_ADDRESS, // customCalculator (not used when useDefaultCalculator=true) - DEFAULT_L1_WITHDRAWER_RECIPIENT, - DEFAULT_L1_WITHDRAWER_GAS_LIMIT, - DEFAULT_SC_REV_SHARE_CALC_CHAIN_FEES_RECIPIENT - ); - vm.expectRevert("portal must be set in config"); - template.simulate(configPath); - vm.removeFile(configPath); - } - - /// @notice Tests that the template reverts when the salt seed is an empty string. - function test_revenueShareUpgradePath_saltSeed_empty_string_reverts() public { - bool useDefaultCalculator = true; - - string memory configPath = _writeTestConfig( - DEFAULT_PORTAL, - EMPTY_STRING, // INVALID - saltSeed is empty - useDefaultCalculator, - ZERO_ADDRESS, // customCalculator (not used when useDefaultCalculator=true) - DEFAULT_L1_WITHDRAWER_RECIPIENT, - DEFAULT_L1_WITHDRAWER_GAS_LIMIT, - DEFAULT_SC_REV_SHARE_CALC_CHAIN_FEES_RECIPIENT - ); - vm.expectRevert("saltSeed must be set in the config"); - template.simulate(configPath); - vm.removeFile(configPath); - } - - /// @notice Tests that the template reverts when the l1 withdrawer recipient is a zero address. - function test_revenueShareUpgradePath_l1WithdrawerRecipient_zero_address_reverts() public { - bool useDefaultCalculator = true; - - string memory configPath = _writeTestConfig( - DEFAULT_PORTAL, - DEFAULT_SALT_SEED, - useDefaultCalculator, - ZERO_ADDRESS, // customCalculator (not used when useDefaultCalculator=true) - ZERO_ADDRESS, // INVALID - l1WithdrawerRecipient is zero address - DEFAULT_L1_WITHDRAWER_GAS_LIMIT, - DEFAULT_SC_REV_SHARE_CALC_CHAIN_FEES_RECIPIENT - ); - vm.expectRevert("l1WithdrawerRecipient must be set in config"); - template.simulate(configPath); - vm.removeFile(configPath); - } - - /// @notice Tests that the template reverts when the l1 withdrawer gas limit is zero. - function test_revenueShareUpgradePath_l1WithdrawerGasLimit_zero_reverts() public { - bool useDefaultCalculator = true; - - string memory configPath = _writeTestConfig( - DEFAULT_PORTAL, - DEFAULT_SALT_SEED, - useDefaultCalculator, - ZERO_ADDRESS, // customCalculator (not used when useDefaultCalculator=true) - DEFAULT_L1_WITHDRAWER_RECIPIENT, - 0, // INVALID - l1WithdrawerGasLimit is zero - DEFAULT_SC_REV_SHARE_CALC_CHAIN_FEES_RECIPIENT - ); - vm.expectRevert("l1WithdrawerGasLimit must be greater than 0"); - template.simulate(configPath); - vm.removeFile(configPath); - } - - /// @notice Tests that the template reverts when the l1 withdrawer gas limit is too high. - function test_revenueShareUpgradePath_l1WithdrawerGasLimit_too_high_reverts() public { - bool useDefaultCalculator = true; - - string memory configPath = _writeTestConfig( - DEFAULT_PORTAL, - DEFAULT_SALT_SEED, - useDefaultCalculator, - ZERO_ADDRESS, // customCalculator (not used when useDefaultCalculator=true) - DEFAULT_L1_WITHDRAWER_RECIPIENT, - UINT32_MAX_PLUS_ONE, // INVALID - l1WithdrawerGasLimit exceeds uint32.max - DEFAULT_SC_REV_SHARE_CALC_CHAIN_FEES_RECIPIENT - ); - vm.expectRevert("l1WithdrawerGasLimit must be less than uint32.max"); - template.simulate(configPath); - vm.removeFile(configPath); - } - - /// @notice Tests that the template reverts when the chain fees recipient is a zero address. - function test_revenueShareUpgradePath_scRevShareCalcChainFeesRecipient_zero_address_reverts() public { - bool useDefaultCalculator = true; - - string memory configPath = _writeTestConfig( - DEFAULT_PORTAL, - DEFAULT_SALT_SEED, - useDefaultCalculator, - ZERO_ADDRESS, // customCalculator (not used when useDefaultCalculator=true) - DEFAULT_L1_WITHDRAWER_RECIPIENT, - DEFAULT_L1_WITHDRAWER_GAS_LIMIT, - ZERO_ADDRESS // INVALID - scRevShareCalcChainFeesRecipient is zero address - ); - vm.expectRevert("scRevShareCalcChainFeesRecipient must be set in config"); - template.simulate(configPath); - vm.removeFile(configPath); - } - - /// @notice Tests that the template reverts when using custom calculator with zero address. - function test_revenueShareUpgradePath_customCalculator_zero_address_reverts() public { - bool useDefaultCalculator = false; - - string memory configPath = _writeTestConfig( - DEFAULT_PORTAL, - DEFAULT_SALT_SEED, - useDefaultCalculator, - ZERO_ADDRESS, // INVALID - customCalculator is zero address when useDefaultCalculator=false - ZERO_ADDRESS, // Not used when useDefaultCalculator=false - 0, // Not used when useDefaultCalculator=false - ZERO_ADDRESS // Not used when useDefaultCalculator=false - ); - vm.expectRevert("customCalculator must be set when useDefaultCalculator is false"); - template.simulate(configPath); - vm.removeFile(configPath); - } -} - -contract RevenueShareUpgradePathTest is Test { - using stdStorage for StdStorage; - - event TransactionDeposited(address indexed from, address indexed to, uint256 indexed version, bytes opaqueData); - - RevenueShareV100UpgradePath public template; - - // Expected addresses from config - address public constant PORTAL = 0xbEb5Fc579115071764c7423A4f12eDde41f106Ed; - address public constant PROXY_ADMIN_OWNER = 0x5a0Aae59D09fccBdDb6C6CcEB07B7279367C3d2A; - - // Expected number of actions - uint256 public constant EXPECTED_DEPLOYMENTS_DEFAULT_CALC = 7; - uint256 public constant EXPECTED_UPGRADES_DEFAULT_CALC = 5; - uint256 public constant EXPECTED_DEPLOYMENTS_CUSTOM_CALC = 5; - uint256 public constant EXPECTED_UPGRADES_CUSTOM_CALC = 5; - - // L2 predeploys - address internal constant CREATE2_DEPLOYER = 0x13b0D85CcB8bf860b6b79AF3029fCA081AE9beF2; - address internal constant FEE_SPLITTER = 0x420000000000000000000000000000000000002B; - address internal constant PROXY_ADMIN = 0x4200000000000000000000000000000000000018; - uint64[12] internal EXPECTED_GAS_LIMITS_DEFAULT_CALC = [ - RevShareGasLimits.L1_WITHDRAWER_DEPLOYMENT_GAS_LIMIT, - RevShareGasLimits.SC_REV_SHARE_CALCULATOR_DEPLOYMENT_GAS_LIMIT, - RevShareGasLimits.FEE_SPLITTER_DEPLOYMENT_GAS_LIMIT, - RevShareGasLimits.UPGRADE_GAS_LIMIT, - RevShareGasLimits.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, - RevShareGasLimits.UPGRADE_GAS_LIMIT, - RevShareGasLimits.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, - RevShareGasLimits.UPGRADE_GAS_LIMIT, - RevShareGasLimits.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, - RevShareGasLimits.UPGRADE_GAS_LIMIT, - RevShareGasLimits.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, - RevShareGasLimits.UPGRADE_GAS_LIMIT - ]; - - uint64[10] internal EXPECTED_GAS_LIMITS_CUSTOM_CALC = [ - RevShareGasLimits.FEE_SPLITTER_DEPLOYMENT_GAS_LIMIT, - RevShareGasLimits.UPGRADE_GAS_LIMIT, - RevShareGasLimits.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, - RevShareGasLimits.UPGRADE_GAS_LIMIT, - RevShareGasLimits.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, - RevShareGasLimits.UPGRADE_GAS_LIMIT, - RevShareGasLimits.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, - RevShareGasLimits.UPGRADE_GAS_LIMIT, - RevShareGasLimits.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, - RevShareGasLimits.UPGRADE_GAS_LIMIT - ]; - - uint256 internal constant DEPOSIT_VERSION = 0; - - function _mockAndExpect(address _receiver, bytes memory _calldata, bytes memory _returned) internal { - vm.mockCall(_receiver, _calldata, _returned); - vm.expectCall(_receiver, _calldata); - } - - function setUp() public { - vm.createSelectFork("mainnet"); - - template = new RevenueShareV100UpgradePath(); - } - - function test_defaultCalculator_succeeds() public { - bool _isDefaultCalculator = true; - - _testRevenueShareUpgrade( - "test/tasks/example/eth/015-revenue-share-upgrade/config.toml", - _isDefaultCalculator, - EXPECTED_DEPLOYMENTS_DEFAULT_CALC + EXPECTED_UPGRADES_DEFAULT_CALC, - EXPECTED_DEPLOYMENTS_DEFAULT_CALC, - EXPECTED_UPGRADES_DEFAULT_CALC, - "Should have 12 actions for default calculator scenario" - ); - } - - function test_customCalculator_succeeds() public { - bool _isDefaultCalculator = false; - - _testRevenueShareUpgrade( - "test/tasks/example/eth/017-revenue-share-upgrade-custom-calc/config.toml", - _isDefaultCalculator, - EXPECTED_DEPLOYMENTS_CUSTOM_CALC + EXPECTED_UPGRADES_CUSTOM_CALC, - EXPECTED_DEPLOYMENTS_CUSTOM_CALC, - EXPECTED_UPGRADES_CUSTOM_CALC, - "Should have 10 actions for custom calculator scenario" - ); - } - - /// @notice Helper function to test revenue share upgrade scenarios - /// @param _configPath Path to the config file - /// @param _isDefaultCalculator Whether this uses the default calculator (true) or custom calculator (false) - /// @param _expectedTotalActions Expected total number of actions - /// @param _expectedDeployments Expected number of deployment actions - /// @param _expectedUpgrades Expected number of upgrade actions - /// @param _actionCountMessage Assertion message for action count verification - function _testRevenueShareUpgrade( - string memory _configPath, - bool _isDefaultCalculator, - uint256 _expectedTotalActions, - uint256 _expectedDeployments, - uint256 _expectedUpgrades, - string memory _actionCountMessage - ) internal { - // Step 1: Run simulate to prepare everything and get the actions - (, Action[] memory _actions,, address _rootSafe) = template.simulate(_configPath, new address[](0)); - - // Verify we got the expected safe and action count - assertEq(_rootSafe, PROXY_ADMIN_OWNER, "Root safe should be ProxyAdminOwner"); - assertEq(_actions.length, _expectedTotalActions, _actionCountMessage); - - // Step 2: Get the safe's owners - IGnosisSafe _safe = IGnosisSafe(_rootSafe); - address[] memory _owners = _safe.getOwners(); - - // Step 3: Get the multicall calldata that will be executed - IMulticall3.Call3Value[] memory _calls = new IMulticall3.Call3Value[](_actions.length); - for (uint256 i; i < _actions.length; i++) { - _calls[i] = IMulticall3.Call3Value({ - target: _actions[i].target, - allowFailure: false, - value: _actions[i].value, - callData: _actions[i].arguments - }); - } - bytes memory _multicallData = abi.encodeCall(IMulticall3.aggregate3Value, (_calls)); - - // Step 4: Get the nonce and compute transaction hash before any state changes - uint256 _nonceBefore = _safe.nonce(); - - bytes32 _txHash = _safe.getTransactionHash( - template.multicallTarget(), - 0, // value - _multicallData, - Enum.Operation.DelegateCall, - 0, // safeTxGas - 0, // baseGas - 0, // gasPrice - address(0), // gasToken - payable(address(0)), // refundReceiver - _nonceBefore - ); - - // Step 5: Manually verify expected portal calls based on known config values - _verifyExpectedPortalCalls(_actions, _isDefaultCalculator); - - // Step 6: Prank owners to approve the transaction - for (uint256 i; i < _owners.length; i++) { - vm.prank(_owners[i]); - _safe.approveHash(_txHash); - } - - // Step 7: Generate signatures after approval - bytes memory _signatures = Signatures.genPrevalidatedSignatures(_owners); - - _expectPortalEvents(_actions); - - // Step 8: Execute the transaction - bool _success = _safe.execTransaction( - template.multicallTarget(), - 0, // value - _multicallData, - Enum.Operation.DelegateCall, - 0, // safeTxGas - 0, // baseGas - 0, // gasPrice - address(0), // gasToken - payable(address(0)), // refundReceiver - _signatures - ); - - assertTrue(_success, "Transaction should execute successfully"); - assertEq(_safe.nonce(), _nonceBefore + 1, "Safe nonce should increment"); - - // Step 9: Verify the portal calls - _verifyPortalCalls(_actions, _expectedDeployments, _expectedUpgrades); - } - - /// @notice Verify the portal calls based on the expected deployments and upgrades - /// @param _actions The actions to verify - /// @param _expectedDeployments The expected number of deployments - /// @param _expectedUpgrades The expected number of upgrades - function _verifyPortalCalls(Action[] memory _actions, uint256 _expectedDeployments, uint256 _expectedUpgrades) - internal - pure - { - uint256 _deploymentCalls = 0; - uint256 _upgradeCalls = 0; - - for (uint256 i; i < _actions.length; i++) { - // Decode the depositTransaction parameters - bytes memory _params = new bytes(_actions[i].arguments.length - 4); - for (uint256 j; j < _params.length; j++) { - _params[j] = _actions[i].arguments[j + 4]; - } - (address _to,,,,) = abi.decode(_params, (address, uint256, uint64, bool, bytes)); - - if (_to == CREATE2_DEPLOYER) { - _deploymentCalls++; - } else { - _upgradeCalls++; - } - } - - assertEq(_deploymentCalls, _expectedDeployments, "Incorrect number of deployment calls"); - assertEq(_upgradeCalls, _expectedUpgrades, "Incorrect number of upgrade calls"); - } - - /// @notice Manually construct and expect portal calls based on known config values - /// This ensures the template generates correct calldata, not just circular validation - function _verifyExpectedPortalCalls(Action[] memory _actions, bool _isDefaultCalculator) internal { - uint256 _deploymentCount; - uint256 _upgradeCount; - - for (uint256 i; i < _actions.length; i++) { - bytes memory _params = _extractParams(_actions[i].arguments); - // depending on if using default calculator or custom calculator, we use the expected gas limits - uint64 _gasLimit = _isDefaultCalculator ? EXPECTED_GAS_LIMITS_DEFAULT_CALC[i] : EXPECTED_GAS_LIMITS_CUSTOM_CALC[i]; - (address _to, uint256 _value, uint64 _actualGasLimit, bool _isCreation, bytes memory _data) = - abi.decode(_params, (address, uint256, uint64, bool, bytes)); - - assertEq(_actions[i].target, PORTAL, "All actions should target the portal"); - _verifyCommonParams(_value, _actualGasLimit, _gasLimit, _isCreation, _data); - - if (_to == CREATE2_DEPLOYER) { - _deploymentCount++; - _verifyDeploymentCall(_gasLimit, _data); - } else { - _upgradeCount++; - _verifyUpgradeCall(_to, _gasLimit, _data); - } - } - - assertGt(_deploymentCount, 0, "Should have at least one deployment"); - assertGt(_upgradeCount, 0, "Should have at least one upgrade"); - assertEq(_deploymentCount + _upgradeCount, _actions.length, "All actions should be accounted for"); - } - - /// @notice Extract the parameters from the arguments - /// @param _arguments The arguments to extract the parameters from - /// @return The parameters - function _extractParams(bytes memory _arguments) internal pure returns (bytes memory) { - bytes memory _params = new bytes(_arguments.length - 4); - for (uint256 j; j < _params.length; j++) { - _params[j] = _arguments[j + 4]; - } - return _params; - } - - /// @notice Verify the parameters on the expected portal calls - /// @param _value The value - /// @param _actualGasLimit The actual gas limit - /// @param _expectedGasLimit The expected gas limit - /// @param _isCreation The is creation - /// @param _data The data, only checking calldata length - /// it is better tested in RevenueShareUpgradePath.sol::_validate - function _verifyCommonParams( - uint256 _value, - uint64 _actualGasLimit, - uint64 _expectedGasLimit, - bool _isCreation, - bytes memory _data - ) internal pure { - require(_value == 0, "All calls should have 0 value"); - require(_actualGasLimit == _expectedGasLimit, "Gas limit should match config"); - require(!_isCreation, "Should not use creation flag"); - require(_data.length > 0, "Should have calldata"); - } - - /// @notice Verify the deployment call - /// @param _gasLimit The expected gas limit - /// @param _data The expected data - function _verifyDeploymentCall(uint64 _gasLimit, bytes memory _data) internal { - vm.expectCall( - PORTAL, abi.encodeCall(IOptimismPortal2.depositTransaction, (CREATE2_DEPLOYER, 0, _gasLimit, false, _data)) - ); - - bytes4 _actualSelector; - assembly { - _actualSelector := mload(add(_data, 32)) - } - assertEq(_actualSelector, ICreate2Deployer.deploy.selector, "Deployment should call CREATE2 deploy"); - } - - /// @notice Verify the upgrade call - /// @param _to The target address, it MUST be the proxy admin - /// @param _gasLimit The expected gas limit - /// @param _data The expected data - function _verifyUpgradeCall(address _to, uint64 _gasLimit, bytes memory _data) internal { - vm.expectCall(PORTAL, abi.encodeCall(IOptimismPortal2.depositTransaction, (_to, 0, _gasLimit, false, _data))); - - _assertIsProxyAdmin(_to); - - bytes4 _selector; - assembly { - _selector := mload(add(_data, 32)) - } - assertTrue( - _selector == IProxyAdmin.upgrade.selector || _selector == IProxyAdmin.upgradeAndCall.selector, - "Upgrade should call upgradeTo or upgradeToAndCall" - ); - } - - /// @notice Verify the target address is the proxy admin - /// @param _to The target address - function _assertIsProxyAdmin(address _to) internal pure { - assertTrue(_to == PROXY_ADMIN, "Upgrade should target the proxy admin"); - } - - /// @notice Expect the portal events - /// @param _actions The actions to expect the events for - function _expectPortalEvents(Action[] memory _actions) internal { - for (uint256 i; i < _actions.length; i++) { - bytes memory _params = _extractParams(_actions[i].arguments); - (address _to,, uint64 _actualGasLimit, bool _isCreation, bytes memory _data) = - abi.decode(_params, (address, uint256, uint64, bool, bytes)); - - bytes memory _opaqueData = abi.encodePacked(uint256(0), uint256(0), _actualGasLimit, _isCreation, _data); - - vm.expectEmit(true, true, true, true, PORTAL); - emit TransactionDeposited( - AddressAliasHelper.applyL1ToL2Alias(PROXY_ADMIN_OWNER), _to, DEPOSIT_VERSION, _opaqueData - ); - } - } -} From 1dad4b4d4ac53808ff1831273b0bef4ae02aa6d6 Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Mon, 10 Nov 2025 18:03:51 -0300 Subject: [PATCH 49/69] chore: remove default value initalization --- src/template/RevShareUpgradeAndSetup.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/template/RevShareUpgradeAndSetup.sol b/src/template/RevShareUpgradeAndSetup.sol index e1e279cc31..e371baf2b7 100644 --- a/src/template/RevShareUpgradeAndSetup.sol +++ b/src/template/RevShareUpgradeAndSetup.sol @@ -41,7 +41,7 @@ contract RevShareUpgradeAndSetup is OPCMTaskBase { function _setAllowedStorageAccesses() internal virtual override { super._setAllowedStorageAccesses(); // Add portal addresses as they will have storage writes from depositTransaction calls - for (uint256 i = 0; i < portals.length; i++) { + for (uint256 i; i < portals.length; i++) { _allowedStorageAccesses.add(portals[i]); } } @@ -69,7 +69,7 @@ contract RevShareUpgradeAndSetup is OPCMTaskBase { RevShareContractsUpgrader.L1WithdrawerConfig[] memory configs = new RevShareContractsUpgrader.L1WithdrawerConfig[](portals.length); - for (uint256 i = 0; i < portals.length; i++) { + for (uint256 i; i < portals.length; i++) { string memory basePath = string.concat(".l1WithdrawerConfigs[", vm.toString(i), "]"); configs[i] = RevShareContractsUpgrader.L1WithdrawerConfig({ minWithdrawalAmount: tomlContent.readUint(string.concat(basePath, ".minWithdrawalAmount")), @@ -111,7 +111,7 @@ contract RevShareUpgradeAndSetup is OPCMTaskBase { bool foundDelegatecall = false; - for (uint256 i = 0; i < _actions.length; i++) { + for (uint256 i; i < _actions.length; i++) { Action memory action = _actions[i]; // Check if this is a delegatecall to RevShareContractsUpgrader if (action.target == REV_SHARE_MANAGER) { From bd5a0fb387449e150680c64b046133bcffbe766b Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Tue, 11 Nov 2025 12:52:52 -0300 Subject: [PATCH 50/69] refactor: rename RevShareManager -> RevShareUpgrader --- src/template/RevShareUpgradeAndSetup.sol | 14 +++++++------- .../RevShareContractsUpgraderIntegration.t.sol | 10 +++++----- .../eth/016-revshare-upgrade-and-setup/config.toml | 4 ++-- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/template/RevShareUpgradeAndSetup.sol b/src/template/RevShareUpgradeAndSetup.sol index e371baf2b7..e16a2db627 100644 --- a/src/template/RevShareUpgradeAndSetup.sol +++ b/src/template/RevShareUpgradeAndSetup.sol @@ -16,7 +16,7 @@ contract RevShareUpgradeAndSetup is OPCMTaskBase { using EnumerableSet for EnumerableSet.AddressSet; /// @notice RevShareContractsUpgrader address - address public REV_SHARE_MANAGER; + address public REV_SHARE_UPGRADER; /// @notice Portal addresses for L2 chains. address[] internal portals; @@ -51,12 +51,12 @@ contract RevShareUpgradeAndSetup is OPCMTaskBase { string memory tomlContent = vm.readFile(taskConfigFilePath); // Load RevShareContractsUpgrader address from TOML - REV_SHARE_MANAGER = tomlContent.readAddress(".revShareManager"); - require(REV_SHARE_MANAGER.code.length > 0, "RevShareContractsUpgrader has no code"); - vm.label(REV_SHARE_MANAGER, "RevShareContractsUpgrader"); + REV_SHARE_UPGRADER = tomlContent.readAddress(".revShareUpgrader"); + require(REV_SHARE_UPGRADER.code.length > 0, "RevShareContractsUpgrader has no code"); + vm.label(REV_SHARE_UPGRADER, "RevShareContractsUpgrader"); // Set RevShareContractsUpgrader as the allowed target for delegatecall - OPCM_TARGETS.push(REV_SHARE_MANAGER); + OPCM_TARGETS.push(REV_SHARE_UPGRADER); // Load portal addresses portals = abi.decode(tomlContent.parseRaw(".portals"), (address[])); @@ -92,7 +92,7 @@ contract RevShareUpgradeAndSetup is OPCMTaskBase { // Delegatecall into RevShareContractsUpgrader // OPCMTaskBase uses Multicall3Delegatecall, so this delegatecall will be captured as an action - (bool success,) = REV_SHARE_MANAGER.delegatecall( + (bool success,) = REV_SHARE_UPGRADER.delegatecall( abi.encodeCall( RevShareContractsUpgrader.upgradeAndSetupRevShare, (portals, l1WithdrawerConfigs, remainderRecipients) ) @@ -114,7 +114,7 @@ contract RevShareUpgradeAndSetup is OPCMTaskBase { for (uint256 i; i < _actions.length; i++) { Action memory action = _actions[i]; // Check if this is a delegatecall to RevShareContractsUpgrader - if (action.target == REV_SHARE_MANAGER) { + if (action.target == REV_SHARE_UPGRADER) { foundDelegatecall = true; // Verify it's calling upgradeAndSetupRevShare bytes4 selector = bytes4(action.arguments); diff --git a/test/integration/RevShareContractsUpgraderIntegration.t.sol b/test/integration/RevShareContractsUpgraderIntegration.t.sol index f12712d706..c47ff0ef36 100644 --- a/test/integration/RevShareContractsUpgraderIntegration.t.sol +++ b/test/integration/RevShareContractsUpgraderIntegration.t.sol @@ -16,7 +16,7 @@ import {IL1Withdrawer} from "src/interfaces/IL1Withdrawer.sol"; import {ISuperchainRevSharesCalculator} from "src/interfaces/ISuperchainRevSharesCalculator.sol"; contract RevShareContractsUpgraderIntegrationTest is IntegrationBase { - RevShareContractsUpgrader public revShareManager; + RevShareContractsUpgrader public revShareUpgrader; RevShareUpgradeAndSetup public revShareTask; // Fork IDs @@ -28,7 +28,7 @@ contract RevShareContractsUpgraderIntegrationTest is IntegrationBase { address internal constant PROXY_ADMIN_OWNER = 0x5a0Aae59D09fccBdDb6C6CcEB07B7279367C3d2A; address internal constant OP_MAINNET_PORTAL = 0xbEb5Fc579115071764c7423A4f12eDde41f106Ed; address internal constant INK_MAINNET_PORTAL = 0x5d66C1782664115999C47c9fA5cd031f495D3e4F; - address internal constant REV_SHARE_MANAGER_ADDRESS = 0x0000000000000000000000000000000000001337; + address internal constant REV_SHARE_UPGRADER_ADDRESS = 0x0000000000000000000000000000000000001337; // L2 predeploys (same across all OP Stack chains) address internal constant SEQUENCER_FEE_VAULT = 0x4200000000000000000000000000000000000011; @@ -68,9 +68,9 @@ contract RevShareContractsUpgraderIntegrationTest is IntegrationBase { vm.selectFork(_mainnetForkId); // Deploy RevShareContractsUpgrader and etch at predetermined address - revShareManager = new RevShareContractsUpgrader(); - vm.etch(REV_SHARE_MANAGER_ADDRESS, address(revShareManager).code); - revShareManager = RevShareContractsUpgrader(REV_SHARE_MANAGER_ADDRESS); + revShareUpgrader = new RevShareContractsUpgrader(); + vm.etch(REV_SHARE_UPGRADER_ADDRESS, address(revShareUpgrader).code); + revShareUpgrader = RevShareContractsUpgrader(REV_SHARE_UPGRADER_ADDRESS); // Deploy RevShareUpgradeAndSetup task revShareTask = new RevShareUpgradeAndSetup(); diff --git a/test/tasks/example/eth/016-revshare-upgrade-and-setup/config.toml b/test/tasks/example/eth/016-revshare-upgrade-and-setup/config.toml index 5d704f302f..4ccc8705fb 100644 --- a/test/tasks/example/eth/016-revshare-upgrade-and-setup/config.toml +++ b/test/tasks/example/eth/016-revshare-upgrade-and-setup/config.toml @@ -7,8 +7,8 @@ l2chains = [{name = "OP Mainnet", chainId = 10}, {name = "Ink", chainId = 57073} safeAddress = "ProxyAdminOwner" -# RevShareContractsManager address -revShareManager = "0x0000000000000000000000000000000000001337" +# RevShareContractsUpgrader address +revShareUpgrader = "0x0000000000000000000000000000000000001337" # Portal addresses for each chain portals = [ From 585bee06abdc247b4aba0f785d2315daa8c20c0e Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Tue, 11 Nov 2025 13:07:50 -0300 Subject: [PATCH 51/69] refactor: single param for calling upgrader contract --- src/RevShareContractsUpgrader.sol | 75 ++++++++----------- src/template/RevShareUpgradeAndSetup.sol | 52 ++++++------- .../config.toml | 29 ++++--- 3 files changed, 73 insertions(+), 83 deletions(-) diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol index 815be502c8..5fbb4a9cf7 100644 --- a/src/RevShareContractsUpgrader.sol +++ b/src/RevShareContractsUpgrader.sol @@ -30,9 +30,6 @@ contract RevShareContractsUpgrader { /// @notice Thrown when chain fees recipient is zero address error ChainFeesRecipientCannotBeZeroAddress(); - /// @notice Thrown when array lengths don't match - error ArrayLengthMismatch(); - /// @notice Thrown when array is empty error EmptyArray(); @@ -46,28 +43,30 @@ contract RevShareContractsUpgrader { 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 _portals Array of OptimismPortal2 addresses for the target L2s. - /// @param _l1WithdrawerConfigs Array of L1Withdrawer configurations. - /// @param _chainFeesRecipients Array of chain fees recipients for the calculators. - function upgradeAndSetupRevShare( - address[] calldata _portals, - L1WithdrawerConfig[] calldata _l1WithdrawerConfigs, - address[] calldata _chainFeesRecipients - ) external { - if (_portals.length == 0) revert EmptyArray(); - if (_portals.length != _l1WithdrawerConfigs.length || _portals.length != _chainFeesRecipients.length) { - revert ArrayLengthMismatch(); - } + /// @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 < _portals.length; i++) { - if (_portals[i] == address(0)) revert PortalCannotBeZeroAddress(); - if (_l1WithdrawerConfigs[i].recipient == address(0)) revert L1WithdrawerRecipientCannotBeZeroAddress(); - if (_chainFeesRecipients[i] == address(0)) revert ChainFeesRecipientCannotBeZeroAddress(); + 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(); // Deploy L1Withdrawer and SuperchainRevenueShareCalculator - address calculator = _deployRevSharePeriphery(_portals[i], _l1WithdrawerConfigs[i], _chainFeesRecipients[i]); + address calculator = _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 @@ -75,13 +74,13 @@ contract RevShareContractsUpgrader { address feeSplitterImpl = Utils.getCreate2Address(feeSplitterSalt, RevShareLibrary.feeSplitterCreationCode, RevShareLibrary.CREATE2_DEPLOYER); _depositCreate2( - _portals[i], + config.portal, RevShareLibrary.FEE_SPLITTER_DEPLOYMENT_GAS_LIMIT, feeSplitterSalt, RevShareLibrary.feeSplitterCreationCode ); _depositCall( - _portals[i], + config.portal, address(RevShareLibrary.PROXY_ADMIN), RevShareLibrary.UPGRADE_GAS_LIMIT, abi.encodeCall( @@ -91,43 +90,35 @@ contract RevShareContractsUpgrader { ); // Upgrade all 4 vaults with RevShare configuration (recipient=FeeSplitter, minWithdrawal=0, network=L2) - _upgradeVaultsWithRevShareConfig(_portals[i]); + _upgradeVaultsWithRevShareConfig(config.portal); } } /// @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 _portals Array of OptimismPortal2 addresses for the target L2s. - /// @param _l1WithdrawerConfigs Array of L1Withdrawer configurations. - /// @param _chainFeesRecipients Array of chain fees recipients for the calculators. - function setupRevShare( - address[] calldata _portals, - L1WithdrawerConfig[] calldata _l1WithdrawerConfigs, - address[] calldata _chainFeesRecipients - ) external { - if (_portals.length == 0) revert EmptyArray(); - if (_portals.length != _l1WithdrawerConfigs.length || _portals.length != _chainFeesRecipients.length) { - revert ArrayLengthMismatch(); - } + /// @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 < _portals.length; i++) { - if (_portals[i] == address(0)) revert PortalCannotBeZeroAddress(); - if (_l1WithdrawerConfigs[i].recipient == address(0)) revert L1WithdrawerRecipientCannotBeZeroAddress(); - if (_chainFeesRecipients[i] == address(0)) revert ChainFeesRecipientCannotBeZeroAddress(); + 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(); // Deploy L1Withdrawer and SuperchainRevenueShareCalculator - address calculator = _deployRevSharePeriphery(_portals[i], _l1WithdrawerConfigs[i], _chainFeesRecipients[i]); + address calculator = _deployRevSharePeriphery(config.portal, config.l1WithdrawerConfig, config.chainFeesRecipient); // Set calculator on fee splitter _depositCall( - _portals[i], + config.portal, RevShareLibrary.FEE_SPLITTER, RevShareLibrary.SETTERS_GAS_LIMIT, abi.encodeCall(IFeeSplitter.setSharesCalculator, (calculator)) ); // Configure all 4 vaults for revenue sharing - _configureVaultsForRevShare(_portals[i]); + _configureVaultsForRevShare(config.portal); } } diff --git a/src/template/RevShareUpgradeAndSetup.sol b/src/template/RevShareUpgradeAndSetup.sol index e16a2db627..b10456b64f 100644 --- a/src/template/RevShareUpgradeAndSetup.sol +++ b/src/template/RevShareUpgradeAndSetup.sol @@ -18,14 +18,8 @@ contract RevShareUpgradeAndSetup is OPCMTaskBase { /// @notice RevShareContractsUpgrader address address public REV_SHARE_UPGRADER; - /// @notice Portal addresses for L2 chains. - address[] internal portals; - - /// @notice L1Withdrawer configurations (stored as encoded bytes). - bytes internal l1WithdrawerConfigsEncoded; - - /// @notice Remainder recipients (chain fees recipients). - address[] internal remainderRecipients; + /// @notice RevShare configurations (stored as encoded bytes). + bytes internal revShareConfigsEncoded; /// @notice Names in the SimpleAddressRegistry that are expected to be written during this task. function _taskStorageWrites() internal pure virtual override returns (string[] memory) { @@ -41,8 +35,10 @@ contract RevShareUpgradeAndSetup is OPCMTaskBase { function _setAllowedStorageAccesses() internal virtual override { super._setAllowedStorageAccesses(); // Add portal addresses as they will have storage writes from depositTransaction calls - for (uint256 i; i < portals.length; i++) { - _allowedStorageAccesses.add(portals[i]); + RevShareContractsUpgrader.RevShareConfig[] memory configs = + abi.decode(revShareConfigsEncoded, (RevShareContractsUpgrader.RevShareConfig[])); + for (uint256 i; i < configs.length; i++) { + _allowedStorageAccesses.add(configs[i].portal); } } @@ -59,43 +55,41 @@ contract RevShareUpgradeAndSetup is OPCMTaskBase { OPCM_TARGETS.push(REV_SHARE_UPGRADER); // Load portal addresses - portals = abi.decode(tomlContent.parseRaw(".portals"), (address[])); + address[] memory portals = abi.decode(tomlContent.parseRaw(".portals"), (address[])); require(portals.length > 0, "No portals configured"); - // Load L1Withdrawer configs by reading each field individually + // Load RevShare configs by reading each field individually // Note: We can't use parseRaw + abi.decode directly because TOML inline tables // sort keys alphabetically, which doesn't match the struct field order // So we need to read each field separately and construct the struct manually - RevShareContractsUpgrader.L1WithdrawerConfig[] memory configs = - new RevShareContractsUpgrader.L1WithdrawerConfig[](portals.length); + RevShareContractsUpgrader.RevShareConfig[] memory configs = + new RevShareContractsUpgrader.RevShareConfig[](portals.length); for (uint256 i; i < portals.length; i++) { - string memory basePath = string.concat(".l1WithdrawerConfigs[", vm.toString(i), "]"); - configs[i] = RevShareContractsUpgrader.L1WithdrawerConfig({ - minWithdrawalAmount: tomlContent.readUint(string.concat(basePath, ".minWithdrawalAmount")), - recipient: tomlContent.readAddress(string.concat(basePath, ".recipient")), - gasLimit: uint32(tomlContent.readUint(string.concat(basePath, ".gasLimit"))) + string memory basePath = string.concat(".configs[", vm.toString(i), "]"); + configs[i] = RevShareContractsUpgrader.RevShareConfig({ + portal: tomlContent.readAddress(string.concat(basePath, ".portal")), + l1WithdrawerConfig: RevShareContractsUpgrader.L1WithdrawerConfig({ + minWithdrawalAmount: tomlContent.readUint(string.concat(basePath, ".l1WithdrawerConfig.minWithdrawalAmount")), + recipient: tomlContent.readAddress(string.concat(basePath, ".l1WithdrawerConfig.recipient")), + gasLimit: uint32(tomlContent.readUint(string.concat(basePath, ".l1WithdrawerConfig.gasLimit"))) + }), + chainFeesRecipient: tomlContent.readAddress(string.concat(basePath, ".chainFeesRecipient")) }); } - l1WithdrawerConfigsEncoded = abi.encode(configs); - - // Load remainder recipients - remainderRecipients = abi.decode(tomlContent.parseRaw(".remainderRecipients"), (address[])); - require(remainderRecipients.length == portals.length, "Remainder recipients length mismatch"); + revShareConfigsEncoded = abi.encode(configs); } /// @notice Builds the actions for executing the operations. function _build(address) internal override { // Decode configs from storage - RevShareContractsUpgrader.L1WithdrawerConfig[] memory l1WithdrawerConfigs = - abi.decode(l1WithdrawerConfigsEncoded, (RevShareContractsUpgrader.L1WithdrawerConfig[])); + RevShareContractsUpgrader.RevShareConfig[] memory configs = + abi.decode(revShareConfigsEncoded, (RevShareContractsUpgrader.RevShareConfig[])); // Delegatecall into RevShareContractsUpgrader // OPCMTaskBase uses Multicall3Delegatecall, so this delegatecall will be captured as an action (bool success,) = REV_SHARE_UPGRADER.delegatecall( - abi.encodeCall( - RevShareContractsUpgrader.upgradeAndSetupRevShare, (portals, l1WithdrawerConfigs, remainderRecipients) - ) + abi.encodeCall(RevShareContractsUpgrader.upgradeAndSetupRevShare, (configs)) ); require(success, "RevShareUpgradeAndSetup: Delegatecall failed"); } diff --git a/test/tasks/example/eth/016-revshare-upgrade-and-setup/config.toml b/test/tasks/example/eth/016-revshare-upgrade-and-setup/config.toml index 4ccc8705fb..f15795f6ee 100644 --- a/test/tasks/example/eth/016-revshare-upgrade-and-setup/config.toml +++ b/test/tasks/example/eth/016-revshare-upgrade-and-setup/config.toml @@ -10,23 +10,28 @@ safeAddress = "ProxyAdminOwner" # RevShareContractsUpgrader address revShareUpgrader = "0x0000000000000000000000000000000000001337" -# Portal addresses for each chain +# Portal addresses for each chain (needed for template validation) portals = [ "0xbEb5Fc579115071764c7423A4f12eDde41f106Ed", # OP Mainnet Portal "0x5d66C1782664115999C47c9fA5cd031f495D3e4F" # Ink Mainnet Portal ] -# Chain fees recipients (remainder recipients for each chain) -remainderRecipients = [ - "0x0000000000000000000000000000000000000001", # OP Mainnet chain fees recipient - "0x0000000000000000000000000000000000000002" # Ink Mainnet chain fees recipient -] - -# L1Withdrawer configurations (different for each chain) -l1WithdrawerConfigs = [ - {minWithdrawalAmount = 350000, recipient = "0x0000000000000000000000000000000000000001", gasLimit = 800000}, # OP Mainnet L1Withdrawer - {minWithdrawalAmount = 500000, recipient = "0x0000000000000000000000000000000000000002", gasLimit = 1000000} # Ink Mainnet L1Withdrawer -] +# RevShare configurations (one per chain) +[[configs]] +portal = "0xbEb5Fc579115071764c7423A4f12eDde41f106Ed" # OP Mainnet Portal +chainFeesRecipient = "0x0000000000000000000000000000000000000001" # OP Mainnet chain fees recipient +[configs.l1WithdrawerConfig] +minWithdrawalAmount = 350000 +recipient = "0x0000000000000000000000000000000000000001" +gasLimit = 800000 + +[[configs]] +portal = "0x5d66C1782664115999C47c9fA5cd031f495D3e4F" # Ink Mainnet Portal +chainFeesRecipient = "0x0000000000000000000000000000000000000002" # Ink Mainnet chain fees recipient +[configs.l1WithdrawerConfig] +minWithdrawalAmount = 500000 +recipient = "0x0000000000000000000000000000000000000002" +gasLimit = 1000000 [addresses] ProxyAdminOwner = "0x5a0Aae59D09fccBdDb6C6CcEB07B7279367C3d2A" From d9a62b822eaaec4b30708c1d3a4bc69d92833e07 Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Tue, 11 Nov 2025 13:33:44 -0300 Subject: [PATCH 52/69] refactor: remove portals array from template config --- src/template/RevShareUpgradeAndSetup.sol | 6 +++--- .../example/eth/016-revshare-upgrade-and-setup/config.toml | 6 ------ 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/template/RevShareUpgradeAndSetup.sol b/src/template/RevShareUpgradeAndSetup.sol index b10456b64f..446328539b 100644 --- a/src/template/RevShareUpgradeAndSetup.sol +++ b/src/template/RevShareUpgradeAndSetup.sol @@ -54,9 +54,9 @@ contract RevShareUpgradeAndSetup is OPCMTaskBase { // Set RevShareContractsUpgrader as the allowed target for delegatecall OPCM_TARGETS.push(REV_SHARE_UPGRADER); - // Load portal addresses - address[] memory portals = abi.decode(tomlContent.parseRaw(".portals"), (address[])); - require(portals.length > 0, "No portals configured"); + // Get the length of the configs array by parsing just the portal addresses + address[] memory portals = abi.decode(tomlContent.parseRaw(".configs[*].portal"), (address[])); + require(portals.length > 0, "No configs found"); // Load RevShare configs by reading each field individually // Note: We can't use parseRaw + abi.decode directly because TOML inline tables diff --git a/test/tasks/example/eth/016-revshare-upgrade-and-setup/config.toml b/test/tasks/example/eth/016-revshare-upgrade-and-setup/config.toml index f15795f6ee..4ed92ba25e 100644 --- a/test/tasks/example/eth/016-revshare-upgrade-and-setup/config.toml +++ b/test/tasks/example/eth/016-revshare-upgrade-and-setup/config.toml @@ -10,12 +10,6 @@ safeAddress = "ProxyAdminOwner" # RevShareContractsUpgrader address revShareUpgrader = "0x0000000000000000000000000000000000001337" -# Portal addresses for each chain (needed for template validation) -portals = [ - "0xbEb5Fc579115071764c7423A4f12eDde41f106Ed", # OP Mainnet Portal - "0x5d66C1782664115999C47c9fA5cd031f495D3e4F" # Ink Mainnet Portal -] - # RevShare configurations (one per chain) [[configs]] portal = "0xbEb5Fc579115071764c7423A4f12eDde41f106Ed" # OP Mainnet Portal From c02d2940285b4208eced51b4e0d7522c5b9ce900 Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Tue, 11 Nov 2025 13:43:09 -0300 Subject: [PATCH 53/69] refactor: remove unnecessary encoding and decoding --- src/template/RevShareUpgradeAndSetup.sol | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/src/template/RevShareUpgradeAndSetup.sol b/src/template/RevShareUpgradeAndSetup.sol index 446328539b..126107c217 100644 --- a/src/template/RevShareUpgradeAndSetup.sol +++ b/src/template/RevShareUpgradeAndSetup.sol @@ -18,8 +18,8 @@ contract RevShareUpgradeAndSetup is OPCMTaskBase { /// @notice RevShareContractsUpgrader address address public REV_SHARE_UPGRADER; - /// @notice RevShare configurations (stored as encoded bytes). - bytes internal revShareConfigsEncoded; + /// @notice RevShare configurations + RevShareContractsUpgrader.RevShareConfig[] internal revShareConfigs; /// @notice Names in the SimpleAddressRegistry that are expected to be written during this task. function _taskStorageWrites() internal pure virtual override returns (string[] memory) { @@ -35,10 +35,8 @@ contract RevShareUpgradeAndSetup is OPCMTaskBase { function _setAllowedStorageAccesses() internal virtual override { super._setAllowedStorageAccesses(); // Add portal addresses as they will have storage writes from depositTransaction calls - RevShareContractsUpgrader.RevShareConfig[] memory configs = - abi.decode(revShareConfigsEncoded, (RevShareContractsUpgrader.RevShareConfig[])); - for (uint256 i; i < configs.length; i++) { - _allowedStorageAccesses.add(configs[i].portal); + for (uint256 i; i < revShareConfigs.length; i++) { + _allowedStorageAccesses.add(revShareConfigs[i].portal); } } @@ -62,12 +60,9 @@ contract RevShareUpgradeAndSetup is OPCMTaskBase { // Note: We can't use parseRaw + abi.decode directly because TOML inline tables // sort keys alphabetically, which doesn't match the struct field order // So we need to read each field separately and construct the struct manually - RevShareContractsUpgrader.RevShareConfig[] memory configs = - new RevShareContractsUpgrader.RevShareConfig[](portals.length); - for (uint256 i; i < portals.length; i++) { string memory basePath = string.concat(".configs[", vm.toString(i), "]"); - configs[i] = RevShareContractsUpgrader.RevShareConfig({ + revShareConfigs.push(RevShareContractsUpgrader.RevShareConfig({ portal: tomlContent.readAddress(string.concat(basePath, ".portal")), l1WithdrawerConfig: RevShareContractsUpgrader.L1WithdrawerConfig({ minWithdrawalAmount: tomlContent.readUint(string.concat(basePath, ".l1WithdrawerConfig.minWithdrawalAmount")), @@ -75,21 +70,16 @@ contract RevShareUpgradeAndSetup is OPCMTaskBase { gasLimit: uint32(tomlContent.readUint(string.concat(basePath, ".l1WithdrawerConfig.gasLimit"))) }), chainFeesRecipient: tomlContent.readAddress(string.concat(basePath, ".chainFeesRecipient")) - }); + })); } - revShareConfigsEncoded = abi.encode(configs); } /// @notice Builds the actions for executing the operations. function _build(address) internal override { - // Decode configs from storage - RevShareContractsUpgrader.RevShareConfig[] memory configs = - abi.decode(revShareConfigsEncoded, (RevShareContractsUpgrader.RevShareConfig[])); - // Delegatecall into RevShareContractsUpgrader // OPCMTaskBase uses Multicall3Delegatecall, so this delegatecall will be captured as an action (bool success,) = REV_SHARE_UPGRADER.delegatecall( - abi.encodeCall(RevShareContractsUpgrader.upgradeAndSetupRevShare, (configs)) + abi.encodeCall(RevShareContractsUpgrader.upgradeAndSetupRevShare, (revShareConfigs)) ); require(success, "RevShareUpgradeAndSetup: Delegatecall failed"); } From 2d7e5af1fe026da1e493167352a17f0fc60df278 Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Tue, 11 Nov 2025 13:59:25 -0300 Subject: [PATCH 54/69] refactor: remove unnecessary for loop --- src/template/RevShareUpgradeAndSetup.sol | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/src/template/RevShareUpgradeAndSetup.sol b/src/template/RevShareUpgradeAndSetup.sol index 126107c217..46f938b446 100644 --- a/src/template/RevShareUpgradeAndSetup.sol +++ b/src/template/RevShareUpgradeAndSetup.sol @@ -93,21 +93,15 @@ contract RevShareUpgradeAndSetup is OPCMTaskBase { require(_actions.length == 1, "Expected exactly one action"); - bool foundDelegatecall = false; - - for (uint256 i; i < _actions.length; i++) { - Action memory action = _actions[i]; - // Check if this is a delegatecall to RevShareContractsUpgrader - if (action.target == REV_SHARE_UPGRADER) { - foundDelegatecall = true; - // Verify it's calling upgradeAndSetupRevShare - bytes4 selector = bytes4(action.arguments); - require( - selector == RevShareContractsUpgrader.upgradeAndSetupRevShare.selector, - "Wrong function selector for delegatecall" - ); - } - } + Action memory action = _actions[0]; + require(action.target == REV_SHARE_UPGRADER, "Delegatecall to RevShareContractsUpgrader not found"); + // Verify it's calling upgradeAndSetupRevShare + bytes4 selector = bytes4(action.arguments); + require( + selector == RevShareContractsUpgrader.upgradeAndSetupRevShare.selector, + "Wrong function selector for delegatecall" + ); + require(foundDelegatecall, "Delegatecall to RevShareContractsUpgrader not found"); } From 4baf4483aee65cb4dea655eea681edb06c4245d6 Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Tue, 11 Nov 2025 14:08:07 -0300 Subject: [PATCH 55/69] fix: broken validation --- src/template/RevShareUpgradeAndSetup.sol | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/template/RevShareUpgradeAndSetup.sol b/src/template/RevShareUpgradeAndSetup.sol index 46f938b446..ccce4fb1fa 100644 --- a/src/template/RevShareUpgradeAndSetup.sol +++ b/src/template/RevShareUpgradeAndSetup.sol @@ -101,9 +101,6 @@ contract RevShareUpgradeAndSetup is OPCMTaskBase { selector == RevShareContractsUpgrader.upgradeAndSetupRevShare.selector, "Wrong function selector for delegatecall" ); - - - require(foundDelegatecall, "Delegatecall to RevShareContractsUpgrader not found"); } /// @notice Override to return a list of addresses that should not be checked for code length. From ef6f9008d1ea5d5607fda7ce5fc1e1f512909557 Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Tue, 11 Nov 2025 14:09:09 -0300 Subject: [PATCH 56/69] refactor: improve var naming --- src/RevShareContractsUpgrader.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol index 5fbb4a9cf7..fa0a63d22f 100644 --- a/src/RevShareContractsUpgrader.sol +++ b/src/RevShareContractsUpgrader.sol @@ -138,14 +138,14 @@ contract RevShareContractsUpgrader { abi.encode(_l1WithdrawerConfig.minWithdrawalAmount, _l1WithdrawerConfig.recipient, _l1WithdrawerConfig.gasLimit) ); bytes32 l1WithdrawerSalt = _getSalt("L1Withdrawer"); - address l1Withdrawer = Utils.getCreate2Address(l1WithdrawerSalt, l1WithdrawerInitCode, RevShareLibrary.CREATE2_DEPLOYER); + 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(l1Withdrawer, _chainFeesRecipient)); + bytes.concat(RevShareLibrary.scRevShareCalculatorCreationCode, abi.encode(precalculatedL1Withdrawer, _chainFeesRecipient)); bytes32 calculatorSalt = _getSalt("SCRevShareCalculator"); calculator = Utils.getCreate2Address(calculatorSalt, calculatorInitCode, RevShareLibrary.CREATE2_DEPLOYER); _depositCreate2( From 7c143e064c8f37f640c1f25ffa718eef965a5cae Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Tue, 11 Nov 2025 14:10:09 -0300 Subject: [PATCH 57/69] refactor: improve var naming --- src/RevShareContractsUpgrader.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol index fa0a63d22f..ef3a540e7d 100644 --- a/src/RevShareContractsUpgrader.sol +++ b/src/RevShareContractsUpgrader.sol @@ -66,7 +66,7 @@ contract RevShareContractsUpgrader { if (config.chainFeesRecipient == address(0)) revert ChainFeesRecipientCannotBeZeroAddress(); // Deploy L1Withdrawer and SuperchainRevenueShareCalculator - address calculator = _deployRevSharePeriphery(config.portal, config.l1WithdrawerConfig, config.chainFeesRecipient); + 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 @@ -85,7 +85,7 @@ contract RevShareContractsUpgrader { RevShareLibrary.UPGRADE_GAS_LIMIT, abi.encodeCall( IProxyAdmin.upgradeAndCall, - (payable(RevShareLibrary.FEE_SPLITTER), feeSplitterImpl, abi.encodeCall(IFeeSplitter.initialize, (calculator))) + (payable(RevShareLibrary.FEE_SPLITTER), feeSplitterImpl, abi.encodeCall(IFeeSplitter.initialize, (precalculatedCalculator))) ) ); From 617a779bfad2207546bca7ea7631977446378b3f Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Tue, 11 Nov 2025 15:13:19 -0300 Subject: [PATCH 58/69] feat: improve template validations --- src/template/RevShareUpgradeAndSetup.sol | 59 ++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/src/template/RevShareUpgradeAndSetup.sol b/src/template/RevShareUpgradeAndSetup.sol index ccce4fb1fa..490deeec71 100644 --- a/src/template/RevShareUpgradeAndSetup.sol +++ b/src/template/RevShareUpgradeAndSetup.sol @@ -95,12 +95,71 @@ contract RevShareUpgradeAndSetup is OPCMTaskBase { Action memory action = _actions[0]; require(action.target == REV_SHARE_UPGRADER, "Delegatecall to RevShareContractsUpgrader not found"); + require(action.value == 0, "Call value must be 0 for delegatecall"); + // Verify it's calling upgradeAndSetupRevShare bytes4 selector = bytes4(action.arguments); require( selector == RevShareContractsUpgrader.upgradeAndSetupRevShare.selector, "Wrong function selector for delegatecall" ); + + // Decode and validate the revShareConfigs argument + bytes memory args = action.arguments; + RevShareContractsUpgrader.RevShareConfig[] memory configs; + assembly { + // Skip the function selector (4 bytes) to get to the actual arguments + let argsPtr := add(args, 0x04) + // The first 32 bytes after selector contain the offset to the array + // Load from memory at that location + configs := add(argsPtr, mload(add(argsPtr, 0x20))) + } + + // Validate each config + require(configs.length > 0, "No configs provided"); + require(configs.length == revShareConfigs.length, "Config length mismatch"); + + for (uint256 i; i < configs.length; i++) { + RevShareContractsUpgrader.RevShareConfig memory config = configs[i]; + + // Validate portal address is not zero + require(config.portal != address(0), "Portal address cannot be zero"); + + // Validate L1 withdrawer config + require( + config.l1WithdrawerConfig.recipient != address(0), + "L1 withdrawer recipient cannot be zero" + ); + require( + config.l1WithdrawerConfig.gasLimit > 0, + "Gas limit must be greater than 0" + ); + + // Validate chain fees recipient + require( + config.chainFeesRecipient != address(0), + "Chain fees recipient cannot be zero" + ); + + // Validate config matches the expected config from template setup + require(config.portal == revShareConfigs[i].portal, "Portal address mismatch"); + require( + config.l1WithdrawerConfig.minWithdrawalAmount == revShareConfigs[i].l1WithdrawerConfig.minWithdrawalAmount, + "Min withdrawal amount mismatch" + ); + require( + config.l1WithdrawerConfig.recipient == revShareConfigs[i].l1WithdrawerConfig.recipient, + "L1 withdrawer recipient mismatch" + ); + require( + config.l1WithdrawerConfig.gasLimit == revShareConfigs[i].l1WithdrawerConfig.gasLimit, + "Gas limit mismatch" + ); + require( + config.chainFeesRecipient == revShareConfigs[i].chainFeesRecipient, + "Chain fees recipient mismatch" + ); + } } /// @notice Override to return a list of addresses that should not be checked for code length. From 491dfc715d1ddad15ae7ae32df6bd25121dadd66 Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Tue, 11 Nov 2025 15:32:11 -0300 Subject: [PATCH 59/69] refactor: remove assembly usage --- src/template/RevShareUpgradeAndSetup.sol | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/template/RevShareUpgradeAndSetup.sol b/src/template/RevShareUpgradeAndSetup.sol index 490deeec71..04f591f669 100644 --- a/src/template/RevShareUpgradeAndSetup.sol +++ b/src/template/RevShareUpgradeAndSetup.sol @@ -105,14 +105,15 @@ contract RevShareUpgradeAndSetup is OPCMTaskBase { ); // Decode and validate the revShareConfigs argument - bytes memory args = action.arguments; + // Skip the first 4 bytes (function selector) and decode the rest RevShareContractsUpgrader.RevShareConfig[] memory configs; - assembly { - // Skip the function selector (4 bytes) to get to the actual arguments - let argsPtr := add(args, 0x04) - // The first 32 bytes after selector contain the offset to the array - // Load from memory at that location - configs := add(argsPtr, mload(add(argsPtr, 0x20))) + { + bytes memory args = action.arguments; + bytes memory argsWithoutSelector = new bytes(args.length - 4); + for (uint256 j = 4; j < args.length; j++) { + argsWithoutSelector[j - 4] = args[j]; + } + configs = abi.decode(argsWithoutSelector, (RevShareContractsUpgrader.RevShareConfig[])); } // Validate each config From 6e57f0c5a4f7b9b0d611cdd19b731b780ae7171a Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Tue, 11 Nov 2025 15:34:51 -0300 Subject: [PATCH 60/69] feat: use same impl for BaseFeeVault and L1FeeVault --- src/RevShareContractsUpgrader.sol | 110 +++- src/libraries/RevShareLibrary.sol | 4 +- src/template/RevenueShareUpgradePath.sol | 660 ----------------------- 3 files changed, 82 insertions(+), 692 deletions(-) delete mode 100644 src/template/RevenueShareUpgradePath.sol diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol index ef3a540e7d..3f5c033b0b 100644 --- a/src/RevShareContractsUpgrader.sol +++ b/src/RevShareContractsUpgrader.sol @@ -172,39 +172,91 @@ contract RevShareContractsUpgrader { } /// @notice Upgrades all 4 vaults with RevShare configuration (recipient=FeeSplitter, minWithdrawal=0, network=L2). + /// Deploys only 3 implementations: OperatorFeeVault, SequencerFeeVault, and a default FeeVault used for both BaseFeeVault and L1FeeVault. /// @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.baseFeeVaultCreationCode, - RevShareLibrary.l1FeeVaultCreationCode - ]; - string[4] memory vaultNames = ["OperatorFeeVault", "SequencerFeeVault", "BaseFeeVault", "L1FeeVault"]; - - for (uint256 i; i < vaultProxies.length; i++) { - bytes32 salt = _getSalt(vaultNames[i]); - address 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) // recipient=FeeSplitter, minWithdrawal=0, network=L2 - ) + // Deploy OperatorFeeVault implementation + bytes32 operatorSalt = _getSalt("OperatorFeeVault"); + address operatorImpl = Utils.getCreate2Address(operatorSalt, RevShareLibrary.operatorFeeVaultCreationCode, RevShareLibrary.CREATE2_DEPLOYER); + _depositCreate2(_portal, RevShareLibrary.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, operatorSalt, RevShareLibrary.operatorFeeVaultCreationCode); + _depositCall( + _portal, + address(RevShareLibrary.PROXY_ADMIN), + RevShareLibrary.UPGRADE_GAS_LIMIT, + abi.encodeCall( + IProxyAdmin.upgradeAndCall, + ( + payable(RevShareLibrary.OPERATOR_FEE_VAULT), + operatorImpl, + abi.encodeCall( + IFeeVault.initialize, + (RevShareLibrary.FEE_SPLITTER, 0, IFeeVault.WithdrawalNetwork.L2) ) ) - ); - } + ) + ); + + // Deploy SequencerFeeVault implementation + bytes32 sequencerSalt = _getSalt("SequencerFeeVault"); + address sequencerImpl = Utils.getCreate2Address(sequencerSalt, RevShareLibrary.sequencerFeeVaultCreationCode, RevShareLibrary.CREATE2_DEPLOYER); + _depositCreate2(_portal, RevShareLibrary.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, sequencerSalt, RevShareLibrary.sequencerFeeVaultCreationCode); + _depositCall( + _portal, + address(RevShareLibrary.PROXY_ADMIN), + RevShareLibrary.UPGRADE_GAS_LIMIT, + abi.encodeCall( + IProxyAdmin.upgradeAndCall, + ( + payable(RevShareLibrary.SEQUENCER_FEE_WALLET), + sequencerImpl, + abi.encodeCall( + IFeeVault.initialize, + (RevShareLibrary.FEE_SPLITTER, 0, IFeeVault.WithdrawalNetwork.L2) + ) + ) + ) + ); + + // Deploy default FeeVault implementation (used for both BaseFeeVault and L1FeeVault) + bytes32 defaultSalt = _getSalt("DefaultFeeVault"); + address defaultImpl = Utils.getCreate2Address(defaultSalt, RevShareLibrary.defaultFeeVaultCreationCode, RevShareLibrary.CREATE2_DEPLOYER); + _depositCreate2(_portal, RevShareLibrary.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, defaultSalt, RevShareLibrary.defaultFeeVaultCreationCode); + + // Upgrade BaseFeeVault with default implementation + _depositCall( + _portal, + address(RevShareLibrary.PROXY_ADMIN), + RevShareLibrary.UPGRADE_GAS_LIMIT, + abi.encodeCall( + IProxyAdmin.upgradeAndCall, + ( + payable(RevShareLibrary.BASE_FEE_VAULT), + defaultImpl, + abi.encodeCall( + IFeeVault.initialize, + (RevShareLibrary.FEE_SPLITTER, 0, IFeeVault.WithdrawalNetwork.L2) + ) + ) + ) + ); + + // Upgrade L1FeeVault with default implementation + _depositCall( + _portal, + address(RevShareLibrary.PROXY_ADMIN), + RevShareLibrary.UPGRADE_GAS_LIMIT, + abi.encodeCall( + IProxyAdmin.upgradeAndCall, + ( + payable(RevShareLibrary.L1_FEE_VAULT), + defaultImpl, + abi.encodeCall( + IFeeVault.initialize, + (RevShareLibrary.FEE_SPLITTER, 0, IFeeVault.WithdrawalNetwork.L2) + ) + ) + ) + ); } /// @notice Helper for CREATE2 contract deployments via depositTransaction. diff --git a/src/libraries/RevShareLibrary.sol b/src/libraries/RevShareLibrary.sol index 5c57d590aa..46ee584efb 100644 --- a/src/libraries/RevShareLibrary.sol +++ b/src/libraries/RevShareLibrary.sol @@ -14,9 +14,7 @@ library RevShareLibrary { hex"6080604052348015600e575f80fd5b5060156019565b60c9565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff161560685760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b039081161460c65780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b610e8d806100d65f395ff3fe6080604052600436106100d1575f3560e01c806382356d8a1161007c57806385b5b14d1161005757806385b5b14d14610276578063b49dc74114610295578063d0e12f90146102b4578063d3e5792b146102e3575f80fd5b806382356d8a1461020f5780638312f1491461024d57806384411d6514610262575f80fd5b80633ccfd60b116100ac5780633ccfd60b1461016c57806354fd4d501461018e57806366d003ac146101e3575f80fd5b80630d9019e1146100dc578063307f29621461012c5780633bbed4a01461014d575f80fd5b366100d857005b5f80fd5b3480156100e7575f80fd5b5060025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b348015610137575f80fd5b5061014b610146366004610c5a565b6102f7565b005b348015610158575f80fd5b5061014b610167366004610c97565b61047a565b348015610177575f80fd5b506101806105de565b604051908152602001610123565b348015610199575f80fd5b506101d66040518060400160405280600581526020017f312e312e3000000000000000000000000000000000000000000000000000000081525081565b6040516101239190610cb2565b3480156101ee575f80fd5b506002546101029073ffffffffffffffffffffffffffffffffffffffff1681565b34801561021a575f80fd5b506002546102409074010000000000000000000000000000000000000000900460ff1681565b6040516101239190610d6b565b348015610258575f80fd5b5061018060015481565b34801561026d575f80fd5b506101805f5481565b348015610281575f80fd5b5061014b610290366004610d7f565b6108ec565b3480156102a0575f80fd5b5061014b6102af366004610d96565b610a0f565b3480156102bf575f80fd5b5060025474010000000000000000000000000000000000000000900460ff16610240565b3480156102ee575f80fd5b50600154610180565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610354573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103789190610dd1565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146103dc576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547401000000000000000000000000000000000000000080820460ff1692849290917fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff9091169083600181111561043857610438610d05565b02179055507ff2ec44eb1c3b3acd547b76333eb2c4b27eee311860c57a9fdb04c95f62398fc8818360405161046e929190610dec565b60405180910390a15050565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104fb9190610dd1565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461055f576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f62e69886a5df0ba8ffcacbfc1388754e7abd9bde24b036354c561f1acd4e4593910161046e565b5f60015447101561069c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f4665655661756c743a207769746864726177616c20616d6f756e74206d75737460448201527f2062652067726561746572207468616e206d696e696d756d207769746864726160648201527f77616c20616d6f756e7400000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b479050805f808282546106af9190610e07565b90915550506002546040805183815273ffffffffffffffffffffffffffffffffffffffff909216602083018190523383830152905190917fc8a211cc64b6ed1b50595a9fcb1932b6d1e5a6e8ef15b60e5b1f988ea9086bba919081900360600190a16002546040517f38e04cbeb8c10f8f568618aa75be0f10b6729b8b4237743b4de20cbcde2839ee916107649185918591339174010000000000000000000000000000000000000000900460ff1690610e3f565b60405180910390a1600160025474010000000000000000000000000000000000000000900460ff16600181111561079d5761079d610d05565b03610841575f6107ad8284610c23565b90508061083c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4665655661756c743a206661696c656420746f2073656e642045544820746f2060448201527f4c322066656520726563697069656e74000000000000000000000000000000006064820152608401610693565b505090565b6040517fc2b3e5ac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015262061a806024820152606060448201525f60648201527342000000000000000000000000000000000000169063c2b3e5ac9084906084015f604051808303818588803b1580156108d1575f80fd5b505af11580156108e3573d5f803e3d5ffd5b50505050505090565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610949573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061096d9190610dd1565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109d1576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180549082905560408051828152602081018490527f895a067c78583e800418fabf3da26a9496aab2ff3429cebdf7fefa642b2e4203910161046e565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f81158015610a595750825b90505f8267ffffffffffffffff166001148015610a755750303b155b905081158015610a83575080155b15610aba576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001660011785558315610b1b5784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b6002805473ffffffffffffffffffffffffffffffffffffffff8a167fffffffffffffffffffffffff000000000000000000000000000000000000000082168117835560018a81558993927fffffffffffffffffffffff000000000000000000000000000000000000000000169091179074010000000000000000000000000000000000000000908490811115610bb357610bb3610d05565b02179055508315610c195784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050565b5f610c2f835a84610c36565b9392505050565b5f805f805f858888f1949350505050565b803560028110610c55575f80fd5b919050565b5f60208284031215610c6a575f80fd5b610c2f82610c47565b73ffffffffffffffffffffffffffffffffffffffff81168114610c94575f80fd5b50565b5f60208284031215610ca7575f80fd5b8135610c2f81610c73565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60028110610d67577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b9052565b60208101610d798284610d32565b92915050565b5f60208284031215610d8f575f80fd5b5035919050565b5f805f60608486031215610da8575f80fd5b8335610db381610c73565b925060208401359150610dc860408501610c47565b90509250925092565b5f60208284031215610de1575f80fd5b8151610c2f81610c73565b60408101610dfa8285610d32565b610c2f6020830184610d32565b80820180821115610d79577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b84815273ffffffffffffffffffffffffffffffffffffffff84811660208301528316604082015260808101610e776060830184610d32565b9594505050505056fea164736f6c6343000819000a"; bytes public constant sequencerFeeVaultCreationCode = hex"6080604052348015600e575f80fd5b5060156019565b60c9565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff161560685760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b039081161460c65780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b610e98806100d65f395ff3fe6080604052600436106100dc575f3560e01c80638312f1491161007c578063b49dc74111610057578063b49dc741146102a0578063d0e12f90146102bf578063d3e5792b146102ee578063d4ff9218146100e7575f80fd5b80638312f1491461025857806384411d651461026d57806385b5b14d14610281575f80fd5b80633ccfd60b116100b75780633ccfd60b1461017757806354fd4d501461019957806366d003ac146101ee57806382356d8a1461021a575f80fd5b80630d9019e1146100e7578063307f2962146101375780633bbed4a014610158575f80fd5b366100e357005b5f80fd5b3480156100f2575f80fd5b5060025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b348015610142575f80fd5b50610156610151366004610c65565b610302565b005b348015610163575f80fd5b50610156610172366004610ca2565b610485565b348015610182575f80fd5b5061018b6105e9565b60405190815260200161012e565b3480156101a4575f80fd5b506101e16040518060400160405280600581526020017f312e362e3000000000000000000000000000000000000000000000000000000081525081565b60405161012e9190610cbd565b3480156101f9575f80fd5b5060025461010d9073ffffffffffffffffffffffffffffffffffffffff1681565b348015610225575f80fd5b5060025461024b9074010000000000000000000000000000000000000000900460ff1681565b60405161012e9190610d76565b348015610263575f80fd5b5061018b60015481565b348015610278575f80fd5b5061018b5f5481565b34801561028c575f80fd5b5061015661029b366004610d8a565b6108f7565b3480156102ab575f80fd5b506101566102ba366004610da1565b610a1a565b3480156102ca575f80fd5b5060025474010000000000000000000000000000000000000000900460ff1661024b565b3480156102f9575f80fd5b5060015461018b565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561035f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103839190610ddc565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146103e7576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547401000000000000000000000000000000000000000080820460ff1692849290917fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff9091169083600181111561044357610443610d10565b02179055507ff2ec44eb1c3b3acd547b76333eb2c4b27eee311860c57a9fdb04c95f62398fc88183604051610479929190610df7565b60405180910390a15050565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104e2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105069190610ddc565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461056a576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f62e69886a5df0ba8ffcacbfc1388754e7abd9bde24b036354c561f1acd4e45939101610479565b5f6001544710156106a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f4665655661756c743a207769746864726177616c20616d6f756e74206d75737460448201527f2062652067726561746572207468616e206d696e696d756d207769746864726160648201527f77616c20616d6f756e7400000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b479050805f808282546106ba9190610e12565b90915550506002546040805183815273ffffffffffffffffffffffffffffffffffffffff909216602083018190523383830152905190917fc8a211cc64b6ed1b50595a9fcb1932b6d1e5a6e8ef15b60e5b1f988ea9086bba919081900360600190a16002546040517f38e04cbeb8c10f8f568618aa75be0f10b6729b8b4237743b4de20cbcde2839ee9161076f9185918591339174010000000000000000000000000000000000000000900460ff1690610e4a565b60405180910390a1600160025474010000000000000000000000000000000000000000900460ff1660018111156107a8576107a8610d10565b0361084c575f6107b88284610c2e565b905080610847576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4665655661756c743a206661696c656420746f2073656e642045544820746f2060448201527f4c322066656520726563697069656e7400000000000000000000000000000000606482015260840161069e565b505090565b6040517fc2b3e5ac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015262061a806024820152606060448201525f60648201527342000000000000000000000000000000000000169063c2b3e5ac9084906084015f604051808303818588803b1580156108dc575f80fd5b505af11580156108ee573d5f803e3d5ffd5b50505050505090565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610954573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109789190610ddc565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109dc576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180549082905560408051828152602081018490527f895a067c78583e800418fabf3da26a9496aab2ff3429cebdf7fefa642b2e42039101610479565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f81158015610a645750825b90505f8267ffffffffffffffff166001148015610a805750303b155b905081158015610a8e575080155b15610ac5576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001660011785558315610b265784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b6002805473ffffffffffffffffffffffffffffffffffffffff8a167fffffffffffffffffffffffff000000000000000000000000000000000000000082168117835560018a81558993927fffffffffffffffffffffff000000000000000000000000000000000000000000169091179074010000000000000000000000000000000000000000908490811115610bbe57610bbe610d10565b02179055508315610c245784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050565b5f610c3a835a84610c41565b9392505050565b5f805f805f858888f1949350505050565b803560028110610c60575f80fd5b919050565b5f60208284031215610c75575f80fd5b610c3a82610c52565b73ffffffffffffffffffffffffffffffffffffffff81168114610c9f575f80fd5b50565b5f60208284031215610cb2575f80fd5b8135610c3a81610c7e565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60028110610d72577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b9052565b60208101610d848284610d3d565b92915050565b5f60208284031215610d9a575f80fd5b5035919050565b5f805f60608486031215610db3575f80fd5b8335610dbe81610c7e565b925060208401359150610dd360408501610c52565b90509250925092565b5f60208284031215610dec575f80fd5b8151610c3a81610c7e565b60408101610e058285610d3d565b610c3a6020830184610d3d565b80820180821115610d84577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b84815273ffffffffffffffffffffffffffffffffffffffff84811660208301528316604082015260808101610e826060830184610d3d565b9594505050505056fea164736f6c6343000819000a"; - bytes public constant baseFeeVaultCreationCode = - hex"6080604052348015600e575f80fd5b5060156019565b60c9565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff161560685760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b039081161460c65780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b610e8d806100d65f395ff3fe6080604052600436106100d1575f3560e01c806382356d8a1161007c57806385b5b14d1161005757806385b5b14d14610276578063b49dc74114610295578063d0e12f90146102b4578063d3e5792b146102e3575f80fd5b806382356d8a1461020f5780638312f1491461024d57806384411d6514610262575f80fd5b80633ccfd60b116100ac5780633ccfd60b1461016c57806354fd4d501461018e57806366d003ac146101e3575f80fd5b80630d9019e1146100dc578063307f29621461012c5780633bbed4a01461014d575f80fd5b366100d857005b5f80fd5b3480156100e7575f80fd5b5060025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b348015610137575f80fd5b5061014b610146366004610c5a565b6102f7565b005b348015610158575f80fd5b5061014b610167366004610c97565b61047a565b348015610177575f80fd5b506101806105de565b604051908152602001610123565b348015610199575f80fd5b506101d66040518060400160405280600581526020017f312e362e3000000000000000000000000000000000000000000000000000000081525081565b6040516101239190610cb2565b3480156101ee575f80fd5b506002546101029073ffffffffffffffffffffffffffffffffffffffff1681565b34801561021a575f80fd5b506002546102409074010000000000000000000000000000000000000000900460ff1681565b6040516101239190610d6b565b348015610258575f80fd5b5061018060015481565b34801561026d575f80fd5b506101805f5481565b348015610281575f80fd5b5061014b610290366004610d7f565b6108ec565b3480156102a0575f80fd5b5061014b6102af366004610d96565b610a0f565b3480156102bf575f80fd5b5060025474010000000000000000000000000000000000000000900460ff16610240565b3480156102ee575f80fd5b50600154610180565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610354573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103789190610dd1565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146103dc576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547401000000000000000000000000000000000000000080820460ff1692849290917fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff9091169083600181111561043857610438610d05565b02179055507ff2ec44eb1c3b3acd547b76333eb2c4b27eee311860c57a9fdb04c95f62398fc8818360405161046e929190610dec565b60405180910390a15050565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104fb9190610dd1565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461055f576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f62e69886a5df0ba8ffcacbfc1388754e7abd9bde24b036354c561f1acd4e4593910161046e565b5f60015447101561069c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f4665655661756c743a207769746864726177616c20616d6f756e74206d75737460448201527f2062652067726561746572207468616e206d696e696d756d207769746864726160648201527f77616c20616d6f756e7400000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b479050805f808282546106af9190610e07565b90915550506002546040805183815273ffffffffffffffffffffffffffffffffffffffff909216602083018190523383830152905190917fc8a211cc64b6ed1b50595a9fcb1932b6d1e5a6e8ef15b60e5b1f988ea9086bba919081900360600190a16002546040517f38e04cbeb8c10f8f568618aa75be0f10b6729b8b4237743b4de20cbcde2839ee916107649185918591339174010000000000000000000000000000000000000000900460ff1690610e3f565b60405180910390a1600160025474010000000000000000000000000000000000000000900460ff16600181111561079d5761079d610d05565b03610841575f6107ad8284610c23565b90508061083c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4665655661756c743a206661696c656420746f2073656e642045544820746f2060448201527f4c322066656520726563697069656e74000000000000000000000000000000006064820152608401610693565b505090565b6040517fc2b3e5ac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015262061a806024820152606060448201525f60648201527342000000000000000000000000000000000000169063c2b3e5ac9084906084015f604051808303818588803b1580156108d1575f80fd5b505af11580156108e3573d5f803e3d5ffd5b50505050505090565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610949573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061096d9190610dd1565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109d1576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180549082905560408051828152602081018490527f895a067c78583e800418fabf3da26a9496aab2ff3429cebdf7fefa642b2e4203910161046e565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f81158015610a595750825b90505f8267ffffffffffffffff166001148015610a755750303b155b905081158015610a83575080155b15610aba576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001660011785558315610b1b5784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b6002805473ffffffffffffffffffffffffffffffffffffffff8a167fffffffffffffffffffffffff000000000000000000000000000000000000000082168117835560018a81558993927fffffffffffffffffffffff000000000000000000000000000000000000000000169091179074010000000000000000000000000000000000000000908490811115610bb357610bb3610d05565b02179055508315610c195784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050565b5f610c2f835a84610c36565b9392505050565b5f805f805f858888f1949350505050565b803560028110610c55575f80fd5b919050565b5f60208284031215610c6a575f80fd5b610c2f82610c47565b73ffffffffffffffffffffffffffffffffffffffff81168114610c94575f80fd5b50565b5f60208284031215610ca7575f80fd5b8135610c2f81610c73565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60028110610d67577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b9052565b60208101610d798284610d32565b92915050565b5f60208284031215610d8f575f80fd5b5035919050565b5f805f60608486031215610da8575f80fd5b8335610db381610c73565b925060208401359150610dc860408501610c47565b90509250925092565b5f60208284031215610de1575f80fd5b8151610c2f81610c73565b60408101610dfa8285610d32565b610c2f6020830184610d32565b80820180821115610d79577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b84815273ffffffffffffffffffffffffffffffffffffffff84811660208301528316604082015260808101610e776060830184610d32565b9594505050505056fea164736f6c6343000819000a"; - bytes public constant l1FeeVaultCreationCode = + bytes public constant defaultFeeVaultCreationCode = hex"6080604052348015600e575f80fd5b5060156019565b60c9565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff161560685760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b039081161460c65780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b610e8d806100d65f395ff3fe6080604052600436106100d1575f3560e01c806382356d8a1161007c57806385b5b14d1161005757806385b5b14d14610276578063b49dc74114610295578063d0e12f90146102b4578063d3e5792b146102e3575f80fd5b806382356d8a1461020f5780638312f1491461024d57806384411d6514610262575f80fd5b80633ccfd60b116100ac5780633ccfd60b1461016c57806354fd4d501461018e57806366d003ac146101e3575f80fd5b80630d9019e1146100dc578063307f29621461012c5780633bbed4a01461014d575f80fd5b366100d857005b5f80fd5b3480156100e7575f80fd5b5060025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b348015610137575f80fd5b5061014b610146366004610c5a565b6102f7565b005b348015610158575f80fd5b5061014b610167366004610c97565b61047a565b348015610177575f80fd5b506101806105de565b604051908152602001610123565b348015610199575f80fd5b506101d66040518060400160405280600581526020017f312e362e3000000000000000000000000000000000000000000000000000000081525081565b6040516101239190610cb2565b3480156101ee575f80fd5b506002546101029073ffffffffffffffffffffffffffffffffffffffff1681565b34801561021a575f80fd5b506002546102409074010000000000000000000000000000000000000000900460ff1681565b6040516101239190610d6b565b348015610258575f80fd5b5061018060015481565b34801561026d575f80fd5b506101805f5481565b348015610281575f80fd5b5061014b610290366004610d7f565b6108ec565b3480156102a0575f80fd5b5061014b6102af366004610d96565b610a0f565b3480156102bf575f80fd5b5060025474010000000000000000000000000000000000000000900460ff16610240565b3480156102ee575f80fd5b50600154610180565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610354573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103789190610dd1565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146103dc576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547401000000000000000000000000000000000000000080820460ff1692849290917fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff9091169083600181111561043857610438610d05565b02179055507ff2ec44eb1c3b3acd547b76333eb2c4b27eee311860c57a9fdb04c95f62398fc8818360405161046e929190610dec565b60405180910390a15050565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104fb9190610dd1565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461055f576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f62e69886a5df0ba8ffcacbfc1388754e7abd9bde24b036354c561f1acd4e4593910161046e565b5f60015447101561069c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f4665655661756c743a207769746864726177616c20616d6f756e74206d75737460448201527f2062652067726561746572207468616e206d696e696d756d207769746864726160648201527f77616c20616d6f756e7400000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b479050805f808282546106af9190610e07565b90915550506002546040805183815273ffffffffffffffffffffffffffffffffffffffff909216602083018190523383830152905190917fc8a211cc64b6ed1b50595a9fcb1932b6d1e5a6e8ef15b60e5b1f988ea9086bba919081900360600190a16002546040517f38e04cbeb8c10f8f568618aa75be0f10b6729b8b4237743b4de20cbcde2839ee916107649185918591339174010000000000000000000000000000000000000000900460ff1690610e3f565b60405180910390a1600160025474010000000000000000000000000000000000000000900460ff16600181111561079d5761079d610d05565b03610841575f6107ad8284610c23565b90508061083c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4665655661756c743a206661696c656420746f2073656e642045544820746f2060448201527f4c322066656520726563697069656e74000000000000000000000000000000006064820152608401610693565b505090565b6040517fc2b3e5ac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015262061a806024820152606060448201525f60648201527342000000000000000000000000000000000000169063c2b3e5ac9084906084015f604051808303818588803b1580156108d1575f80fd5b505af11580156108e3573d5f803e3d5ffd5b50505050505090565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610949573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061096d9190610dd1565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109d1576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180549082905560408051828152602081018490527f895a067c78583e800418fabf3da26a9496aab2ff3429cebdf7fefa642b2e4203910161046e565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f81158015610a595750825b90505f8267ffffffffffffffff166001148015610a755750303b155b905081158015610a83575080155b15610aba576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001660011785558315610b1b5784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b6002805473ffffffffffffffffffffffffffffffffffffffff8a167fffffffffffffffffffffffff000000000000000000000000000000000000000082168117835560018a81558993927fffffffffffffffffffffff000000000000000000000000000000000000000000169091179074010000000000000000000000000000000000000000908490811115610bb357610bb3610d05565b02179055508315610c195784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050565b5f610c2f835a84610c36565b9392505050565b5f805f805f858888f1949350505050565b803560028110610c55575f80fd5b919050565b5f60208284031215610c6a575f80fd5b610c2f82610c47565b73ffffffffffffffffffffffffffffffffffffffff81168114610c94575f80fd5b50565b5f60208284031215610ca7575f80fd5b8135610c2f81610c73565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60028110610d67577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b9052565b60208101610d798284610d32565b92915050565b5f60208284031215610d8f575f80fd5b5035919050565b5f805f60608486031215610da8575f80fd5b8335610db381610c73565b925060208401359150610dc860408501610c47565b90509250925092565b5f60208284031215610de1575f80fd5b8151610c2f81610c73565b60408101610dfa8285610d32565b610c2f6020830184610d32565b80820180821115610d79577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b84815273ffffffffffffffffffffffffffffffffffffffff84811660208301528316604082015260808101610e776060830184610d32565b9594505050505056fea164736f6c6343000819000a"; bytes public constant feeSplitterCreationCode = hex"6080604052348015600e575f80fd5b5060156019565b60d4565b5f54610100900460ff161560835760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b5f5460ff908116101560d2575f805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b611308806100e15f395ff3fe608060405260043610610096575f3560e01c80637dfbd04911610066578063b87ea8d41161004c578063b87ea8d414610284578063c4d66de814610298578063d61a398b146102b7575f80fd5b80637dfbd0491461024e5780637fc81bb714610265575f80fd5b80630a7617b31461014e5780630c0544a31461016f578063394d2731146101d157806354fd4d50146101f9575f80fd5b3661014a573373ffffffffffffffffffffffffffffffffffffffff7f21346dddac42cc163a6523eefc19df981df7352c870dc3b0b17a6a92fc6fe8135c161461010b576040517f14885cf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805134815247602082018190529133917f213e72af0d3613bd643cff3059f872c1015e6541624e37872bf95eefbaf220a8910160405180910390a2005b5f80fd5b348015610159575f80fd5b5061016d610168366004610f49565b61030d565b005b34801561017a575f80fd5b506001546101ab9070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1681565b6040516fffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101dc575f80fd5b506001546101ab906fffffffffffffffffffffffffffffffff1681565b348015610204575f80fd5b506102416040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516101c89190610f64565b348015610259575f80fd5b506101ab6301e1338081565b348015610270575f80fd5b5061016d61027f366004610fb7565b6104cf565b34801561028f575f80fd5b5061016d6106c2565b3480156102a3575f80fd5b5061016d6102b2366004610f49565b610a9a565b3480156102c2575f80fd5b505f546102e89062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101c8565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561036a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061038e9190610fe6565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146103f2576040517f38bac74200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff811661043f576040517f99c6ec0800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f805473ffffffffffffffffffffffffffffffffffffffff838116620100008181027fffffffffffffffffffff0000000000000000000000000000000000000000ffff85161790945560408051949093049091168084526020840191909152917f16417cc372deec0caee5f52e2ad77a5f07b4591fd56b4ff31b6e20f817d4daeb91015b60405180910390a15050565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561052c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105509190610fe6565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146105b4576040517f38bac74200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806fffffffffffffffffffffffffffffffff165f036105ff576040517fcf85916100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6301e133806fffffffffffffffffffffffffffffffff8216111561064f576040517f30b9f35e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180546fffffffffffffffffffffffffffffffff8381167001000000000000000000000000000000008181028385161790945560408051949093049091168084526020840191909152917f4492086b630ed3846eec0979dd87a71c814ceb1c6dab80ab81e3450b21e4de2891016104c3565b6001546106f7906fffffffffffffffffffffffffffffffff70010000000000000000000000000000000082048116911661102e565b6fffffffffffffffffffffffffffffffff16421015610742576040517f1e4a9f3a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffffffffffff0000000000000000000000000000000016426fffffffffffffffffffffffffffffffff161790555f61079c734200000000000000000000000000000000000011610c8e565b90505f6107bc734200000000000000000000000000000000000019610c8e565b90505f6107dc73420000000000000000000000000000000000001a610c8e565b90505f6107fc73420000000000000000000000000000000000001b610c8e565b90506108075f610edb565b5f8282610814868861105e565b61081e919061105e565b610828919061105e565b9050805f03610863576040517fc8972e5200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80546040517f54e7f42d000000000000000000000000000000000000000000000000000000008152600481018890526024810187905260448101859052606481018690526201000090910473ffffffffffffffffffffffffffffffffffffffff16906354e7f42d906084015f60405180830381865afa1580156108e9573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261092e919081019061111c565b80519091505f81900361096d576040517f763970d600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f805b82811015610a1d575f84828151811061098b5761098b6111eb565b6020026020010151602001519050805f036109a65750610a15565b5f6109cd8684815181106109bc576109bc6111eb565b60200260200101515f015183610f01565b905080610a06576040517fd68d1b1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a10828561105e565b935050505b600101610970565b50838114610a57576040517f9c01eac000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f73f9a13241a1848ec157967f3a85601709353e616f1f2605d818c0f2d21774df8385604051610a88929190611218565b60405180910390a15050505050505050565b5f54610100900460ff1615808015610ab857505f54600160ff909116105b80610ad15750303b158015610ad157505f5460ff166001145b610b61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840160405180910390fd5b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610bbd575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b5f80547fffffffffffffffffffff0000000000000000000000000000000000000000ffff166201000073ffffffffffffffffffffffffffffffffffffffff85160217905572015180000000000000000000000000000000006fffffffffffffffffffffffffffffffff4216176001558015610c8a575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498906020016104c3565b5050565b5f60018273ffffffffffffffffffffffffffffffffffffffff166382356d8a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610cda573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cfe91906112b3565b6001811115610d0f57610d0f611286565b14610d46576040517fb4726cbe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff166366d003ac6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610da6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610dca9190610fe6565b73ffffffffffffffffffffffffffffffffffffffff1614610e17576040517fc3380cef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b47610e2183610edb565b8273ffffffffffffffffffffffffffffffffffffffff16633ccfd60b6040518163ffffffff1660e01b81526004016020604051808303815f875af1158015610e6b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e8f91906112d1565b91504782610e9d83836112e8565b14610ed4576040517f87c91c5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050919050565b807f21346dddac42cc163a6523eefc19df981df7352c870dc3b0b17a6a92fc6fe8135d50565b5f610f0d835a84610f14565b9392505050565b5f805f805f858888f1949350505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f46575f80fd5b50565b5f60208284031215610f59575f80fd5b8135610f0d81610f25565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b5f60208284031215610fc7575f80fd5b81356fffffffffffffffffffffffffffffffff81168114610f0d575f80fd5b5f60208284031215610ff6575f80fd5b8151610f0d81610f25565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b6fffffffffffffffffffffffffffffffff81811683821601908082111561105757611057611001565b5092915050565b8082018082111561107157611071611001565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6040805190810167ffffffffffffffff811182821017156110c7576110c7611077565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561111457611114611077565b604052919050565b5f602080838503121561112d575f80fd5b825167ffffffffffffffff80821115611144575f80fd5b818501915085601f830112611157575f80fd5b81518181111561116957611169611077565b611177848260051b016110cd565b818152848101925060069190911b830184019087821115611196575f80fd5b928401925b818410156111e057604084890312156111b2575f80fd5b6111ba6110a4565b84516111c581610f25565b8152848601518682015283526040909301929184019161119b565b979650505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b604080825283518282018190525f91906020906060850190828801855b82811015611270578151805173ffffffffffffffffffffffffffffffffffffffff168552850151858501529285019290840190600101611235565b5050508093505050508260208301529392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b5f602082840312156112c3575f80fd5b815160028110610f0d575f80fd5b5f602082840312156112e1575f80fd5b5051919050565b818103818111156110715761107161100156fea164736f6c6343000819000a"; diff --git a/src/template/RevenueShareUpgradePath.sol b/src/template/RevenueShareUpgradePath.sol deleted file mode 100644 index 25c43a355a..0000000000 --- a/src/template/RevenueShareUpgradePath.sol +++ /dev/null @@ -1,660 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.15; - -import {VmSafe} from "forge-std/Vm.sol"; -import {LibString} from "@solady/utils/LibString.sol"; -import {stdToml} from "lib/forge-std/src/StdToml.sol"; -import {SimpleTaskBase} from "src/tasks/types/SimpleTaskBase.sol"; -import {Action} from "src/libraries/MultisigTypes.sol"; -import {MultisigTaskPrinter} from "src/libraries/MultisigTaskPrinter.sol"; -import {RevShareLibrary} from "src/libraries/RevShareLibrary.sol"; -import {Utils} from "src/libraries/Utils.sol"; - -/// @notice Interface for the OptimismPortal2 in L1. This is the main interaction point for the template. -interface IOptimismPortal2 { - function depositTransaction(address _to, uint256 _value, uint64 _gasLimit, bool _isCreation, bytes memory _data) - external - payable; -} - -/// @notice Interface of the Create2 Preinstall in L2. -interface ICreate2Deployer { - function deploy(uint256 _value, bytes32 _salt, bytes memory _code) external; -} - -/// @notice Interface for the FeeSplitter in L2. -interface IFeeSplitter { - function initialize(address _sharesCalculator) external; -} - -/// @notice Interface for the vaults in L2. -interface IFeeVault { - function initialize(address _recipient, uint256 _minWithdrawalAmount, uint8 _withdrawalNetwork) external; -} - -/// @notice Interface for ProxyAdmin. -interface IProxyAdmin { - function upgrade(address payable _proxy, address _implementation) external; - function upgradeAndCall(address payable _proxy, address _implementation, bytes memory _data) external; -} - -/// @notice A template contract for chains to upgrade to the Revenue Share v1.0.0 implementation. -contract RevenueShareV100UpgradePath is SimpleTaskBase { - using LibString for string; - using stdToml for string; - - /// @notice Used to validate calls made to the OptimismPortal. - mapping(bytes32 => uint8) internal _callsToPortal; - - /// @notice The withdrawal network configuration for the fee vaults. - uint8 public constant FEE_VAULT_WITHDRAWAL_NETWORK = 1; - - /// @notice The minimum withdrawal amount configuration for the fee vaults. - uint256 public constant FEE_VAULT_MIN_WITHDRAWAL_AMOUNT = 0; - - /// @notice The configuration for the l1 withdrawer - uint256 public l1WithdrawerMinWithdrawalAmount; - // TODO(17505): This address is expected to be set to the appropriate FeesDepositor address once deployed. - // The deployment is done by running the task at test/tasks/example/eth/016-deploy-fees-depositor - address public l1WithdrawerRecipient; - /// @notice The gas limit for the L1 Withdrawer. - uint32 public l1WithdrawerGasLimit; - - /// @notice The configuration for sc rev share calculator. - address public scRevShareCalcChainFeesRecipient; - - /// @notice Whether to use the default calculator. If true, deploy the default SC Rev Share Calculator and L1Withdrawer. - /// If false, use the custom calculator and skip deploying the default calculator and L1Withdrawer. - bool public useDefaultCalculator; - - /// @notice Custom calculator address. - address public customCalculator; - - /// @notice The address of the OptimismPortal through which we are making the deposit txns - address public portal; - - /// @notice The salt seed to be used for the L2 deployments - string public saltSeed; - - /// @notice The address the OperatorFeeVault implementation is deployed to. - address internal _operatorFeeVaultPrecalculatedAddress; - /// @notice The calldata sent to the OptimismPortal to deploy the OperatorFeeVault. - bytes internal _operatorFeeVaultCalldata; - - /// @notice The address the SequencerFeeVault implementation is deployed to. - address internal _sequencerFeeVaultPrecalculatedAddress; - /// @notice The calldata sent to the OptimismPortal to deploy the SequencerFeeVault. - bytes internal _sequencerFeeVaultCalldata; - - /// @notice The address the BaseFeeVault implementation is deployed to. - address internal _baseFeeVaultPrecalculatedAddress; - /// @notice The calldata sent to the OptimismPortal to deploy the BaseFeeVault. - bytes internal _baseFeeVaultCalldata; - - /// @notice The address the L1FeeVault implementation is deployed to. - address internal _l1FeeVaultPrecalculatedAddress; - /// @notice The calldata sent to the OptimismPortal to deploy the L1FeeVault. - bytes internal _l1FeeVaultCalldata; - - /// @notice The address the L1Withdrawer implementation is deployed to. - address internal _l1WithdrawerPrecalculatedAddress; - /// @notice The calldata sent to the OptimismPortal to deploy the L1Withdrawer. - bytes internal _l1WithdrawerCalldata; - - /// @notice The address the SuperchainRevenueShareCalculator implementation is deployed to. - address internal _scRevShareCalculatorPrecalculatedAddress; - /// @notice The calldata sent to the OptimismPortal to deploy the SuperchainRevenueShareCalculator. - bytes internal _scRevShareCalculatorCalldata; - - /// @notice The address the FeeSplitter implementation is deployed to. - address internal _feeSplitterPrecalculatedAddress; - /// @notice The calldata sent to the OptimismPortal to deploy the FeeSplitter. - bytes internal _feeSplitterCalldata; - - /// @notice Returns the safe address string identifier. - function safeAddressString() public pure override returns (string memory) { - return "ProxyAdminOwner"; - } - - /// @notice Returns the storage write permissions required for this task. This is an array of - /// contract names that are expected to be written to during the execution of the task. - function _taskStorageWrites() internal pure virtual override returns (string[] memory) { - string[] memory _storageWrites = new string[](1); - _storageWrites[0] = "OptimismPortal"; - return _storageWrites; - } - - /// @notice Returns an array of strings that refer to contract names in the address registry. - /// Contracts with these names are expected to have their balance changes during the task. - /// By default returns an empty array. Override this function if your task expects balance changes. - function _taskBalanceChanges() internal view virtual override returns (string[] memory) { - string[] memory _balanceChanges = new string[](1); - _balanceChanges[0] = "OptimismPortal"; - return _balanceChanges; - } - - /// @notice Sets up the template with implementation configurations from a TOML file. - /// State overrides are not applied yet. Keep this in mind when performing various pre-simulation assertions in this function. - function _templateSetup(string memory _taskConfigFilePath, address) internal override { - string memory _toml = vm.readFile(_taskConfigFilePath); - - portal = _toml.readAddress(".portal"); - require(portal != address(0), "portal must be set in config"); - - saltSeed = _toml.readString(".saltSeed"); - require(bytes(saltSeed).length != 0, "saltSeed must be set in the config"); - - // Read whether to use the default calculator - useDefaultCalculator = _toml.readBool(".useDefaultCalculator"); - - // If useDefaultCalculator is true, deploy the default calculator and L1Withdrawer - if (useDefaultCalculator) { - l1WithdrawerMinWithdrawalAmount = _toml.readUint(".l1WithdrawerMinWithdrawalAmount"); - - l1WithdrawerRecipient = _toml.readAddress(".l1WithdrawerRecipient"); - require(l1WithdrawerRecipient != address(0), "l1WithdrawerRecipient must be set in config"); - - uint256 _l1WithdrawerGasLimitRaw = _toml.readUint(".l1WithdrawerGasLimit"); - require(_l1WithdrawerGasLimitRaw > 0, "l1WithdrawerGasLimit must be greater than 0"); - require(_l1WithdrawerGasLimitRaw <= type(uint32).max, "l1WithdrawerGasLimit must be less than uint32.max"); - l1WithdrawerGasLimit = uint32(_l1WithdrawerGasLimitRaw); - - // Calculate addresses and data to deploy L1 Withdrawer - bytes memory _l1WithdrawerInitCode = bytes.concat( - RevShareLibrary.l1WithdrawerCreationCode, - abi.encode(l1WithdrawerMinWithdrawalAmount, l1WithdrawerRecipient, l1WithdrawerGasLimit) - ); - _l1WithdrawerCalldata = - abi.encodeCall(ICreate2Deployer.deploy, (0, _getSalt(saltSeed, "L1Withdrawer"), _l1WithdrawerInitCode)); - _l1WithdrawerPrecalculatedAddress = - Utils.getCreate2Address(_getSalt(saltSeed, "L1Withdrawer"), _l1WithdrawerInitCode, RevShareLibrary.CREATE2_DEPLOYER); - // Expected calls for L1 Withdrawer: 1 (deploy) - _incrementCallsToPortal( - abi.encodeCall( - IOptimismPortal2.depositTransaction, - ( - address(RevShareLibrary.CREATE2_DEPLOYER), - 0, - RevShareLibrary.L1_WITHDRAWER_DEPLOYMENT_GAS_LIMIT, - false, - _l1WithdrawerCalldata - ) - ) - ); - - // Calculate addresses and data to deploy SC Rev Share Calculator - scRevShareCalcChainFeesRecipient = _toml.readAddress(".scRevShareCalcChainFeesRecipient"); - require( - scRevShareCalcChainFeesRecipient != address(0), "scRevShareCalcChainFeesRecipient must be set in config" - ); - - bytes memory _scRevShareCalculatorInitCode = bytes.concat( - RevShareLibrary.scRevShareCalculatorCreationCode, - abi.encode(_l1WithdrawerPrecalculatedAddress, scRevShareCalcChainFeesRecipient) - ); - _scRevShareCalculatorCalldata = abi.encodeCall( - ICreate2Deployer.deploy, (0, _getSalt(saltSeed, "SCRevShareCalculator"), _scRevShareCalculatorInitCode) - ); - - _scRevShareCalculatorPrecalculatedAddress = Utils.getCreate2Address( - _getSalt(saltSeed, "SCRevShareCalculator"), _scRevShareCalculatorInitCode, RevShareLibrary.CREATE2_DEPLOYER - ); - - // Expected calls for SC Rev Shares Calculator: 1 (deploy) - _incrementCallsToPortal( - abi.encodeCall( - IOptimismPortal2.depositTransaction, - ( - address(RevShareLibrary.CREATE2_DEPLOYER), - 0, - RevShareLibrary.SC_REV_SHARE_CALCULATOR_DEPLOYMENT_GAS_LIMIT, - false, - _scRevShareCalculatorCalldata - ) - ) - ); - } else { - // Use custom calculator, read it from config and set it as the calculator address for the fee splitter - customCalculator = _toml.readAddress(".customCalculator"); - require(customCalculator != address(0), "customCalculator must be set when useDefaultCalculator is false"); - _scRevShareCalculatorPrecalculatedAddress = customCalculator; - } - - // Calculate addresses and data to deploy vaults - // Calculate addresses and data to deploy OperatorFeeVault - bytes memory _operatorFeeVaultInitCode = RevShareLibrary.operatorFeeVaultCreationCode; - _operatorFeeVaultPrecalculatedAddress = - Utils.getCreate2Address(_getSalt(saltSeed, "OperatorFeeVault"), _operatorFeeVaultInitCode, RevShareLibrary.CREATE2_DEPLOYER); - - _operatorFeeVaultCalldata = abi.encodeCall( - ICreate2Deployer.deploy, (0, _getSalt(saltSeed, "OperatorFeeVault"), _operatorFeeVaultInitCode) - ); - // Expected calls for OperatorFeeVault: 2 (deploy + upgradeAndCall) - _incrementCallsToPortal( - abi.encodeCall( - IOptimismPortal2.depositTransaction, - ( - address(RevShareLibrary.CREATE2_DEPLOYER), - 0, - RevShareLibrary.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, - false, - _operatorFeeVaultCalldata - ) - ) - ); - _incrementCallsToPortal( - abi.encodeCall( - IOptimismPortal2.depositTransaction, - ( - address(RevShareLibrary.PROXY_ADMIN), - 0, - RevShareLibrary.UPGRADE_GAS_LIMIT, - false, - abi.encodeCall( - IProxyAdmin.upgradeAndCall, - ( - payable(RevShareLibrary.OPERATOR_FEE_VAULT), - address(_operatorFeeVaultPrecalculatedAddress), - abi.encodeCall( - IFeeVault.initialize, - ( - RevShareLibrary.FEE_VAULT_RECIPIENT, - FEE_VAULT_MIN_WITHDRAWAL_AMOUNT, - FEE_VAULT_WITHDRAWAL_NETWORK - ) - ) - ) - ) - ) - ) - ); - - // Calculate addresses and data to deploy SequencerFeeVault - bytes memory _sequencerFeeVaultInitCode = RevShareLibrary.sequencerFeeVaultCreationCode; - _sequencerFeeVaultPrecalculatedAddress = Utils.getCreate2Address( - _getSalt(saltSeed, "SequencerFeeVault"), _sequencerFeeVaultInitCode, RevShareLibrary.CREATE2_DEPLOYER - ); - _sequencerFeeVaultCalldata = abi.encodeCall( - ICreate2Deployer.deploy, (0, _getSalt(saltSeed, "SequencerFeeVault"), _sequencerFeeVaultInitCode) - ); - - // Expected calls for SequencerFeeVault: 2 (deploy + upgrade) - _incrementCallsToPortal( - abi.encodeCall( - IOptimismPortal2.depositTransaction, - ( - address(RevShareLibrary.CREATE2_DEPLOYER), - 0, - RevShareLibrary.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, - false, - _sequencerFeeVaultCalldata - ) - ) - ); - _incrementCallsToPortal( - abi.encodeCall( - IOptimismPortal2.depositTransaction, - ( - address(RevShareLibrary.PROXY_ADMIN), - 0, - RevShareLibrary.UPGRADE_GAS_LIMIT, - false, - abi.encodeCall( - IProxyAdmin.upgradeAndCall, - ( - payable(RevShareLibrary.SEQUENCER_FEE_WALLET), - address(_sequencerFeeVaultPrecalculatedAddress), - abi.encodeCall( - IFeeVault.initialize, - ( - RevShareLibrary.FEE_VAULT_RECIPIENT, - FEE_VAULT_MIN_WITHDRAWAL_AMOUNT, - FEE_VAULT_WITHDRAWAL_NETWORK - ) - ) - ) - ) - ) - ) - ); - - // Calculate addresses and data to deploy BaseFeeVault - bytes memory _baseFeeVaultInitCode = RevShareLibrary.baseFeeVaultCreationCode; - _baseFeeVaultPrecalculatedAddress = - Utils.getCreate2Address(_getSalt(saltSeed, "BaseFeeVault"), _baseFeeVaultInitCode, RevShareLibrary.CREATE2_DEPLOYER); - _baseFeeVaultCalldata = - abi.encodeCall(ICreate2Deployer.deploy, (0, _getSalt(saltSeed, "BaseFeeVault"), _baseFeeVaultInitCode)); - - // Expected calls for BaseFeeVault: 2 (deploy + upgradeAndCall) - _incrementCallsToPortal( - abi.encodeCall( - IOptimismPortal2.depositTransaction, - ( - address(RevShareLibrary.CREATE2_DEPLOYER), - 0, - RevShareLibrary.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, - false, - _baseFeeVaultCalldata - ) - ) - ); - _incrementCallsToPortal( - abi.encodeCall( - IOptimismPortal2.depositTransaction, - ( - address(RevShareLibrary.PROXY_ADMIN), - 0, - RevShareLibrary.UPGRADE_GAS_LIMIT, - false, - abi.encodeCall( - IProxyAdmin.upgradeAndCall, - ( - payable(RevShareLibrary.BASE_FEE_VAULT), - address(_baseFeeVaultPrecalculatedAddress), - abi.encodeCall( - IFeeVault.initialize, - (RevShareLibrary.FEE_VAULT_RECIPIENT, FEE_VAULT_MIN_WITHDRAWAL_AMOUNT, FEE_VAULT_WITHDRAWAL_NETWORK) - ) - ) - ) - ) - ) - ); - - // Calculate addresses and data to deploy L1FeeVault - bytes memory _l1FeeVaultInitCode = RevShareLibrary.l1FeeVaultCreationCode; - _l1FeeVaultPrecalculatedAddress = - Utils.getCreate2Address(_getSalt(saltSeed, "L1FeeVault"), _l1FeeVaultInitCode, RevShareLibrary.CREATE2_DEPLOYER); - _l1FeeVaultCalldata = - abi.encodeCall(ICreate2Deployer.deploy, (0, _getSalt(saltSeed, "L1FeeVault"), _l1FeeVaultInitCode)); - - // Expected calls for L1FeeVault: 2 (deploy + upgradeAndCall) - _incrementCallsToPortal( - abi.encodeCall( - IOptimismPortal2.depositTransaction, - ( - address(RevShareLibrary.CREATE2_DEPLOYER), - 0, - RevShareLibrary.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, - false, - _l1FeeVaultCalldata - ) - ) - ); - _incrementCallsToPortal( - abi.encodeCall( - IOptimismPortal2.depositTransaction, - ( - address(RevShareLibrary.PROXY_ADMIN), - 0, - RevShareLibrary.UPGRADE_GAS_LIMIT, - false, - abi.encodeCall( - IProxyAdmin.upgradeAndCall, - ( - payable(RevShareLibrary.L1_FEE_VAULT), - address(_l1FeeVaultPrecalculatedAddress), - abi.encodeCall( - IFeeVault.initialize, - (RevShareLibrary.FEE_VAULT_RECIPIENT, FEE_VAULT_MIN_WITHDRAWAL_AMOUNT, FEE_VAULT_WITHDRAWAL_NETWORK) - ) - ) - ) - ) - ) - ); - - // Calculate addresses and data to deploy Fee Splitter - _feeSplitterCalldata = abi.encodeCall( - ICreate2Deployer.deploy, (0, _getSalt(saltSeed, "FeeSplitter"), RevShareLibrary.feeSplitterCreationCode) - ); - _feeSplitterPrecalculatedAddress = Utils.getCreate2Address( - _getSalt(saltSeed, "FeeSplitter"), RevShareLibrary.feeSplitterCreationCode, RevShareLibrary.CREATE2_DEPLOYER - ); - - // Expected calls for FeeSplitter: 2 (deploy + upgradeAndCall) - _incrementCallsToPortal( - abi.encodeCall( - IOptimismPortal2.depositTransaction, - ( - address(RevShareLibrary.CREATE2_DEPLOYER), - 0, - RevShareLibrary.FEE_SPLITTER_DEPLOYMENT_GAS_LIMIT, - false, - _feeSplitterCalldata - ) - ) - ); - _incrementCallsToPortal( - abi.encodeCall( - IOptimismPortal2.depositTransaction, - ( - address(RevShareLibrary.PROXY_ADMIN), - 0, - RevShareLibrary.UPGRADE_GAS_LIMIT, - false, - abi.encodeCall( - IProxyAdmin.upgradeAndCall, - ( - payable(RevShareLibrary.FEE_SPLITTER), - address(_feeSplitterPrecalculatedAddress), - abi.encodeCall(IFeeSplitter.initialize, (_scRevShareCalculatorPrecalculatedAddress)) - ) - ) - ) - ) - ); - } - - /// @notice Before implementing the `_build` function, template developers must consider the following: - /// 1. Which Multicall contract does this template use — `Multicall3` or `Multicall3Delegatecall`? - /// 2. Based on the contract, should the target be called using `call` or `delegatecall`? - /// 3. Ensure that the call to the target uses the appropriate method (`call` or `delegatecall`) accordingly. - /// Guidelines: - /// - `Multicall3`: - /// If the template directly inherits from `L2TaskBase` or `SimpleTaskBase`, it uses the `Multicall3` contract. - /// In this case, calls to the target **must** use `call`, e.g.: - /// ` dgm.setRespectedGameType(IOptimismPortal2(payable(portalAddress)), cfg[chainId].gameType);` - /// WARNING: Any state written to in this function will be reverted after the build function has been run. - /// Do not rely on setting global variables in this function. - function _build(address) internal override { - // Only deploy L1 Withdrawer and SC Rev Share Calculator if using default calculator - if (useDefaultCalculator) { - // Deploy L1 Withdrawer - IOptimismPortal2(payable(portal)).depositTransaction( - address(RevShareLibrary.CREATE2_DEPLOYER), - 0, - RevShareLibrary.L1_WITHDRAWER_DEPLOYMENT_GAS_LIMIT, - false, - _l1WithdrawerCalldata - ); - - // Deploy SC Rev Share Calculator - IOptimismPortal2(payable(portal)).depositTransaction( - address(RevShareLibrary.CREATE2_DEPLOYER), - 0, - RevShareLibrary.SC_REV_SHARE_CALCULATOR_DEPLOYMENT_GAS_LIMIT, - false, - _scRevShareCalculatorCalldata - ); - } - - _deployFeeSplitter(); - _deployFeeVaults(); - } - - /// @notice This method performs all validations and assertions that verify the calls executed as expected. - function _validate(VmSafe.AccountAccess[] memory, Action[] memory _actions, address) internal override { - MultisigTaskPrinter.printTitle("Validating calls to portal"); - // Expected portal calls: - // - 10 (base vault operations + fee splitter) - // - 12 if using default calculator (+ L1 withdrawer + calculator) - uint256 _expectedCallsToPortal = useDefaultCalculator ? 12 : 10; - uint256 _actualCallsToPortal = 0; - for (uint256 i = 0; i < _actions.length; i++) { - Action memory action = _actions[i]; - if (action.target == address(portal) && action.arguments.length > 0) { - _verifyAndDecrementCallsToPortal(action.arguments); - _actualCallsToPortal += 1; - } - } - - require(_actualCallsToPortal == _expectedCallsToPortal, "Invalid number of calls to portal"); - } - - /// @notice Override to return a list of addresses that should not be checked for code length. - function _getCodeExceptions() internal view virtual override returns (address[] memory) {} - - /// @notice Deploys the fee vaults implementation and upgrades the proxies to the calculated addresses. - function _deployFeeVaults() private { - // Deploy the fee vaults - // Deploy the operator fee vault - IOptimismPortal2(payable(portal)).depositTransaction( - address(RevShareLibrary.CREATE2_DEPLOYER), - 0, - RevShareLibrary.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, - false, - _operatorFeeVaultCalldata - ); - IOptimismPortal2(payable(portal)).depositTransaction( - address(RevShareLibrary.PROXY_ADMIN), - 0, - RevShareLibrary.UPGRADE_GAS_LIMIT, - false, - abi.encodeCall( - IProxyAdmin.upgradeAndCall, - ( - payable(RevShareLibrary.OPERATOR_FEE_VAULT), - address(_operatorFeeVaultPrecalculatedAddress), - abi.encodeCall( - IFeeVault.initialize, - ( - RevShareLibrary.FEE_VAULT_RECIPIENT, - FEE_VAULT_MIN_WITHDRAWAL_AMOUNT, - FEE_VAULT_WITHDRAWAL_NETWORK - ) - ) - ) - ) - ); - - // Deploy the sequencer fee vault - IOptimismPortal2(payable(portal)).depositTransaction( - address(RevShareLibrary.CREATE2_DEPLOYER), - 0, - RevShareLibrary.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, - false, - _sequencerFeeVaultCalldata - ); - IOptimismPortal2(payable(portal)).depositTransaction( - address(RevShareLibrary.PROXY_ADMIN), - 0, - RevShareLibrary.UPGRADE_GAS_LIMIT, - false, - abi.encodeCall( - IProxyAdmin.upgradeAndCall, - ( - payable(RevShareLibrary.SEQUENCER_FEE_WALLET), - address(_sequencerFeeVaultPrecalculatedAddress), - abi.encodeCall( - IFeeVault.initialize, - ( - RevShareLibrary.FEE_VAULT_RECIPIENT, - FEE_VAULT_MIN_WITHDRAWAL_AMOUNT, - FEE_VAULT_WITHDRAWAL_NETWORK - ) - ) - ) - ) - ); - - // Deploy the base fee vault - IOptimismPortal2(payable(portal)).depositTransaction( - address(RevShareLibrary.CREATE2_DEPLOYER), - 0, - RevShareLibrary.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, - false, - _baseFeeVaultCalldata - ); - IOptimismPortal2(payable(portal)).depositTransaction( - address(RevShareLibrary.PROXY_ADMIN), - 0, - RevShareLibrary.UPGRADE_GAS_LIMIT, - false, - abi.encodeCall( - IProxyAdmin.upgradeAndCall, - ( - payable(RevShareLibrary.BASE_FEE_VAULT), - address(_baseFeeVaultPrecalculatedAddress), - abi.encodeCall( - IFeeVault.initialize, - (RevShareLibrary.FEE_VAULT_RECIPIENT, FEE_VAULT_MIN_WITHDRAWAL_AMOUNT, FEE_VAULT_WITHDRAWAL_NETWORK) - ) - ) - ) - ); - - // Deploy the l1 fee vault - IOptimismPortal2(payable(portal)).depositTransaction( - address(RevShareLibrary.CREATE2_DEPLOYER), 0, RevShareLibrary.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, false, _l1FeeVaultCalldata - ); - IOptimismPortal2(payable(portal)).depositTransaction( - address(RevShareLibrary.PROXY_ADMIN), - 0, - RevShareLibrary.UPGRADE_GAS_LIMIT, - false, - abi.encodeCall( - IProxyAdmin.upgradeAndCall, - ( - payable(RevShareLibrary.L1_FEE_VAULT), - address(_l1FeeVaultPrecalculatedAddress), - abi.encodeCall( - IFeeVault.initialize, - (RevShareLibrary.FEE_VAULT_RECIPIENT, FEE_VAULT_MIN_WITHDRAWAL_AMOUNT, FEE_VAULT_WITHDRAWAL_NETWORK) - ) - ) - ) - ); - } - - /// @notice Deploys the fee splitter implementation using Create2. - function _deployFeeSplitter() private { - // Deploy Fee Splitter - IOptimismPortal2(payable(portal)).depositTransaction( - address(RevShareLibrary.CREATE2_DEPLOYER), - 0, - RevShareLibrary.FEE_SPLITTER_DEPLOYMENT_GAS_LIMIT, - false, - _feeSplitterCalldata - ); - - IOptimismPortal2(payable(portal)).depositTransaction( - address(RevShareLibrary.PROXY_ADMIN), - 0, - RevShareLibrary.UPGRADE_GAS_LIMIT, - false, - abi.encodeCall( - IProxyAdmin.upgradeAndCall, - ( - payable(RevShareLibrary.FEE_SPLITTER), - address(_feeSplitterPrecalculatedAddress), - abi.encodeCall(IFeeSplitter.initialize, (_scRevShareCalculatorPrecalculatedAddress)) - ) - ) - ); - } - - function _incrementCallsToPortal(bytes memory _calldata) private { - _callsToPortal[keccak256(_calldata)] += 1; - } - - function _verifyAndDecrementCallsToPortal(bytes memory _calldata) private { - bytes32 _calldataHash = keccak256(_calldata); - require(_callsToPortal[_calldataHash] > 0, "Invalid number of calls with this calldata"); - _callsToPortal[_calldataHash] -= 1; - } - - function _getSalt(string memory _prefix, string memory _suffix) private pure returns (bytes32) { - return keccak256(abi.encodePacked(bytes(_prefix), bytes(":"), bytes(_suffix))); - } -} From a932638b6959bcf7df0c9066d8c8f526ce27afa4 Mon Sep 17 00:00:00 2001 From: Chiin <77933451+0xChin@users.noreply.github.com> Date: Tue, 11 Nov 2025 15:38:42 -0300 Subject: [PATCH 61/69] chore: improve comments Co-authored-by: Disco <131301107+0xDiscotech@users.noreply.github.com> Signed-off-by: Chiin <77933451+0xChin@users.noreply.github.com> --- src/RevShareContractsUpgrader.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol index 3f5c033b0b..0901236441 100644 --- a/src/RevShareContractsUpgrader.sol +++ b/src/RevShareContractsUpgrader.sol @@ -172,7 +172,7 @@ contract RevShareContractsUpgrader { } /// @notice Upgrades all 4 vaults with RevShare configuration (recipient=FeeSplitter, minWithdrawal=0, network=L2). - /// Deploys only 3 implementations: OperatorFeeVault, SequencerFeeVault, and a default FeeVault used for both BaseFeeVault and L1FeeVault. + /// 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 { // Deploy OperatorFeeVault implementation From ec1d538980a5e2d288b576adf69299e27e477d06 Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Tue, 11 Nov 2025 15:48:03 -0300 Subject: [PATCH 62/69] refactor: use for loop for vaults deployment --- src/RevShareContractsUpgrader.sol | 119 +++++++++++------------------- 1 file changed, 43 insertions(+), 76 deletions(-) diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol index 0901236441..ce0ef39f6f 100644 --- a/src/RevShareContractsUpgrader.sol +++ b/src/RevShareContractsUpgrader.sol @@ -175,88 +175,55 @@ contract RevShareContractsUpgrader { /// 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 { - // Deploy OperatorFeeVault implementation - bytes32 operatorSalt = _getSalt("OperatorFeeVault"); - address operatorImpl = Utils.getCreate2Address(operatorSalt, RevShareLibrary.operatorFeeVaultCreationCode, RevShareLibrary.CREATE2_DEPLOYER); - _depositCreate2(_portal, RevShareLibrary.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, operatorSalt, RevShareLibrary.operatorFeeVaultCreationCode); - _depositCall( - _portal, - address(RevShareLibrary.PROXY_ADMIN), - RevShareLibrary.UPGRADE_GAS_LIMIT, - abi.encodeCall( - IProxyAdmin.upgradeAndCall, - ( - payable(RevShareLibrary.OPERATOR_FEE_VAULT), - operatorImpl, - abi.encodeCall( - IFeeVault.initialize, - (RevShareLibrary.FEE_SPLITTER, 0, IFeeVault.WithdrawalNetwork.L2) - ) - ) - ) - ); + 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"]; - // Deploy SequencerFeeVault implementation - bytes32 sequencerSalt = _getSalt("SequencerFeeVault"); - address sequencerImpl = Utils.getCreate2Address(sequencerSalt, RevShareLibrary.sequencerFeeVaultCreationCode, RevShareLibrary.CREATE2_DEPLOYER); - _depositCreate2(_portal, RevShareLibrary.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, sequencerSalt, RevShareLibrary.sequencerFeeVaultCreationCode); - _depositCall( - _portal, - address(RevShareLibrary.PROXY_ADMIN), - RevShareLibrary.UPGRADE_GAS_LIMIT, - abi.encodeCall( - IProxyAdmin.upgradeAndCall, - ( - payable(RevShareLibrary.SEQUENCER_FEE_WALLET), - sequencerImpl, - abi.encodeCall( - IFeeVault.initialize, - (RevShareLibrary.FEE_SPLITTER, 0, IFeeVault.WithdrawalNetwork.L2) - ) - ) - ) - ); + address defaultImpl; + for (uint256 i; i < vaultProxies.length; i++) { + bytes32 salt = _getSalt(vaultNames[i]); + address impl; - // Deploy default FeeVault implementation (used for both BaseFeeVault and L1FeeVault) - bytes32 defaultSalt = _getSalt("DefaultFeeVault"); - address defaultImpl = Utils.getCreate2Address(defaultSalt, RevShareLibrary.defaultFeeVaultCreationCode, RevShareLibrary.CREATE2_DEPLOYER); - _depositCreate2(_portal, RevShareLibrary.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, defaultSalt, RevShareLibrary.defaultFeeVaultCreationCode); + // 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")); - // Upgrade BaseFeeVault with default implementation - _depositCall( - _portal, - address(RevShareLibrary.PROXY_ADMIN), - RevShareLibrary.UPGRADE_GAS_LIMIT, - abi.encodeCall( - IProxyAdmin.upgradeAndCall, - ( - payable(RevShareLibrary.BASE_FEE_VAULT), - defaultImpl, - abi.encodeCall( - IFeeVault.initialize, - (RevShareLibrary.FEE_SPLITTER, 0, IFeeVault.WithdrawalNetwork.L2) - ) - ) - ) - ); + 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]); + } - // Upgrade L1FeeVault with default implementation - _depositCall( - _portal, - address(RevShareLibrary.PROXY_ADMIN), - RevShareLibrary.UPGRADE_GAS_LIMIT, - abi.encodeCall( - IProxyAdmin.upgradeAndCall, - ( - payable(RevShareLibrary.L1_FEE_VAULT), - defaultImpl, - abi.encodeCall( - IFeeVault.initialize, - (RevShareLibrary.FEE_SPLITTER, 0, IFeeVault.WithdrawalNetwork.L2) + _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. From e83ae809f72c911af0ed21809c7b6bec246750c7 Mon Sep 17 00:00:00 2001 From: Disco <131301107+0xDiscotech@users.noreply.github.com> Date: Tue, 11 Nov 2025 16:23:56 -0300 Subject: [PATCH 63/69] feat: add upgrader unit tests (#55) --- src/RevShareContractsUpgrader.sol | 61 +- .../RevShareContractsUpgrader.t.sol | 618 ++++++++++++++++++ 2 files changed, 663 insertions(+), 16 deletions(-) create mode 100644 test/template/revenue-share-upgrade-path/RevShareContractsUpgrader.t.sol diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol index ce0ef39f6f..889775934e 100644 --- a/src/RevShareContractsUpgrader.sol +++ b/src/RevShareContractsUpgrader.sol @@ -66,13 +66,15 @@ contract RevShareContractsUpgrader { if (config.chainFeesRecipient == address(0)) revert ChainFeesRecipientCannotBeZeroAddress(); // Deploy L1Withdrawer and SuperchainRevenueShareCalculator - address precalculatedCalculator = _deployRevSharePeriphery(config.portal, config.l1WithdrawerConfig, config.chainFeesRecipient); + 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); + address feeSplitterImpl = Utils.getCreate2Address( + feeSplitterSalt, RevShareLibrary.feeSplitterCreationCode, RevShareLibrary.CREATE2_DEPLOYER + ); _depositCreate2( config.portal, RevShareLibrary.FEE_SPLITTER_DEPLOYMENT_GAS_LIMIT, @@ -85,7 +87,11 @@ contract RevShareContractsUpgrader { RevShareLibrary.UPGRADE_GAS_LIMIT, abi.encodeCall( IProxyAdmin.upgradeAndCall, - (payable(RevShareLibrary.FEE_SPLITTER), feeSplitterImpl, abi.encodeCall(IFeeSplitter.initialize, (precalculatedCalculator))) + ( + payable(RevShareLibrary.FEE_SPLITTER), + feeSplitterImpl, + abi.encodeCall(IFeeSplitter.initialize, (precalculatedCalculator)) + ) ) ); @@ -107,7 +113,8 @@ contract RevShareContractsUpgrader { if (config.chainFeesRecipient == address(0)) revert ChainFeesRecipientCannotBeZeroAddress(); // Deploy L1Withdrawer and SuperchainRevenueShareCalculator - address calculator = _deployRevSharePeriphery(config.portal, config.l1WithdrawerConfig, config.chainFeesRecipient); + address calculator = + _deployRevSharePeriphery(config.portal, config.l1WithdrawerConfig, config.chainFeesRecipient); // Set calculator on fee splitter _depositCall( @@ -135,17 +142,21 @@ contract RevShareContractsUpgrader { // Deploy L1Withdrawer bytes memory l1WithdrawerInitCode = bytes.concat( RevShareLibrary.l1WithdrawerCreationCode, - abi.encode(_l1WithdrawerConfig.minWithdrawalAmount, _l1WithdrawerConfig.recipient, _l1WithdrawerConfig.gasLimit) + abi.encode( + _l1WithdrawerConfig.minWithdrawalAmount, _l1WithdrawerConfig.recipient, _l1WithdrawerConfig.gasLimit + ) ); bytes32 l1WithdrawerSalt = _getSalt("L1Withdrawer"); - address precalculatedL1Withdrawer = Utils.getCreate2Address(l1WithdrawerSalt, l1WithdrawerInitCode, RevShareLibrary.CREATE2_DEPLOYER); + 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)); + bytes memory calculatorInitCode = bytes.concat( + RevShareLibrary.scRevShareCalculatorCreationCode, abi.encode(precalculatedL1Withdrawer, _chainFeesRecipient) + ); bytes32 calculatorSalt = _getSalt("SCRevShareCalculator"); calculator = Utils.getCreate2Address(calculatorSalt, calculatorInitCode, RevShareLibrary.CREATE2_DEPLOYER); _depositCreate2( @@ -156,17 +167,31 @@ contract RevShareContractsUpgrader { /// @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]; + 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)) + _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)) + _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)) + _portal, + vaults[i], + RevShareLibrary.SETTERS_GAS_LIMIT, + abi.encodeCall(IFeeVault.setWithdrawalNetwork, (IFeeVault.WithdrawalNetwork.L2)) ); } } @@ -175,7 +200,12 @@ contract RevShareContractsUpgrader { /// 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]; + 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, @@ -217,8 +247,7 @@ contract RevShareContractsUpgrader { payable(vaultProxies[i]), impl, abi.encodeCall( - IFeeVault.initialize, - (RevShareLibrary.FEE_SPLITTER, 0, IFeeVault.WithdrawalNetwork.L2) + IFeeVault.initialize, (RevShareLibrary.FEE_SPLITTER, 0, IFeeVault.WithdrawalNetwork.L2) ) ) ) diff --git a/test/template/revenue-share-upgrade-path/RevShareContractsUpgrader.t.sol b/test/template/revenue-share-upgrade-path/RevShareContractsUpgrader.t.sol new file mode 100644 index 0000000000..4bd823e9ef --- /dev/null +++ b/test/template/revenue-share-upgrade-path/RevShareContractsUpgrader.t.sol @@ -0,0 +1,618 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +// Testing +import {Test} from "forge-std/Test.sol"; + +// Contract under test +import {RevShareContractsUpgrader} from "src/RevShareContractsUpgrader.sol"; + +// Libraries +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_TestInit +/// @notice Base test contract with shared setup and helpers for RevShareContractsUpgrader tests. +contract RevShareContractsUpgrader_TestInit is Test { + // Contract under test + RevShareContractsUpgrader internal upgrader; + + // Test constants + address internal immutable PORTAL_ONE = makeAddr("PORTAL_ONE"); + address internal immutable PORTAL_TWO = makeAddr("PORTAL_TWO"); + address internal immutable L1_RECIPIENT_ONE = makeAddr("L1_RECIPIENT_ONE"); + address internal immutable L1_RECIPIENT_TWO = makeAddr("L1_RECIPIENT_TWO"); + address internal immutable CHAIN_FEES_RECIPIENT_ONE = makeAddr("CHAIN_FEES_RECIPIENT_ONE"); + address internal immutable CHAIN_FEES_RECIPIENT_TWO = makeAddr("CHAIN_FEES_RECIPIENT_TWO"); + uint256 internal immutable MIN_WITHDRAWAL_AMOUNT = 1 ether; + uint32 internal immutable GAS_LIMIT = 500_000; + + /// @notice Test setup + function setUp() public { + upgrader = new RevShareContractsUpgrader(); + } + + function _assumeValidAddress(address _address) internal pure { + assumeNotZeroAddress(_address); + assumeNotForgeAddress(_address); + assumeNotPrecompile(_address); + } + + /// @notice Helper function to setup a mock and expect a call to it. + function _mockAndExpect(address _receiver, bytes memory _calldata, bytes memory _returned) internal { + vm.mockCall(_receiver, _calldata, _returned); + vm.expectCall(_receiver, _calldata); + } + + /// @notice Helper to create RevShareConfig + function _createRevShareConfig( + address _portal, + uint256 _minWithdrawalAmount, + address _l1Recipient, + uint32 _gasLimit, + address _chainFeesRecipient + ) internal pure returns (RevShareContractsUpgrader.RevShareConfig memory) { + return RevShareContractsUpgrader.RevShareConfig({ + portal: _portal, + l1WithdrawerConfig: RevShareContractsUpgrader.L1WithdrawerConfig({ + minWithdrawalAmount: _minWithdrawalAmount, + recipient: _l1Recipient, + gasLimit: _gasLimit + }), + chainFeesRecipient: _chainFeesRecipient + }); + } + + /// @notice Helper to calculate expected CREATE2 address + function _calculateExpectedCreate2Address(string memory _suffix, bytes memory _initCode) + internal + pure + returns (address _expectedAddress) + { + bytes32 salt = keccak256(abi.encodePacked("RevShare", ":", _suffix)); + _expectedAddress = Utils.getCreate2Address(salt, _initCode, RevShareLibrary.CREATE2_DEPLOYER); + assumeNotZeroAddress(_expectedAddress); + } + + /// @notice Helper to mock L1Withdrawer deployment + function _mockAndExpectL1WithdrawerDeploy( + address _portal, + uint256 _minWithdrawalAmount, + address _recipient, + uint32 _gasLimit + ) internal { + bytes memory l1WithdrawerInitCode = bytes.concat( + RevShareLibrary.l1WithdrawerCreationCode, abi.encode(_minWithdrawalAmount, _recipient, _gasLimit) + ); + bytes32 salt = keccak256(abi.encodePacked("RevShare", ":", "L1Withdrawer")); + + _mockAndExpect( + _portal, + abi.encodeCall( + IOptimismPortal2.depositTransaction, + ( + RevShareLibrary.CREATE2_DEPLOYER, + 0, + RevShareLibrary.L1_WITHDRAWER_DEPLOYMENT_GAS_LIMIT, + false, + abi.encodeCall(ICreate2Deployer.deploy, (0, salt, l1WithdrawerInitCode)) + ) + ), + abi.encode() + ); + } + + /// @notice Helper to mock Calculator deployment + function _mockAndExpectCalculatorDeploy(address _portal, address _l1Withdrawer, address _chainFeesRecipient) + internal + { + bytes memory calculatorInitCode = bytes.concat( + RevShareLibrary.scRevShareCalculatorCreationCode, abi.encode(_l1Withdrawer, _chainFeesRecipient) + ); + bytes32 salt = keccak256(abi.encodePacked("RevShare", ":", "SCRevShareCalculator")); + + _mockAndExpect( + _portal, + abi.encodeCall( + IOptimismPortal2.depositTransaction, + ( + RevShareLibrary.CREATE2_DEPLOYER, + 0, + RevShareLibrary.SC_REV_SHARE_CALCULATOR_DEPLOYMENT_GAS_LIMIT, + false, + abi.encodeCall(ICreate2Deployer.deploy, (0, salt, calculatorInitCode)) + ) + ), + abi.encode() + ); + } + + /// @notice Helper to mock FeeSplitter deployment + function _mockAndExpectFeeSplitterDeployAndSetup(address _portal, address _calculator) internal { + // FeeSplitter deployment deposit + bytes32 salt = keccak256(abi.encodePacked("RevShare", ":", "FeeSplitter")); + _mockAndExpect( + _portal, + abi.encodeCall( + IOptimismPortal2.depositTransaction, + ( + RevShareLibrary.CREATE2_DEPLOYER, + 0, + RevShareLibrary.FEE_SPLITTER_DEPLOYMENT_GAS_LIMIT, + false, + abi.encodeCall(ICreate2Deployer.deploy, (0, salt, RevShareLibrary.feeSplitterCreationCode)) + ) + ), + abi.encode() + ); + + // Initialize FeeSplitter with calculator deposit + address feeSplitterImpl = + _calculateExpectedCreate2Address("FeeSplitter", RevShareLibrary.feeSplitterCreationCode); + + bytes memory upgradeCall = abi.encodeCall( + IProxyAdmin.upgradeAndCall, + ( + payable(RevShareLibrary.FEE_SPLITTER), + feeSplitterImpl, + abi.encodeCall(IFeeSplitter.initialize, (_calculator)) + ) + ); + + _mockAndExpect( + _portal, + abi.encodeCall( + IOptimismPortal2.depositTransaction, + (RevShareLibrary.PROXY_ADMIN, 0, RevShareLibrary.UPGRADE_GAS_LIMIT, false, upgradeCall) + ), + abi.encode() + ); + } + + /// @notice Helper to mock FeeSplitter setSharesCalculator call + function _mockAndExpectFeeSplitterSetCalculator(address _portal, address _calculator) internal { + bytes memory setCalculatorCall = abi.encodeCall(IFeeSplitter.setSharesCalculator, (_calculator)); + + _mockAndExpect( + _portal, + abi.encodeCall( + IOptimismPortal2.depositTransaction, + (RevShareLibrary.FEE_SPLITTER, 0, RevShareLibrary.SETTERS_GAS_LIMIT, false, setCalculatorCall) + ), + abi.encode() + ); + } + + /// @notice Helper to mock a single vault deployment and upgrade + function _mockAndExpectVaultUpgrade( + address _portal, + address _vault, + string memory _vaultName, + bytes memory _creationCode + ) internal { + // Mock vault implementation deployment + bytes32 salt = keccak256(abi.encodePacked("RevShare", ":", _vaultName)); + _mockAndExpect( + _portal, + abi.encodeCall( + IOptimismPortal2.depositTransaction, + ( + RevShareLibrary.CREATE2_DEPLOYER, + 0, + RevShareLibrary.FEE_VAULTS_DEPLOYMENT_GAS_LIMIT, + false, + abi.encodeCall(ICreate2Deployer.deploy, (0, salt, _creationCode)) + ) + ), + abi.encode() + ); + + // Mock vault upgrade call + address vaultImpl = _calculateExpectedCreate2Address(_vaultName, _creationCode); + bytes memory vaultUpgradeCall = abi.encodeCall( + IProxyAdmin.upgradeAndCall, + ( + payable(_vault), + vaultImpl, + abi.encodeCall(IFeeVault.initialize, (RevShareLibrary.FEE_SPLITTER, 0, IFeeVault.WithdrawalNetwork.L2)) + ) + ); + + _mockAndExpect( + _portal, + abi.encodeCall( + IOptimismPortal2.depositTransaction, + (RevShareLibrary.PROXY_ADMIN, 0, RevShareLibrary.UPGRADE_GAS_LIMIT, false, vaultUpgradeCall) + ), + abi.encode() + ); + } + + /// @notice Helper to mock a single vault setter calls + function _mockAndExpectVaultSetter(address _portal, address _vault) internal { + // Mock setRecipient call + _mockAndExpect( + _portal, + abi.encodeCall( + IOptimismPortal2.depositTransaction, + ( + _vault, + 0, + RevShareLibrary.SETTERS_GAS_LIMIT, + false, + abi.encodeCall(IFeeVault.setRecipient, (RevShareLibrary.FEE_SPLITTER)) + ) + ), + abi.encode() + ); + + // Mock setMinWithdrawalAmount call + _mockAndExpect( + _portal, + abi.encodeCall( + IOptimismPortal2.depositTransaction, + ( + _vault, + 0, + RevShareLibrary.SETTERS_GAS_LIMIT, + false, + abi.encodeCall(IFeeVault.setMinWithdrawalAmount, (0)) + ) + ), + abi.encode() + ); + + // Mock setWithdrawalNetwork call + _mockAndExpect( + _portal, + abi.encodeCall( + IOptimismPortal2.depositTransaction, + ( + _vault, + 0, + RevShareLibrary.SETTERS_GAS_LIMIT, + false, + abi.encodeCall(IFeeVault.setWithdrawalNetwork, (IFeeVault.WithdrawalNetwork.L2)) + ) + ), + abi.encode() + ); + } + + /// @notice Helper to mock only a vault upgrade (no deployment) - for vaults that reuse another vault's implementation + /// @param _portal The portal address + /// @param _vault The vault proxy address to upgrade + /// @param _implVaultName The vault name whose implementation to reuse (e.g., "BaseFeeVault" for L1FeeVault) + /// @param _creationCode The creation code of the implementation being reused + function _mockAndExpectVaultUpgradeOnly( + address _portal, + address _vault, + string memory _implVaultName, + bytes memory _creationCode + ) internal { + // Calculate the implementation address (using the name of the vault whose impl we're reusing) + address vaultImpl = _calculateExpectedCreate2Address(_implVaultName, _creationCode); + + // Mock vault upgrade call (no deployment, just upgrade) + bytes memory vaultUpgradeCall = abi.encodeCall( + IProxyAdmin.upgradeAndCall, + ( + payable(_vault), + vaultImpl, + abi.encodeCall(IFeeVault.initialize, (RevShareLibrary.FEE_SPLITTER, 0, IFeeVault.WithdrawalNetwork.L2)) + ) + ); + + _mockAndExpect( + _portal, + abi.encodeCall( + IOptimismPortal2.depositTransaction, + (RevShareLibrary.PROXY_ADMIN, 0, RevShareLibrary.UPGRADE_GAS_LIMIT, false, vaultUpgradeCall) + ), + abi.encode() + ); + } + + /// @notice Helper to mock all vault upgrades (3 vault deployments + 4 upgrades) + /// @dev BaseFeeVault and L1FeeVault share the same implementation, so only BaseFeeVault is deployed + function _mockAndExpectAllVaultUpgrades(address _portal) internal { + // Deploy and upgrade OperatorFeeVault + _mockAndExpectVaultUpgrade( + _portal, + RevShareLibrary.OPERATOR_FEE_VAULT, + "OperatorFeeVault", + RevShareLibrary.operatorFeeVaultCreationCode + ); + + // Deploy and upgrade SequencerFeeVault + _mockAndExpectVaultUpgrade( + _portal, + RevShareLibrary.SEQUENCER_FEE_WALLET, + "SequencerFeeVault", + RevShareLibrary.sequencerFeeVaultCreationCode + ); + + // Deploy and upgrade BaseFeeVault (this deployment is shared with L1FeeVault) + _mockAndExpectVaultUpgrade( + _portal, RevShareLibrary.BASE_FEE_VAULT, "BaseFeeVault", RevShareLibrary.defaultFeeVaultCreationCode + ); + + // L1FeeVault upgrade only (reuses BaseFeeVault's implementation, no deployment) + _mockAndExpectVaultUpgradeOnly( + _portal, RevShareLibrary.L1_FEE_VAULT, "BaseFeeVault", RevShareLibrary.defaultFeeVaultCreationCode + ); + } + + /// @notice Helper to mock all vault setters (4 vaults, 3 calls each = 12 calls total) + function _mockAndExpectAllVaultSetters(address _portal) internal { + _mockAndExpectVaultSetter(_portal, RevShareLibrary.OPERATOR_FEE_VAULT); + _mockAndExpectVaultSetter(_portal, RevShareLibrary.SEQUENCER_FEE_WALLET); + _mockAndExpectVaultSetter(_portal, RevShareLibrary.BASE_FEE_VAULT); + _mockAndExpectVaultSetter(_portal, RevShareLibrary.L1_FEE_VAULT); + } +} + +/// @title RevShareContractsUpgrader_UpgradeAndSetupRevShare_Test +/// @notice Tests for the upgradeAndSetupRevShare function of the RevShareContractsUpgrader contract. +contract RevShareContractsUpgrader_UpgradeAndSetupRevShare_Test is RevShareContractsUpgrader_TestInit { + /// @notice Test that upgradeAndSetupRevShare reverts when configs array is empty + function test_upgradeAndSetupRevShare_whenEmptyArray_reverts() public { + RevShareContractsUpgrader.RevShareConfig[] memory configs = new RevShareContractsUpgrader.RevShareConfig[](0); + + vm.expectRevert(RevShareContractsUpgrader.EmptyArray.selector); + upgrader.upgradeAndSetupRevShare(configs); + } + + /// @notice Test that upgradeAndSetupRevShare reverts when portal address is zero + function test_upgradeAndSetupRevShare_whenPortalIsZero_reverts() public { + RevShareContractsUpgrader.RevShareConfig[] memory configs = new RevShareContractsUpgrader.RevShareConfig[](1); + configs[0] = _createRevShareConfig( + address(0), MIN_WITHDRAWAL_AMOUNT, L1_RECIPIENT_ONE, GAS_LIMIT, CHAIN_FEES_RECIPIENT_ONE + ); + + vm.expectRevert(RevShareContractsUpgrader.PortalCannotBeZeroAddress.selector); + upgrader.upgradeAndSetupRevShare(configs); + } + + /// @notice Test that upgradeAndSetupRevShare reverts when L1Withdrawer recipient is zero + function test_upgradeAndSetupRevShare_whenL1WithdrawerRecipientIsZero_reverts() public { + RevShareContractsUpgrader.RevShareConfig[] memory configs = new RevShareContractsUpgrader.RevShareConfig[](1); + configs[0] = + _createRevShareConfig(PORTAL_ONE, MIN_WITHDRAWAL_AMOUNT, address(0), GAS_LIMIT, CHAIN_FEES_RECIPIENT_ONE); + + vm.expectRevert(RevShareContractsUpgrader.L1WithdrawerRecipientCannotBeZeroAddress.selector); + upgrader.upgradeAndSetupRevShare(configs); + } + + /// @notice Test that upgradeAndSetupRevShare reverts when chain fees recipient is zero + function test_upgradeAndSetupRevShare_whenChainFeesRecipientIsZero_reverts() public { + RevShareContractsUpgrader.RevShareConfig[] memory configs = new RevShareContractsUpgrader.RevShareConfig[](1); + configs[0] = _createRevShareConfig(PORTAL_ONE, MIN_WITHDRAWAL_AMOUNT, L1_RECIPIENT_ONE, GAS_LIMIT, address(0)); + + vm.expectRevert(RevShareContractsUpgrader.ChainFeesRecipientCannotBeZeroAddress.selector); + upgrader.upgradeAndSetupRevShare(configs); + } + + /// @notice Fuzz test successful upgradeAndSetupRevShare with single chain + function testFuzz_upgradeAndSetupRevShare_singleChain_succeeds( + address _portal, + uint256 _minWithdrawalAmount, + address _l1Recipient, + uint32 _gasLimit, + address _chainFeesRecipient + ) public { + // Bound inputs to valid ranges + _assumeValidAddress(_portal); + _assumeValidAddress(_l1Recipient); + _assumeValidAddress(_chainFeesRecipient); + bound(_gasLimit, 1, type(uint32).max); + + RevShareContractsUpgrader.RevShareConfig[] memory configs = new RevShareContractsUpgrader.RevShareConfig[](1); + configs[0] = _createRevShareConfig(_portal, _minWithdrawalAmount, _l1Recipient, _gasLimit, _chainFeesRecipient); + + // Calculate expected L1Withdrawer address + bytes memory l1WithdrawerInitCode = bytes.concat( + RevShareLibrary.l1WithdrawerCreationCode, abi.encode(_minWithdrawalAmount, _l1Recipient, _gasLimit) + ); + address expectedL1Withdrawer = _calculateExpectedCreate2Address("L1Withdrawer", l1WithdrawerInitCode); + + // Calculate expected Calculator address + bytes memory calculatorInitCode = bytes.concat( + RevShareLibrary.scRevShareCalculatorCreationCode, abi.encode(expectedL1Withdrawer, _chainFeesRecipient) + ); + address expectedCalculator = _calculateExpectedCreate2Address("SCRevShareCalculator", calculatorInitCode); + + // Mock all calls with strict abi.encodeCall + _mockAndExpectL1WithdrawerDeploy(_portal, _minWithdrawalAmount, _l1Recipient, _gasLimit); + _mockAndExpectCalculatorDeploy(_portal, expectedL1Withdrawer, _chainFeesRecipient); + _mockAndExpectFeeSplitterDeployAndSetup(_portal, expectedCalculator); + _mockAndExpectAllVaultUpgrades(_portal); + + // Execute + upgrader.upgradeAndSetupRevShare(configs); + } + + /// @notice Fuzz test successful upgradeAndSetupRevShare with multiple chains + function testFuzz_upgradeAndSetupRevShare_multipleChains_succeeds(uint8 _numChains, uint256 _seed) public { + // Bound to reasonable range: 2-50 chains + _numChains = uint8(bound(_numChains, 2, 50)); + + // Setup configs array + RevShareContractsUpgrader.RevShareConfig[] memory configs = + new RevShareContractsUpgrader.RevShareConfig[](_numChains); + + // Generate random configs and setup mocks for each chain + for (uint256 i; i < _numChains; ++i) { + // Use seed + index to generate pseudo-random but deterministic values + uint256 chainSeed = uint256(keccak256(abi.encode(_seed, i))); + + // Generate random but valid addresses (non-zero) + address portal = makeAddr(string.concat("portal_", vm.toString(chainSeed))); + address l1Recipient = makeAddr(string.concat("l1recipient_", vm.toString(chainSeed))); + address chainFeeRecipient = makeAddr(string.concat("chainfee_", vm.toString(chainSeed))); + + // Generate random config values + uint256 minWithdrawalAmount = + bound(uint256(keccak256(abi.encode(chainSeed, "minwithdrawal"))), 1, type(uint256).max); + uint32 gasLimit = uint32(bound(uint256(keccak256(abi.encode(chainSeed, "gaslimit"))), 1, type(uint32).max)); + + configs[i] = _createRevShareConfig(portal, minWithdrawalAmount, l1Recipient, gasLimit, chainFeeRecipient); + + // Calculate expected addresses for this chain + bytes memory l1WithdrawerInitCode = bytes.concat( + RevShareLibrary.l1WithdrawerCreationCode, abi.encode(minWithdrawalAmount, l1Recipient, gasLimit) + ); + address expectedL1Withdrawer = _calculateExpectedCreate2Address("L1Withdrawer", l1WithdrawerInitCode); + + bytes memory calculatorInitCode = bytes.concat( + RevShareLibrary.scRevShareCalculatorCreationCode, abi.encode(expectedL1Withdrawer, chainFeeRecipient) + ); + address expectedCalculator = _calculateExpectedCreate2Address("SCRevShareCalculator", calculatorInitCode); + + // Setup mocks for this chain + _mockAndExpectL1WithdrawerDeploy(portal, minWithdrawalAmount, l1Recipient, gasLimit); + _mockAndExpectCalculatorDeploy(portal, expectedL1Withdrawer, chainFeeRecipient); + _mockAndExpectFeeSplitterDeployAndSetup(portal, expectedCalculator); + _mockAndExpectAllVaultUpgrades(portal); + } + + // Execute once with all chains + upgrader.upgradeAndSetupRevShare(configs); + } +} + +/// @title RevShareContractsUpgrader_SetupRevShare_Test +/// @notice Tests for the setupRevShare function of the RevShareContractsUpgrader contract. +contract RevShareContractsUpgrader_SetupRevShare_Test is RevShareContractsUpgrader_TestInit { + /// @notice Test that setupRevShare reverts when configs array is empty + function test_setupRevShare_whenEmptyArray_reverts() public { + RevShareContractsUpgrader.RevShareConfig[] memory configs = new RevShareContractsUpgrader.RevShareConfig[](0); + + vm.expectRevert(RevShareContractsUpgrader.EmptyArray.selector); + upgrader.setupRevShare(configs); + } + + /// @notice Test that setupRevShare reverts when portal address is zero + function test_setupRevShare_whenPortalIsZero_reverts() public { + RevShareContractsUpgrader.RevShareConfig[] memory configs = new RevShareContractsUpgrader.RevShareConfig[](1); + configs[0] = _createRevShareConfig( + address(0), MIN_WITHDRAWAL_AMOUNT, L1_RECIPIENT_ONE, GAS_LIMIT, CHAIN_FEES_RECIPIENT_ONE + ); + + vm.expectRevert(RevShareContractsUpgrader.PortalCannotBeZeroAddress.selector); + upgrader.setupRevShare(configs); + } + + /// @notice Test that setupRevShare reverts when L1Withdrawer recipient is zero + function test_setupRevShare_whenL1WithdrawerRecipientIsZero_reverts() public { + RevShareContractsUpgrader.RevShareConfig[] memory configs = new RevShareContractsUpgrader.RevShareConfig[](1); + configs[0] = + _createRevShareConfig(PORTAL_ONE, MIN_WITHDRAWAL_AMOUNT, address(0), GAS_LIMIT, CHAIN_FEES_RECIPIENT_ONE); + + vm.expectRevert(RevShareContractsUpgrader.L1WithdrawerRecipientCannotBeZeroAddress.selector); + upgrader.setupRevShare(configs); + } + + /// @notice Test that setupRevShare reverts when chain fees recipient is zero + function test_setupRevShare_whenChainFeesRecipientIsZero_reverts() public { + RevShareContractsUpgrader.RevShareConfig[] memory configs = new RevShareContractsUpgrader.RevShareConfig[](1); + configs[0] = _createRevShareConfig(PORTAL_ONE, MIN_WITHDRAWAL_AMOUNT, L1_RECIPIENT_ONE, GAS_LIMIT, address(0)); + + vm.expectRevert(RevShareContractsUpgrader.ChainFeesRecipientCannotBeZeroAddress.selector); + upgrader.setupRevShare(configs); + } + + /// @notice Fuzz test successful setupRevShare with single chain + function testFuzz_setupRevShare_singleChain_succeeds( + address _portal, + uint256 _minWithdrawalAmount, + address _l1Recipient, + uint32 _gasLimit, + address _chainFeesRecipient + ) public { + // Bound inputs to valid ranges + assumeNotForgeAddress(_portal); + _assumeValidAddress(_portal); + _assumeValidAddress(_l1Recipient); + _assumeValidAddress(_chainFeesRecipient); + bound(_gasLimit, 1, type(uint32).max); + + RevShareContractsUpgrader.RevShareConfig[] memory configs = new RevShareContractsUpgrader.RevShareConfig[](1); + configs[0] = _createRevShareConfig(_portal, _minWithdrawalAmount, _l1Recipient, _gasLimit, _chainFeesRecipient); + + // Calculate expected addresses + bytes memory l1WithdrawerInitCode = bytes.concat( + RevShareLibrary.l1WithdrawerCreationCode, abi.encode(_minWithdrawalAmount, _l1Recipient, _gasLimit) + ); + address expectedL1Withdrawer = _calculateExpectedCreate2Address("L1Withdrawer", l1WithdrawerInitCode); + + bytes memory calculatorInitCode = bytes.concat( + RevShareLibrary.scRevShareCalculatorCreationCode, abi.encode(expectedL1Withdrawer, _chainFeesRecipient) + ); + address expectedCalculator = _calculateExpectedCreate2Address("SCRevShareCalculator", calculatorInitCode); + + // Mock all calls (setupRevShare deploys periphery, sets calculator, and configures vaults) + _mockAndExpectL1WithdrawerDeploy(_portal, _minWithdrawalAmount, _l1Recipient, _gasLimit); + _mockAndExpectCalculatorDeploy(_portal, expectedL1Withdrawer, _chainFeesRecipient); + _mockAndExpectFeeSplitterSetCalculator(_portal, expectedCalculator); + _mockAndExpectAllVaultSetters(_portal); + + // Execute + upgrader.setupRevShare(configs); + } + + /// @notice Fuzz test successful setupRevShare with multiple chains + function testFuzz_setupRevShare_multipleChains_succeeds(uint8 _numChains, uint256 _seed) public { + // Bound to reasonable range: 2-50 chains + _numChains = uint8(bound(_numChains, 2, 50)); + + // Setup configs array + RevShareContractsUpgrader.RevShareConfig[] memory configs = + new RevShareContractsUpgrader.RevShareConfig[](_numChains); + + // Generate random configs and setup mocks for each chain + for (uint256 i; i < _numChains; ++i) { + // Use seed + index to generate pseudo-random but deterministic values + uint256 chainSeed = uint256(keccak256(abi.encode(_seed, i))); + + // Generate random but valid addresses (non-zero) + address portal = makeAddr(string.concat("portal_", vm.toString(chainSeed))); + address l1Recipient = makeAddr(string.concat("l1recipient_", vm.toString(chainSeed))); + address chainFeeRecipient = makeAddr(string.concat("chainfee_", vm.toString(chainSeed))); + + // Generate random config values + uint256 minWithdrawalAmount = + bound(uint256(keccak256(abi.encode(chainSeed, "minwithdrawal"))), 1, type(uint256).max); + uint32 gasLimit = uint32(bound(uint256(keccak256(abi.encode(chainSeed, "gaslimit"))), 1, type(uint32).max)); + + configs[i] = _createRevShareConfig(portal, minWithdrawalAmount, l1Recipient, gasLimit, chainFeeRecipient); + + // Calculate expected addresses for this chain + bytes memory l1WithdrawerInitCode = bytes.concat( + RevShareLibrary.l1WithdrawerCreationCode, abi.encode(minWithdrawalAmount, l1Recipient, gasLimit) + ); + address expectedL1Withdrawer = _calculateExpectedCreate2Address("L1Withdrawer", l1WithdrawerInitCode); + + bytes memory calculatorInitCode = bytes.concat( + RevShareLibrary.scRevShareCalculatorCreationCode, abi.encode(expectedL1Withdrawer, chainFeeRecipient) + ); + address expectedCalculator = _calculateExpectedCreate2Address("SCRevShareCalculator", calculatorInitCode); + + // Setup mocks for this chain (setupRevShare deploys periphery, sets calculator, and configures vaults) + _mockAndExpectL1WithdrawerDeploy(portal, minWithdrawalAmount, l1Recipient, gasLimit); + _mockAndExpectCalculatorDeploy(portal, expectedL1Withdrawer, chainFeeRecipient); + _mockAndExpectFeeSplitterSetCalculator(portal, expectedCalculator); + _mockAndExpectAllVaultSetters(portal); + } + + // Execute once with all chains + upgrader.setupRevShare(configs); + } +} From 99a3551f60d61a262997c4d1e55eff488877f676 Mon Sep 17 00:00:00 2001 From: 0xDiscotech <131301107+0xDiscotech@users.noreply.github.com> Date: Tue, 11 Nov 2025 16:30:57 -0300 Subject: [PATCH 64/69] chore: add comment --- src/libraries/RevShareLibrary.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libraries/RevShareLibrary.sol b/src/libraries/RevShareLibrary.sol index 46ee584efb..fbdda60102 100644 --- a/src/libraries/RevShareLibrary.sol +++ b/src/libraries/RevShareLibrary.sol @@ -14,6 +14,7 @@ library RevShareLibrary { hex"6080604052348015600e575f80fd5b5060156019565b60c9565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff161560685760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b039081161460c65780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b610e8d806100d65f395ff3fe6080604052600436106100d1575f3560e01c806382356d8a1161007c57806385b5b14d1161005757806385b5b14d14610276578063b49dc74114610295578063d0e12f90146102b4578063d3e5792b146102e3575f80fd5b806382356d8a1461020f5780638312f1491461024d57806384411d6514610262575f80fd5b80633ccfd60b116100ac5780633ccfd60b1461016c57806354fd4d501461018e57806366d003ac146101e3575f80fd5b80630d9019e1146100dc578063307f29621461012c5780633bbed4a01461014d575f80fd5b366100d857005b5f80fd5b3480156100e7575f80fd5b5060025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b348015610137575f80fd5b5061014b610146366004610c5a565b6102f7565b005b348015610158575f80fd5b5061014b610167366004610c97565b61047a565b348015610177575f80fd5b506101806105de565b604051908152602001610123565b348015610199575f80fd5b506101d66040518060400160405280600581526020017f312e312e3000000000000000000000000000000000000000000000000000000081525081565b6040516101239190610cb2565b3480156101ee575f80fd5b506002546101029073ffffffffffffffffffffffffffffffffffffffff1681565b34801561021a575f80fd5b506002546102409074010000000000000000000000000000000000000000900460ff1681565b6040516101239190610d6b565b348015610258575f80fd5b5061018060015481565b34801561026d575f80fd5b506101805f5481565b348015610281575f80fd5b5061014b610290366004610d7f565b6108ec565b3480156102a0575f80fd5b5061014b6102af366004610d96565b610a0f565b3480156102bf575f80fd5b5060025474010000000000000000000000000000000000000000900460ff16610240565b3480156102ee575f80fd5b50600154610180565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610354573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103789190610dd1565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146103dc576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547401000000000000000000000000000000000000000080820460ff1692849290917fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff9091169083600181111561043857610438610d05565b02179055507ff2ec44eb1c3b3acd547b76333eb2c4b27eee311860c57a9fdb04c95f62398fc8818360405161046e929190610dec565b60405180910390a15050565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104fb9190610dd1565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461055f576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f62e69886a5df0ba8ffcacbfc1388754e7abd9bde24b036354c561f1acd4e4593910161046e565b5f60015447101561069c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f4665655661756c743a207769746864726177616c20616d6f756e74206d75737460448201527f2062652067726561746572207468616e206d696e696d756d207769746864726160648201527f77616c20616d6f756e7400000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b479050805f808282546106af9190610e07565b90915550506002546040805183815273ffffffffffffffffffffffffffffffffffffffff909216602083018190523383830152905190917fc8a211cc64b6ed1b50595a9fcb1932b6d1e5a6e8ef15b60e5b1f988ea9086bba919081900360600190a16002546040517f38e04cbeb8c10f8f568618aa75be0f10b6729b8b4237743b4de20cbcde2839ee916107649185918591339174010000000000000000000000000000000000000000900460ff1690610e3f565b60405180910390a1600160025474010000000000000000000000000000000000000000900460ff16600181111561079d5761079d610d05565b03610841575f6107ad8284610c23565b90508061083c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4665655661756c743a206661696c656420746f2073656e642045544820746f2060448201527f4c322066656520726563697069656e74000000000000000000000000000000006064820152608401610693565b505090565b6040517fc2b3e5ac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015262061a806024820152606060448201525f60648201527342000000000000000000000000000000000000169063c2b3e5ac9084906084015f604051808303818588803b1580156108d1575f80fd5b505af11580156108e3573d5f803e3d5ffd5b50505050505090565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610949573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061096d9190610dd1565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109d1576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180549082905560408051828152602081018490527f895a067c78583e800418fabf3da26a9496aab2ff3429cebdf7fefa642b2e4203910161046e565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f81158015610a595750825b90505f8267ffffffffffffffff166001148015610a755750303b155b905081158015610a83575080155b15610aba576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001660011785558315610b1b5784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b6002805473ffffffffffffffffffffffffffffffffffffffff8a167fffffffffffffffffffffffff000000000000000000000000000000000000000082168117835560018a81558993927fffffffffffffffffffffff000000000000000000000000000000000000000000169091179074010000000000000000000000000000000000000000908490811115610bb357610bb3610d05565b02179055508315610c195784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050565b5f610c2f835a84610c36565b9392505050565b5f805f805f858888f1949350505050565b803560028110610c55575f80fd5b919050565b5f60208284031215610c6a575f80fd5b610c2f82610c47565b73ffffffffffffffffffffffffffffffffffffffff81168114610c94575f80fd5b50565b5f60208284031215610ca7575f80fd5b8135610c2f81610c73565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60028110610d67577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b9052565b60208101610d798284610d32565b92915050565b5f60208284031215610d8f575f80fd5b5035919050565b5f805f60608486031215610da8575f80fd5b8335610db381610c73565b925060208401359150610dc860408501610c47565b90509250925092565b5f60208284031215610de1575f80fd5b8151610c2f81610c73565b60408101610dfa8285610d32565b610c2f6020830184610d32565b80820180821115610d79577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b84815273ffffffffffffffffffffffffffffffffffffffff84811660208301528316604082015260808101610e776060830184610d32565b9594505050505056fea164736f6c6343000819000a"; bytes public constant sequencerFeeVaultCreationCode = hex"6080604052348015600e575f80fd5b5060156019565b60c9565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff161560685760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b039081161460c65780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b610e98806100d65f395ff3fe6080604052600436106100dc575f3560e01c80638312f1491161007c578063b49dc74111610057578063b49dc741146102a0578063d0e12f90146102bf578063d3e5792b146102ee578063d4ff9218146100e7575f80fd5b80638312f1491461025857806384411d651461026d57806385b5b14d14610281575f80fd5b80633ccfd60b116100b75780633ccfd60b1461017757806354fd4d501461019957806366d003ac146101ee57806382356d8a1461021a575f80fd5b80630d9019e1146100e7578063307f2962146101375780633bbed4a014610158575f80fd5b366100e357005b5f80fd5b3480156100f2575f80fd5b5060025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b348015610142575f80fd5b50610156610151366004610c65565b610302565b005b348015610163575f80fd5b50610156610172366004610ca2565b610485565b348015610182575f80fd5b5061018b6105e9565b60405190815260200161012e565b3480156101a4575f80fd5b506101e16040518060400160405280600581526020017f312e362e3000000000000000000000000000000000000000000000000000000081525081565b60405161012e9190610cbd565b3480156101f9575f80fd5b5060025461010d9073ffffffffffffffffffffffffffffffffffffffff1681565b348015610225575f80fd5b5060025461024b9074010000000000000000000000000000000000000000900460ff1681565b60405161012e9190610d76565b348015610263575f80fd5b5061018b60015481565b348015610278575f80fd5b5061018b5f5481565b34801561028c575f80fd5b5061015661029b366004610d8a565b6108f7565b3480156102ab575f80fd5b506101566102ba366004610da1565b610a1a565b3480156102ca575f80fd5b5060025474010000000000000000000000000000000000000000900460ff1661024b565b3480156102f9575f80fd5b5060015461018b565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561035f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103839190610ddc565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146103e7576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547401000000000000000000000000000000000000000080820460ff1692849290917fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff9091169083600181111561044357610443610d10565b02179055507ff2ec44eb1c3b3acd547b76333eb2c4b27eee311860c57a9fdb04c95f62398fc88183604051610479929190610df7565b60405180910390a15050565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104e2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105069190610ddc565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461056a576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f62e69886a5df0ba8ffcacbfc1388754e7abd9bde24b036354c561f1acd4e45939101610479565b5f6001544710156106a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f4665655661756c743a207769746864726177616c20616d6f756e74206d75737460448201527f2062652067726561746572207468616e206d696e696d756d207769746864726160648201527f77616c20616d6f756e7400000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b479050805f808282546106ba9190610e12565b90915550506002546040805183815273ffffffffffffffffffffffffffffffffffffffff909216602083018190523383830152905190917fc8a211cc64b6ed1b50595a9fcb1932b6d1e5a6e8ef15b60e5b1f988ea9086bba919081900360600190a16002546040517f38e04cbeb8c10f8f568618aa75be0f10b6729b8b4237743b4de20cbcde2839ee9161076f9185918591339174010000000000000000000000000000000000000000900460ff1690610e4a565b60405180910390a1600160025474010000000000000000000000000000000000000000900460ff1660018111156107a8576107a8610d10565b0361084c575f6107b88284610c2e565b905080610847576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4665655661756c743a206661696c656420746f2073656e642045544820746f2060448201527f4c322066656520726563697069656e7400000000000000000000000000000000606482015260840161069e565b505090565b6040517fc2b3e5ac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015262061a806024820152606060448201525f60648201527342000000000000000000000000000000000000169063c2b3e5ac9084906084015f604051808303818588803b1580156108dc575f80fd5b505af11580156108ee573d5f803e3d5ffd5b50505050505090565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610954573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109789190610ddc565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109dc576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180549082905560408051828152602081018490527f895a067c78583e800418fabf3da26a9496aab2ff3429cebdf7fefa642b2e42039101610479565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f81158015610a645750825b90505f8267ffffffffffffffff166001148015610a805750303b155b905081158015610a8e575080155b15610ac5576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001660011785558315610b265784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b6002805473ffffffffffffffffffffffffffffffffffffffff8a167fffffffffffffffffffffffff000000000000000000000000000000000000000082168117835560018a81558993927fffffffffffffffffffffff000000000000000000000000000000000000000000169091179074010000000000000000000000000000000000000000908490811115610bbe57610bbe610d10565b02179055508315610c245784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050565b5f610c3a835a84610c41565b9392505050565b5f805f805f858888f1949350505050565b803560028110610c60575f80fd5b919050565b5f60208284031215610c75575f80fd5b610c3a82610c52565b73ffffffffffffffffffffffffffffffffffffffff81168114610c9f575f80fd5b50565b5f60208284031215610cb2575f80fd5b8135610c3a81610c7e565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60028110610d72577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b9052565b60208101610d848284610d3d565b92915050565b5f60208284031215610d9a575f80fd5b5035919050565b5f805f60608486031215610db3575f80fd5b8335610dbe81610c7e565b925060208401359150610dd360408501610c52565b90509250925092565b5f60208284031215610dec575f80fd5b8151610c3a81610c7e565b60408101610e058285610d3d565b610c3a6020830184610d3d565b80820180821115610d84577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b84815273ffffffffffffffffffffffffffffffffffffffff84811660208301528316604082015260808101610e826060830184610d3d565b9594505050505056fea164736f6c6343000819000a"; + /// @notice Both `L1FeeVault` and `BaseFeeVault` share the exact same creation code. bytes public constant defaultFeeVaultCreationCode = hex"6080604052348015600e575f80fd5b5060156019565b60c9565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff161560685760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b039081161460c65780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b610e8d806100d65f395ff3fe6080604052600436106100d1575f3560e01c806382356d8a1161007c57806385b5b14d1161005757806385b5b14d14610276578063b49dc74114610295578063d0e12f90146102b4578063d3e5792b146102e3575f80fd5b806382356d8a1461020f5780638312f1491461024d57806384411d6514610262575f80fd5b80633ccfd60b116100ac5780633ccfd60b1461016c57806354fd4d501461018e57806366d003ac146101e3575f80fd5b80630d9019e1146100dc578063307f29621461012c5780633bbed4a01461014d575f80fd5b366100d857005b5f80fd5b3480156100e7575f80fd5b5060025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b348015610137575f80fd5b5061014b610146366004610c5a565b6102f7565b005b348015610158575f80fd5b5061014b610167366004610c97565b61047a565b348015610177575f80fd5b506101806105de565b604051908152602001610123565b348015610199575f80fd5b506101d66040518060400160405280600581526020017f312e362e3000000000000000000000000000000000000000000000000000000081525081565b6040516101239190610cb2565b3480156101ee575f80fd5b506002546101029073ffffffffffffffffffffffffffffffffffffffff1681565b34801561021a575f80fd5b506002546102409074010000000000000000000000000000000000000000900460ff1681565b6040516101239190610d6b565b348015610258575f80fd5b5061018060015481565b34801561026d575f80fd5b506101805f5481565b348015610281575f80fd5b5061014b610290366004610d7f565b6108ec565b3480156102a0575f80fd5b5061014b6102af366004610d96565b610a0f565b3480156102bf575f80fd5b5060025474010000000000000000000000000000000000000000900460ff16610240565b3480156102ee575f80fd5b50600154610180565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610354573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103789190610dd1565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146103dc576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547401000000000000000000000000000000000000000080820460ff1692849290917fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff9091169083600181111561043857610438610d05565b02179055507ff2ec44eb1c3b3acd547b76333eb2c4b27eee311860c57a9fdb04c95f62398fc8818360405161046e929190610dec565b60405180910390a15050565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104fb9190610dd1565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461055f576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f62e69886a5df0ba8ffcacbfc1388754e7abd9bde24b036354c561f1acd4e4593910161046e565b5f60015447101561069c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f4665655661756c743a207769746864726177616c20616d6f756e74206d75737460448201527f2062652067726561746572207468616e206d696e696d756d207769746864726160648201527f77616c20616d6f756e7400000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b479050805f808282546106af9190610e07565b90915550506002546040805183815273ffffffffffffffffffffffffffffffffffffffff909216602083018190523383830152905190917fc8a211cc64b6ed1b50595a9fcb1932b6d1e5a6e8ef15b60e5b1f988ea9086bba919081900360600190a16002546040517f38e04cbeb8c10f8f568618aa75be0f10b6729b8b4237743b4de20cbcde2839ee916107649185918591339174010000000000000000000000000000000000000000900460ff1690610e3f565b60405180910390a1600160025474010000000000000000000000000000000000000000900460ff16600181111561079d5761079d610d05565b03610841575f6107ad8284610c23565b90508061083c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4665655661756c743a206661696c656420746f2073656e642045544820746f2060448201527f4c322066656520726563697069656e74000000000000000000000000000000006064820152608401610693565b505090565b6040517fc2b3e5ac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015262061a806024820152606060448201525f60648201527342000000000000000000000000000000000000169063c2b3e5ac9084906084015f604051808303818588803b1580156108d1575f80fd5b505af11580156108e3573d5f803e3d5ffd5b50505050505090565b73420000000000000000000000000000000000001873ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610949573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061096d9190610dd1565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109d1576040517f7cd7e09f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180549082905560408051828152602081018490527f895a067c78583e800418fabf3da26a9496aab2ff3429cebdf7fefa642b2e4203910161046e565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f81158015610a595750825b90505f8267ffffffffffffffff166001148015610a755750303b155b905081158015610a83575080155b15610aba576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001660011785558315610b1b5784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b6002805473ffffffffffffffffffffffffffffffffffffffff8a167fffffffffffffffffffffffff000000000000000000000000000000000000000082168117835560018a81558993927fffffffffffffffffffffff000000000000000000000000000000000000000000169091179074010000000000000000000000000000000000000000908490811115610bb357610bb3610d05565b02179055508315610c195784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050565b5f610c2f835a84610c36565b9392505050565b5f805f805f858888f1949350505050565b803560028110610c55575f80fd5b919050565b5f60208284031215610c6a575f80fd5b610c2f82610c47565b73ffffffffffffffffffffffffffffffffffffffff81168114610c94575f80fd5b50565b5f60208284031215610ca7575f80fd5b8135610c2f81610c73565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60028110610d67577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b9052565b60208101610d798284610d32565b92915050565b5f60208284031215610d8f575f80fd5b5035919050565b5f805f60608486031215610da8575f80fd5b8335610db381610c73565b925060208401359150610dc860408501610c47565b90509250925092565b5f60208284031215610de1575f80fd5b8151610c2f81610c73565b60408101610dfa8285610d32565b610c2f6020830184610d32565b80820180821115610d79577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b84815273ffffffffffffffffffffffffffffffffffffffff84811660208301528316604082015260808101610e776060830184610d32565b9594505050505056fea164736f6c6343000819000a"; bytes public constant feeSplitterCreationCode = From b532af61764c26a8fcc4da7e351d0d797f292479 Mon Sep 17 00:00:00 2001 From: Disco <131301107+0xDiscotech@users.noreply.github.com> Date: Tue, 11 Nov 2025 19:07:31 -0300 Subject: [PATCH 65/69] feat: add check and interface (#56) --- src/RevShareContractsUpgrader.sol | 5 ++++ src/interfaces/IRevShareContractsUpgrader.sol | 25 +++++++++++++++++++ .../RevShareContractsUpgrader.t.sol | 22 ++++++++++++++-- 3 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 src/interfaces/IRevShareContractsUpgrader.sol diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol index 889775934e..2604daa24b 100644 --- a/src/RevShareContractsUpgrader.sol +++ b/src/RevShareContractsUpgrader.sol @@ -30,6 +30,9 @@ contract RevShareContractsUpgrader { /// @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(); @@ -64,6 +67,7 @@ contract RevShareContractsUpgrader { 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 = @@ -111,6 +115,7 @@ contract RevShareContractsUpgrader { 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 = diff --git a/src/interfaces/IRevShareContractsUpgrader.sol b/src/interfaces/IRevShareContractsUpgrader.sol new file mode 100644 index 0000000000..6a63c9ffa9 --- /dev/null +++ b/src/interfaces/IRevShareContractsUpgrader.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface IRevShareContractsUpgrader { + error PortalCannotBeZeroAddress(); + error L1WithdrawerRecipientCannotBeZeroAddress(); + error ChainFeesRecipientCannotBeZeroAddress(); + error GasLimitCannotBeZero(); + error EmptyArray(); + + 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; +} diff --git a/test/template/revenue-share-upgrade-path/RevShareContractsUpgrader.t.sol b/test/template/revenue-share-upgrade-path/RevShareContractsUpgrader.t.sol index 4bd823e9ef..749c629354 100644 --- a/test/template/revenue-share-upgrade-path/RevShareContractsUpgrader.t.sol +++ b/test/template/revenue-share-upgrade-path/RevShareContractsUpgrader.t.sol @@ -400,6 +400,15 @@ contract RevShareContractsUpgrader_UpgradeAndSetupRevShare_Test is RevShareContr upgrader.upgradeAndSetupRevShare(configs); } + /// @notice Test that upgradeAndSetupRevShare reverts when gas limit is zero + function test_upgradeAndSetupRevShare_whenGasLimitIsZero_reverts() public { + RevShareContractsUpgrader.RevShareConfig[] memory configs = new RevShareContractsUpgrader.RevShareConfig[](1); + configs[0] = _createRevShareConfig(PORTAL_ONE, MIN_WITHDRAWAL_AMOUNT, L1_RECIPIENT_ONE, 0, CHAIN_FEES_RECIPIENT_ONE); + + vm.expectRevert(RevShareContractsUpgrader.GasLimitCannotBeZero.selector); + upgrader.upgradeAndSetupRevShare(configs); + } + /// @notice Fuzz test successful upgradeAndSetupRevShare with single chain function testFuzz_upgradeAndSetupRevShare_singleChain_succeeds( address _portal, @@ -412,7 +421,7 @@ contract RevShareContractsUpgrader_UpgradeAndSetupRevShare_Test is RevShareContr _assumeValidAddress(_portal); _assumeValidAddress(_l1Recipient); _assumeValidAddress(_chainFeesRecipient); - bound(_gasLimit, 1, type(uint32).max); + _gasLimit = uint32(bound(_gasLimit, 1, type(uint32).max)); RevShareContractsUpgrader.RevShareConfig[] memory configs = new RevShareContractsUpgrader.RevShareConfig[](1); configs[0] = _createRevShareConfig(_portal, _minWithdrawalAmount, _l1Recipient, _gasLimit, _chainFeesRecipient); @@ -529,6 +538,15 @@ contract RevShareContractsUpgrader_SetupRevShare_Test is RevShareContractsUpgrad upgrader.setupRevShare(configs); } + /// @notice Test that setupRevShare reverts when gas limit is zero + function test_setupRevShare_whenGasLimitIsZero_reverts() public { + RevShareContractsUpgrader.RevShareConfig[] memory configs = new RevShareContractsUpgrader.RevShareConfig[](1); + configs[0] = _createRevShareConfig(PORTAL_ONE, MIN_WITHDRAWAL_AMOUNT, L1_RECIPIENT_ONE, 0, CHAIN_FEES_RECIPIENT_ONE); + + vm.expectRevert(RevShareContractsUpgrader.GasLimitCannotBeZero.selector); + upgrader.setupRevShare(configs); + } + /// @notice Fuzz test successful setupRevShare with single chain function testFuzz_setupRevShare_singleChain_succeeds( address _portal, @@ -542,7 +560,7 @@ contract RevShareContractsUpgrader_SetupRevShare_Test is RevShareContractsUpgrad _assumeValidAddress(_portal); _assumeValidAddress(_l1Recipient); _assumeValidAddress(_chainFeesRecipient); - bound(_gasLimit, 1, type(uint32).max); + _gasLimit = uint32(bound(_gasLimit, 1, type(uint32).max)); RevShareContractsUpgrader.RevShareConfig[] memory configs = new RevShareContractsUpgrader.RevShareConfig[](1); configs[0] = _createRevShareConfig(_portal, _minWithdrawalAmount, _l1Recipient, _gasLimit, _chainFeesRecipient); From ad2dc9d506b8a52e18f23f08c4e5481fcadf97a7 Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Tue, 11 Nov 2025 19:11:58 -0300 Subject: [PATCH 66/69] chore: fix gas costs --- src/libraries/RevShareLibrary.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libraries/RevShareLibrary.sol b/src/libraries/RevShareLibrary.sol index fbdda60102..c91fdb3617 100644 --- a/src/libraries/RevShareLibrary.sol +++ b/src/libraries/RevShareLibrary.sol @@ -33,8 +33,8 @@ library RevShareLibrary { /// - SC Rev Share Calculator deployment: 579,688 /// - Fee Vaults deployment: ~831,000 /// - Fee Splitter deployment: 1,121,747 - /// - upgrade: ~48,000 - /// - setters: ~50,000 + /// - Splitter upgrade: 72,913 + /// - Vaults upgrades: ~55,000 /// The gas limits below include a buffer to ensure successful execution. /// @notice The gas limit for the SC Rev Share Calculator deployment. From f2d108bc798ec1cf1cdd47c0bfa327cf5cf0f2ff Mon Sep 17 00:00:00 2001 From: 0xchin <77933451+0xChin@users.noreply.github.com> Date: Tue, 11 Nov 2025 19:12:31 -0300 Subject: [PATCH 67/69] chore: undo wrong changes --- src/libraries/RevShareLibrary.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libraries/RevShareLibrary.sol b/src/libraries/RevShareLibrary.sol index c91fdb3617..fbdda60102 100644 --- a/src/libraries/RevShareLibrary.sol +++ b/src/libraries/RevShareLibrary.sol @@ -33,8 +33,8 @@ library RevShareLibrary { /// - SC Rev Share Calculator deployment: 579,688 /// - Fee Vaults deployment: ~831,000 /// - Fee Splitter deployment: 1,121,747 - /// - Splitter upgrade: 72,913 - /// - Vaults upgrades: ~55,000 + /// - upgrade: ~48,000 + /// - setters: ~50,000 /// The gas limits below include a buffer to ensure successful execution. /// @notice The gas limit for the SC Rev Share Calculator deployment. From 1bdc2367da27f99b086762d0a45599518de1fa17 Mon Sep 17 00:00:00 2001 From: Chiin <77933451+0xChin@users.noreply.github.com> Date: Tue, 11 Nov 2025 19:18:42 -0300 Subject: [PATCH 68/69] chore: update gas limits (#57) --- src/libraries/RevShareLibrary.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libraries/RevShareLibrary.sol b/src/libraries/RevShareLibrary.sol index fbdda60102..c91fdb3617 100644 --- a/src/libraries/RevShareLibrary.sol +++ b/src/libraries/RevShareLibrary.sol @@ -33,8 +33,8 @@ library RevShareLibrary { /// - SC Rev Share Calculator deployment: 579,688 /// - Fee Vaults deployment: ~831,000 /// - Fee Splitter deployment: 1,121,747 - /// - upgrade: ~48,000 - /// - setters: ~50,000 + /// - Splitter upgrade: 72,913 + /// - Vaults upgrades: ~55,000 /// The gas limits below include a buffer to ensure successful execution. /// @notice The gas limit for the SC Rev Share Calculator deployment. From ce3936c6fe0d093d9b707c14aeb6a8c9d22fc56e Mon Sep 17 00:00:00 2001 From: Disco <131301107+0xDiscotech@users.noreply.github.com> Date: Tue, 11 Nov 2025 19:34:00 -0300 Subject: [PATCH 69/69] feat: add chain processed event (#58) --- src/RevShareContractsUpgrader.sol | 9 +++++++ src/interfaces/IRevShareContractsUpgrader.sol | 2 ++ .../RevShareContractsUpgrader.t.sol | 25 +++++++++++++++++-- 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/RevShareContractsUpgrader.sol b/src/RevShareContractsUpgrader.sol index 2604daa24b..9dccd26703 100644 --- a/src/RevShareContractsUpgrader.sol +++ b/src/RevShareContractsUpgrader.sol @@ -36,6 +36,11 @@ contract RevShareContractsUpgrader { /// @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 @@ -101,6 +106,8 @@ contract RevShareContractsUpgrader { // Upgrade all 4 vaults with RevShare configuration (recipient=FeeSplitter, minWithdrawal=0, network=L2) _upgradeVaultsWithRevShareConfig(config.portal); + + emit ChainProcessed(config.portal, i); } } @@ -131,6 +138,8 @@ contract RevShareContractsUpgrader { // Configure all 4 vaults for revenue sharing _configureVaultsForRevShare(config.portal); + + emit ChainProcessed(config.portal, i); } } diff --git a/src/interfaces/IRevShareContractsUpgrader.sol b/src/interfaces/IRevShareContractsUpgrader.sol index 6a63c9ffa9..4f5f04833f 100644 --- a/src/interfaces/IRevShareContractsUpgrader.sol +++ b/src/interfaces/IRevShareContractsUpgrader.sol @@ -8,6 +8,8 @@ interface IRevShareContractsUpgrader { error GasLimitCannotBeZero(); error EmptyArray(); + event ChainProcessed(address portal, uint256 chainIndex); + struct L1WithdrawerConfig { uint256 minWithdrawalAmount; address recipient; diff --git a/test/template/revenue-share-upgrade-path/RevShareContractsUpgrader.t.sol b/test/template/revenue-share-upgrade-path/RevShareContractsUpgrader.t.sol index 749c629354..d669822d69 100644 --- a/test/template/revenue-share-upgrade-path/RevShareContractsUpgrader.t.sol +++ b/test/template/revenue-share-upgrade-path/RevShareContractsUpgrader.t.sol @@ -21,6 +21,9 @@ import {IFeeVault} from "src/interfaces/IFeeVault.sol"; /// @title RevShareContractsUpgrader_TestInit /// @notice Base test contract with shared setup and helpers for RevShareContractsUpgrader tests. contract RevShareContractsUpgrader_TestInit is Test { + // Events + event ChainProcessed(address portal, uint256 chainIndex); + // Contract under test RevShareContractsUpgrader internal upgrader; @@ -403,7 +406,8 @@ contract RevShareContractsUpgrader_UpgradeAndSetupRevShare_Test is RevShareContr /// @notice Test that upgradeAndSetupRevShare reverts when gas limit is zero function test_upgradeAndSetupRevShare_whenGasLimitIsZero_reverts() public { RevShareContractsUpgrader.RevShareConfig[] memory configs = new RevShareContractsUpgrader.RevShareConfig[](1); - configs[0] = _createRevShareConfig(PORTAL_ONE, MIN_WITHDRAWAL_AMOUNT, L1_RECIPIENT_ONE, 0, CHAIN_FEES_RECIPIENT_ONE); + configs[0] = + _createRevShareConfig(PORTAL_ONE, MIN_WITHDRAWAL_AMOUNT, L1_RECIPIENT_ONE, 0, CHAIN_FEES_RECIPIENT_ONE); vm.expectRevert(RevShareContractsUpgrader.GasLimitCannotBeZero.selector); upgrader.upgradeAndSetupRevShare(configs); @@ -444,6 +448,10 @@ contract RevShareContractsUpgrader_UpgradeAndSetupRevShare_Test is RevShareContr _mockAndExpectFeeSplitterDeployAndSetup(_portal, expectedCalculator); _mockAndExpectAllVaultUpgrades(_portal); + // Expect event + vm.expectEmit(address(upgrader)); + emit ChainProcessed(_portal, 0); + // Execute upgrader.upgradeAndSetupRevShare(configs); } @@ -490,6 +498,10 @@ contract RevShareContractsUpgrader_UpgradeAndSetupRevShare_Test is RevShareContr _mockAndExpectCalculatorDeploy(portal, expectedL1Withdrawer, chainFeeRecipient); _mockAndExpectFeeSplitterDeployAndSetup(portal, expectedCalculator); _mockAndExpectAllVaultUpgrades(portal); + + // Expect event for this chain + vm.expectEmit(address(upgrader)); + emit ChainProcessed(portal, i); } // Execute once with all chains @@ -541,7 +553,8 @@ contract RevShareContractsUpgrader_SetupRevShare_Test is RevShareContractsUpgrad /// @notice Test that setupRevShare reverts when gas limit is zero function test_setupRevShare_whenGasLimitIsZero_reverts() public { RevShareContractsUpgrader.RevShareConfig[] memory configs = new RevShareContractsUpgrader.RevShareConfig[](1); - configs[0] = _createRevShareConfig(PORTAL_ONE, MIN_WITHDRAWAL_AMOUNT, L1_RECIPIENT_ONE, 0, CHAIN_FEES_RECIPIENT_ONE); + configs[0] = + _createRevShareConfig(PORTAL_ONE, MIN_WITHDRAWAL_AMOUNT, L1_RECIPIENT_ONE, 0, CHAIN_FEES_RECIPIENT_ONE); vm.expectRevert(RevShareContractsUpgrader.GasLimitCannotBeZero.selector); upgrader.setupRevShare(configs); @@ -582,6 +595,10 @@ contract RevShareContractsUpgrader_SetupRevShare_Test is RevShareContractsUpgrad _mockAndExpectFeeSplitterSetCalculator(_portal, expectedCalculator); _mockAndExpectAllVaultSetters(_portal); + // Expect event + vm.expectEmit(address(upgrader)); + emit ChainProcessed(_portal, 0); + // Execute upgrader.setupRevShare(configs); } @@ -628,6 +645,10 @@ contract RevShareContractsUpgrader_SetupRevShare_Test is RevShareContractsUpgrad _mockAndExpectCalculatorDeploy(portal, expectedL1Withdrawer, chainFeeRecipient); _mockAndExpectFeeSplitterSetCalculator(portal, expectedCalculator); _mockAndExpectAllVaultSetters(portal); + + // Expect event for this chain + vm.expectEmit(address(upgrader)); + emit ChainProcessed(portal, i); } // Execute once with all chains